Author: Rashmi Mudduluru Date: 2023-06-21T15:54:09-07:00 New Revision: db3dcedb9cedcec4a9570fda7406490c642df8ae
URL: https://github.com/llvm/llvm-project/commit/db3dcedb9cedcec4a9570fda7406490c642df8ae DIFF: https://github.com/llvm/llvm-project/commit/db3dcedb9cedcec4a9570fda7406490c642df8ae.diff LOG: [-Wunsafe-buffer-usage] Handle pointer initializations for grouping related variables Differential Revision: https://reviews.llvm.org/D150489 Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 57d9dcc5bdcb7..ff687a0d178bd 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -37,6 +37,7 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '&DRE[any]' in an Unspecified Poin FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement) // '++Ptr' in an Unspecified Pointer Context FIXABLE_GADGET(PointerAssignment) +FIXABLE_GADGET(PointerInit) #undef FIXABLE_GADGET #undef WARNING_GADGET diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 49229a6b56c1c..aa29fb45726a8 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -533,23 +533,66 @@ class PointerArithmeticGadget : public WarningGadget { // FIXME: this gadge will need a fix-it }; +/// A pointer initialization expression of the form: +/// \code +/// int *p = q; +/// \endcode +class PointerInitGadget : public FixableGadget { +private: + static constexpr const char *const PointerInitLHSTag = "ptrInitLHS"; + static constexpr const char *const PointerInitRHSTag = "ptrInitRHS"; + const VarDecl * PtrInitLHS; // the LHS pointer expression in `PI` + const DeclRefExpr * PtrInitRHS; // the RHS pointer expression in `PI` + +public: + PointerInitGadget(const MatchFinder::MatchResult &Result) + : FixableGadget(Kind::PointerInit), + PtrInitLHS(Result.Nodes.getNodeAs<VarDecl>(PointerInitLHSTag)), + PtrInitRHS(Result.Nodes.getNodeAs<DeclRefExpr>(PointerInitRHSTag)) {} + + static bool classof(const Gadget *G) { + return G->getKind() == Kind::PointerInit; + } + + static Matcher matcher() { + auto PtrInitStmt = declStmt(hasSingleDecl(varDecl( + hasInitializer(ignoringImpCasts(declRefExpr( + hasPointerType()). + bind(PointerInitRHSTag)))). + bind(PointerInitLHSTag))); + + return stmt(PtrInitStmt); + } + + virtual std::optional<FixItList> getFixits(const Strategy &S) const override; + + virtual const Stmt *getBaseStmt() const override { return nullptr; } + + virtual DeclUseList getClaimedVarUseSites() const override { + return DeclUseList{PtrInitRHS}; + } + + virtual std::optional<std::pair<const VarDecl *, const VarDecl *>> + getStrategyImplications() const override { + return std::make_pair(PtrInitLHS, + cast<VarDecl>(PtrInitRHS->getDecl())); + } +}; + /// A pointer assignment expression of the form: /// \code /// p = q; /// \endcode class PointerAssignmentGadget : public FixableGadget { private: - static constexpr const char *const PointerAssignmentTag = "ptrAssign"; static constexpr const char *const PointerAssignLHSTag = "ptrLHS"; static constexpr const char *const PointerAssignRHSTag = "ptrRHS"; - const BinaryOperator *PA; // pointer arithmetic expression const DeclRefExpr * PtrLHS; // the LHS pointer expression in `PA` const DeclRefExpr * PtrRHS; // the RHS pointer expression in `PA` public: PointerAssignmentGadget(const MatchFinder::MatchResult &Result) : FixableGadget(Kind::PointerAssignment), - PA(Result.Nodes.getNodeAs<BinaryOperator>(PointerAssignmentTag)), PtrLHS(Result.Nodes.getNodeAs<DeclRefExpr>(PointerAssignLHSTag)), PtrRHS(Result.Nodes.getNodeAs<DeclRefExpr>(PointerAssignRHSTag)) {} @@ -566,13 +609,12 @@ class PointerAssignmentGadget : public FixableGadget { to(varDecl())). bind(PointerAssignLHSTag)))); - //FIXME: Handle declarations at assignments return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr)); } virtual std::optional<FixItList> getFixits(const Strategy &S) const override; - virtual const Stmt *getBaseStmt() const override { return PA; } + virtual const Stmt *getBaseStmt() const override { return nullptr; } virtual DeclUseList getClaimedVarUseSites() const override { return DeclUseList{PtrLHS, PtrRHS}; @@ -769,8 +811,8 @@ class UPCAddressofArraySubscriptGadget : public FixableGadget { namespace { // An auxiliary tracking facility for the fixit analysis. It helps connect -// declarations to its and make sure we've covered all uses with our analysis -// before we try to fix the declaration. +// declarations to its uses and make sure we've covered all uses with our +// analysis before we try to fix the declaration. class DeclUseTracker { using UseSetTy = SmallSet<const DeclRefExpr *, 16>; using DefMapTy = DenseMap<const VarDecl *, const DeclStmt *>; @@ -1174,6 +1216,24 @@ PointerAssignmentGadget::getFixits(const Strategy &S) const { return std::nullopt; } +std::optional<FixItList> +PointerInitGadget::getFixits(const Strategy &S) const { + const auto *LeftVD = PtrInitLHS; + const auto *RightVD = cast<VarDecl>(PtrInitRHS->getDecl()); + switch (S.lookup(LeftVD)) { + case Strategy::Kind::Span: + if (S.lookup(RightVD) == Strategy::Kind::Span) + return FixItList{}; + return std::nullopt; + case Strategy::Kind::Wontfix: + return std::nullopt; + case Strategy::Kind::Iterator: + case Strategy::Kind::Array: + case Strategy::Kind::Vector: + llvm_unreachable("unsupported strategies for FixableGadgets"); + } + return std::nullopt; +} std::optional<FixItList> ULCArraySubscriptGadget::getFixits(const Strategy &S) const { @@ -2020,10 +2080,10 @@ static bool overlapWithMacro(const FixItList &FixIts) { }); } -static bool impossibleToFixForVar(const FixableGadgetSets &FixablesForUnsafeVars, +static bool impossibleToFixForVar(const FixableGadgetSets &FixablesForAllVars, const Strategy &S, const VarDecl * Var) { - for (const auto &F : FixablesForUnsafeVars.byVar.find(Var)->second) { + for (const auto &F : FixablesForAllVars.byVar.find(Var)->second) { std::optional<FixItList> Fixits = F->getFixits(S); if (!Fixits) { return true; @@ -2033,13 +2093,13 @@ static bool impossibleToFixForVar(const FixableGadgetSets &FixablesForUnsafeVars } static std::map<const VarDecl *, FixItList> -getFixIts(FixableGadgetSets &FixablesForUnsafeVars, const Strategy &S, +getFixIts(FixableGadgetSets &FixablesForAllVars, const Strategy &S, ASTContext &Ctx, /* The function decl under analysis */ const Decl *D, const DeclUseTracker &Tracker, UnsafeBufferUsageHandler &Handler, const DefMapTy &VarGrpMap) { std::map<const VarDecl *, FixItList> FixItsForVariable; - for (const auto &[VD, Fixables] : FixablesForUnsafeVars.byVar) { + for (const auto &[VD, Fixables] : FixablesForAllVars.byVar) { FixItsForVariable[VD] = fixVariable(VD, S.lookup(VD), D, Tracker, Ctx, Handler); // If we fail to produce Fix-It for the declaration we have to skip the @@ -2073,7 +2133,7 @@ getFixIts(FixableGadgetSets &FixablesForUnsafeVars, const Strategy &S, if (V == VD) { continue; } - if (impossibleToFixForVar(FixablesForUnsafeVars, S, V)) { + if (impossibleToFixForVar(FixablesForAllVars, S, V)) { ImpossibleToFix = true; break; } diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp new file mode 100644 index 0000000000000..e29ac7fa8fcb3 --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init-fixits.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN: -fsafe-buffer-usage-suggestions \ +// RUN: -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +void lhs_span_multi_assign() { + int *a = new int[2]; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> a" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 2}" + int *b = a; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> b" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + int *c = b; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> c" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + int *d = c; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> d" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + int tmp = d[2]; // expected-note{{used in buffer access here}} +} + +void rhs_span1() { + int *q = new int[12]; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 12}" + int *p = q; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + p[5] = 10; + int *r = q; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + r[10] = 5; // expected-note{{used in buffer access here}} +} + +void rhs_span2() { + int *q = new int[6]; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 6}" + int *p = q; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> p" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + p[5] = 10; // expected-note{{used in buffer access here}} +} + +void rhs_span3() { + int *q = new int[6]; + int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} + p[5] = 10; // expected-note{{used in buffer access here}} + int *r = q; +} + +void test_grouping() { + int *z = new int[8]; + int tmp; + int *y = new int[10]; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> y" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}" + tmp = y[5]; + + int *x = new int[10]; + x = y; + + int *w = z; +} + +void test_crash() { + int *r = new int[8]; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 8}" + int *q = r; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> q" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + int *p; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span<int> p" + p = q; + int tmp = p[9]; // expected-note{{used in buffer access here}} +} diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp new file mode 100644 index 0000000000000..2fec417aafa8c --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-ptr-init.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions -verify %s + +void lhs_span_multi_assign() { + int *a = new int[2]; + int *b = a; + int *c = b; + int *d = c; // expected-warning{{'d' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'd' to 'std::span' to preserve bounds information, and change ('a', 'b', and 'c'|'a', 'c', and 'b'|'b', 'a', and 'c'|'b', 'c', and 'a'|'c', 'a', and 'b'|'c', 'b', and 'a') to 'std::span' to propagate bounds information between them$}}}} + int tmp = d[2]; // expected-note{{used in buffer access here}} +} + +void rhs_span1() { + int *q = new int[12]; + int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change ('q' and 'r'|'r' and 'q') to 'std::span' to propagate bounds information between them$}}}} + p[5] = 10; // expected-note{{used in buffer access here}} + int *r = q; // expected-warning{{'r' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'r' to 'std::span' to preserve bounds information, and change ('p' and 'q'|'q' and 'p') to 'std::span' to propagate bounds information between them$}}}} + r[10] = 5; // expected-note{{used in buffer access here}} +} + +void rhs_span2() { + int *q = new int[6]; + int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change 'q' to 'std::span' to propagate bounds information between them$}}}} + p[5] = 10; // expected-note{{used in buffer access here}} +} + +// FIXME: Suggest fixits for p, q, and r since span a valid fixit for r. +void rhs_span3() { + int *q = new int[6]; + int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} + p[5] = 10; // expected-note{{used in buffer access here}} + int *r = q; +} + +void test_grouping() { + int *z = new int[8]; + int tmp; + int *y = new int[10]; // expected-warning{{'y' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'y' to 'std::span' to preserve bounds information$}}}} + tmp = y[5]; // expected-note{{used in buffer access here}} + + int *x = new int[10]; + x = y; + + int *w = z; +} + +void test_crash() { + int *r = new int[8]; + int *q = r; + int *p; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change ('r' and 'q'|'q' and 'r') to 'std::span' to propagate bounds information between them$}}}} + p = q; + int tmp = p[9]; // expected-note{{used in buffer access here}} +} diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp index 0c5716ba19478..6c867fe8a3204 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc-fixits.cpp @@ -48,6 +48,21 @@ void uuc_if_body1(bool flag) { p[5] = 4; } +void uuc_if_body2_ptr_init(bool flag) { + int *r = new int[7]; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span<int> r" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", 7}" + if (flag) { + } else { + int* p = r; + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:13}:"std::span<int> p" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"{" + // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:15-[[@LINE-3]]:15}:", <# placeholder #>}" + p[5] = 4; + } +} + void uuc_if_cond_no_unsafe_op() { int *r = new int[7]; int *p = new int[4]; @@ -58,32 +73,32 @@ void uuc_if_cond_no_unsafe_op() { void uuc_if_cond_unsafe_op() { int *r = new int[7]; - int *p = new int[4]; //expected-warning{{'p' is an unsafe pointer used for buffer access}} + int *p = new int[4]; if ((p = r)) { - p[3] = 2; // expected-note{{used in buffer access here}} + p[3] = 2; } } void uuc_if_cond_unsafe_op1() { - int *r = new int[7]; // expected-warning{{'r' is an unsafe pointer used for buffer access}} + int *r = new int[7]; int *p = new int[4]; if ((p = r)) { - r[3] = 2; // expected-note{{used in buffer access here}} + r[3] = 2; } } void uuc_if_cond_unsafe_op2() { - int *r = new int[7]; // expected-warning{{'r' is an unsafe pointer used for buffer access}} - int *p = new int[4]; // expected-warning{{'p' is an unsafe pointer used for buffer access}} + int *r = new int[7]; + int *p = new int[4]; if ((p = r)) { - r[3] = 2; // expected-note{{used in buffer access here}} + r[3] = 2; } - p[4] = 6; // expected-note{{used in buffer access here}} + p[4] = 6; } void uuc_call1() { - int *w = new int[4]; // expected-warning{{'w' is an unsafe pointer used for buffer access}} + int *w = new int[4]; int *y = new int[4]; bar(w = y); - w[5] = 0; // expected-note{{used in buffer access here}} + w[5] = 0; } diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp index 2b37442cbd84b..d5a3f121c19ea 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-uuc.cpp @@ -38,6 +38,15 @@ void uuc_if_body2(bool flag) { p[5] = 4; // expected-note{{used in buffer access here}} } +void uuc_if_body2_ptr_init(bool flag) { + int *r = new int[7]; + if (flag) { + } else { + int* p = r; // expected-warning{{'p' is an unsafe pointer used for buffer access}} // expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change 'r' to 'std::span' to propagate bounds information between them$}}}} + p[5] = 4; // expected-note{{used in buffer access here}} + } +} + void uuc_if_cond_no_unsafe_op() { int *r = new int[7]; int *p = new int[4]; diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp index d2aa57997e6d4..a60e7310c99a6 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-multi-decl-warnings.cpp @@ -39,13 +39,11 @@ void local_assign_lhs_span() { p = q; } - -// FIXME: Support initializations at declarations. void lhs_span_multi_assign() { int *a = new int[2]; int *b = a; int *c = b; - int *d = c; // expected-warning{{'d' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'd' to 'std::span' to preserve bounds information$}}}} + int *d = c; // expected-warning{{'d' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'd' to 'std::span' to preserve bounds information, and change ('a', 'b', and 'c'|'a', 'c', and 'b'|'b', 'a', and 'c'|'b', 'c', and 'a'|'c', 'a', and 'b'|'c', 'b', and 'a') to 'std::span' to propagate bounds information between them$}}}} int tmp = d[2]; // expected-note{{used in buffer access here}} } @@ -59,15 +57,15 @@ void rhs_span() { void rhs_span1() { int *q = new int[12]; - int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information$}}}} + int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change ('q' and 'r'|'r' and 'q') to 'std::span' to propagate bounds information between them$}}}} p[5] = 10; // expected-note{{used in buffer access here}} - int *r = q; // expected-warning{{'r' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'r' to 'std::span' to preserve bounds information$}}}} + int *r = q; // expected-warning{{'r' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'r' to 'std::span' to preserve bounds information, and change ('p' and 'q'|'q' and 'p') to 'std::span' to propagate bounds information between them$}}}} r[10] = 5; // expected-note{{used in buffer access here}} } void rhs_span2() { int *q = new int[6]; - int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information$}}}} + int *p = q; // expected-warning{{'p' is an unsafe pointer used for buffer access}} p[5] = 10; // expected-note{{used in buffer access here}} int *r = q; } @@ -175,7 +173,7 @@ void foo3b() { void test_crash() { int *r = new int[8]; int *q = r; - int *p; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change 'q' to 'std::span' to propagate bounds information between them$}}}} + int *p; // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-note-re{{{{^change type of 'p' to 'std::span' to preserve bounds information, and change ('r' and 'q'|'q' and 'r') to 'std::span' to propagate bounds information between them$}}}} p = q; int tmp = p[9]; // expected-note{{used in buffer access here}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits