Index: clang/lib/Analysis/UnsafeBufferUsage.cpp =================================================================== --- clang/lib/Analysis/UnsafeBufferUsage.cpp +++ clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -557,14 +557,14 @@ static constexpr const char *const PointerInitLHSTag = "ptrInitLHS"; static constexpr const char *const PointerInitRHSTag = "ptrInitRHS"; const DeclStmt *PI; // pointer arithmetic expression - const DeclRefExpr * PtrInitLHS; // the LHS pointer expression in `PI` + 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), PI(Result.Nodes.getNodeAs(PointerInitTag)), - PtrInitLHS(Result.Nodes.getNodeAs(PointerInitLHSTag)), + PtrInitLHS(Result.Nodes.getNodeAs(PointerInitLHSTag)), PtrInitRHS(Result.Nodes.getNodeAs(PointerInitRHSTag)) {} static bool classof(const Gadget *G) { @@ -572,9 +572,9 @@ } static Matcher matcher() { - auto PtrInitExpr = declRefExpr(to(varDecl( hasInitializer(ignoringImpCasts(declRefExpr(hasType(hasCanonicalType(pointerType()))).bind(PointerInitRHSTag)))))).bind(PointerInitLHSTag); - - return declStmt(PtrInitExpr); + auto PtrInitStmt = declStmt(hasSingleDecl(varDecl( hasInitializer(ignoringImpCasts(declRefExpr(hasPointerType()).bind(PointerInitRHSTag)))).bind(PointerInitLHSTag))); + + return PtrInitStmt; } virtual std::optional getFixits(const Strategy &S) const override; @@ -582,12 +582,13 @@ virtual const Stmt *getBaseStmt() const override { return PI; } virtual DeclUseList getClaimedVarUseSites() const override { - return DeclUseList{PtrInitLHS, PtrInitRHS}; +// return DeclUseList{PtrInitLHS, PtrInitRHS}; + return DeclUseList{PtrInitRHS}; } virtual std::optional> getStrategyImplications() const override { - return std::make_pair(cast(PtrInitLHS->getDecl()), + return std::make_pair(PtrInitLHS, cast(PtrInitRHS->getDecl())); } }; @@ -726,8 +727,8 @@ 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; using DefMapTy = DenseMap; @@ -1186,7 +1187,7 @@ std::optional PointerInitGadget::getFixits(const Strategy &S) const { - const auto *LeftVD = cast(PtrInitLHS->getDecl()); + const auto *LeftVD = PtrInitLHS; const auto *RightVD = cast(PtrInitRHS->getDecl()); switch (S.lookup(LeftVD)) { case Strategy::Kind::Span: @@ -1624,16 +1625,16 @@ const DeclUseTracker &Tracker, const ASTContext &Ctx, UnsafeBufferUsageHandler &Handler) { - const DeclStmt *DS = Tracker.lookupDecl(VD); - assert(DS && "Fixing non-local variables not implemented yet!"); - if (!DS->isSingleDecl()) { - // FIXME: to support handling multiple `VarDecl`s in a single `DeclStmt` - return {}; - } - // Currently DS is an unused variable but we'll need it when - // non-single decls are implemented, where the pointee type name - // and the '*' are spread around the place. - (void)DS; +// const DeclStmt *DS = Tracker.lookupDecl(VD); +// assert(DS && "Fixing non-local variables not implemented yet!"); +// if (!DS->isSingleDecl()) { +// // FIXME: to support handling multiple `VarDecl`s in a single `DeclStmt` +// return {}; +// } +// // Currently DS is an unused variable but we'll need it when +// // non-single decls are implemented, where the pointee type name +// // and the '*' are spread around the place. +// (void)DS; // FIXME: handle cases where DS has multiple declarations return fixVarDeclWithSpan(VD, Ctx, Handler.getUserFillPlaceHolder()); Index: clang/test/SemaCXX/debug_crash.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/debug_crash.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -verify %s + +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$}}}} + p[5] = 10; // expected-note{{used in buffer access here}} +}