Index: clang/lib/Analysis/UnsafeBufferUsage.cpp =================================================================== --- clang/lib/Analysis/UnsafeBufferUsage.cpp +++ clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -380,6 +380,10 @@ } }; +static auto toSupportedVariable() { + return to(anyOf(varDecl(), bindingDecl())); +} + using FixableGadgetList = std::vector>; using WarningGadgetList = std::vector>; @@ -616,10 +620,10 @@ static Matcher matcher() { auto PtrAssignExpr = binaryOperator(allOf(hasOperatorName("="), hasRHS(ignoringParenImpCasts(declRefExpr(hasPointerType(), - to(varDecl())). + toSupportedVariable()). bind(PointerAssignRHSTag))), hasLHS(declRefExpr(hasPointerType(), - to(varDecl())). + toSupportedVariable()). bind(PointerAssignLHSTag)))); return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr)); @@ -733,7 +737,7 @@ static Matcher matcher() { auto ArrayOrPtr = anyOf(hasPointerType(), hasArrayType()); auto target = expr( - ignoringParenImpCasts(declRefExpr(allOf(ArrayOrPtr, to(varDecl()))).bind(DeclRefExprTag))); + ignoringParenImpCasts(declRefExpr(allOf(ArrayOrPtr, toSupportedVariable())).bind(DeclRefExprTag))); return stmt(isInUnspecifiedPointerContext(target)); } @@ -769,7 +773,7 @@ unaryOperator( hasOperatorName("*"), has(expr(ignoringParenImpCasts( - declRefExpr(to(varDecl())).bind(BaseDeclRefExprTag))))) + declRefExpr(toSupportedVariable()).bind(BaseDeclRefExprTag))))) .bind(OperatorTag); return expr(isInUnspecifiedLvalueContext(Target)); @@ -999,7 +1003,8 @@ static Matcher matcher() { // clang-format off auto ThePtr = expr(hasPointerType(), - ignoringImpCasts(declRefExpr(to(varDecl())).bind(BaseDeclRefExprTag))); + ignoringImpCasts(declRefExpr(toSupportedVariable()). + bind(BaseDeclRefExprTag))); auto PlusOverPtrAndInteger = expr(anyOf( binaryOperator(hasOperatorName("+"), hasLHS(ThePtr), hasRHS(integerLiteral().bind(OffsetTag))) @@ -1106,7 +1111,7 @@ // In parallel, match all DeclRefExprs so that to find out // whether there are any uncovered by gadgets. declRefExpr(anyOf(hasPointerType(), hasArrayType()), - to(varDecl())).bind("any_dre"), + toSupportedVariable()).bind("any_dre"), // Also match DeclStmts because we'll need them when fixing // their underlying VarDecls that otherwise don't have // any backreferences to DeclStmts. Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp @@ -78,3 +78,23 @@ auto [x, y] = a; x = 9; } + +void test_claim_use_multiple() { + int *a = new int[8]; // expected-warning{{'a' is an unsafe pointer used for buffer access}} + a[6] = 9; // expected-note{{used in buffer access here}} + a++; // expected-note{{used in pointer arithmetic here}} \ + // debug-note{{safe buffers debug: failed to produce fixit for 'a' : has an unclaimed use}} +} + +struct S +{ + int *x; +}; + +S f() { return S{new int[4]}; } + +void test_struct_claim_use() { + auto [x] = f(); + x[6] = 8; // expected-warning{{unsafe buffer access}} + x++; // expected-warning{{unsafe pointer arithmetic}} +}