https://github.com/NeKon69 updated https://github.com/llvm/llvm-project/pull/189546
>From 364fa6f3020e2d11c2e0d40e995ab7b4c3ce23a3 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Tue, 31 Mar 2026 00:21:57 +0300 Subject: [PATCH 1/5] [LifetimeSafety] propogate loans on pointer arithmetic --- .../Analyses/LifetimeSafety/FactsGenerator.h | 2 ++ .../lib/Analysis/LifetimeSafety/FactsGenerator.cpp | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h index dfcbdc7d73007..1bfd3fd5f2c1c 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h @@ -61,6 +61,8 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> { void handleAssignment(const Expr *LHSExpr, const Expr *RHSExpr); + void handlePointerArithmetic(const BinaryOperator *BO); + void handleCXXCtorInitializer(const CXXCtorInitializer *CII); void handleLifetimeEnds(const CFGLifetimeEnds &LifetimeEnds); diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index 6b61d7fd64fd7..29f4204345586 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -371,9 +371,19 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr, flow(LHSList->peelOuterOrigin(), RHSList, /*Kill=*/true); } +void FactsGenerator::handlePointerArithmetic(const BinaryOperator *BO) { + if (Expr *RHS = BO->getRHS(); RHS->getType()->isPointerType()) { + flowOrigin(*BO, *RHS); + return; + } + Expr *LHS = BO->getLHS(); + assert(LHS->getType()->isPointerType() && "Unexpected operand was found"); + flowOrigin(*BO, *LHS); +} + void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) { - // TODO: Handle pointer arithmetic (e.g., `p + 1` or `1 + p`) where the - // result should have the same loans as the pointer operand. + if (BO->getType()->isPointerType() && BO->isAdditiveOp()) + handlePointerArithmetic(BO); if (BO->isCompoundAssignmentOp()) return; handleUse(BO->getRHS()); >From 851993ed9f98b26e86ab028d09d7dc20bd9d91d4 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Tue, 31 Mar 2026 09:52:53 +0300 Subject: [PATCH 2/5] [LifetimeSfety] move check after compund assignment check and add tests --- clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp | 5 +++-- clang/test/Sema/warn-lifetime-safety-suggestions.cpp | 7 +++++++ clang/test/Sema/warn-lifetime-safety.cpp | 7 +++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index 29f4204345586..7db01392cc11f 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -382,10 +382,11 @@ void FactsGenerator::handlePointerArithmetic(const BinaryOperator *BO) { } void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) { - if (BO->getType()->isPointerType() && BO->isAdditiveOp()) - handlePointerArithmetic(BO); if (BO->isCompoundAssignmentOp()) return; + + if (BO->getType()->isPointerType() && BO->isAdditiveOp()) + handlePointerArithmetic(BO); handleUse(BO->getRHS()); if (BO->isAssignmentOp()) handleAssignment(BO->getLHS(), BO->getRHS()); diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp index 22c4222022ebf..3591270306827 100644 --- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp +++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp @@ -438,4 +438,11 @@ struct MemberArrayReturn { } }; +struct MemberPointerArithmeticReturn { + int arr[10]; + int* end() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}} + return arr + 10; // expected-note {{param returned here}} + } +}; + } // namespace array diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index 76d43445f8636..4e2c69c7fb2b8 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -2070,14 +2070,13 @@ int* static_array() { return &a[1]; } -// FIXME: Pointer arithmetic is not yet tracked. void pointer_arithmetic_use_after_scope() { int* p; { int a[10]{}; - p = a + 5; - } - (void)*p; // Should warn. + p = a + 5; // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} } // FIXME: Copying a pointer value out of an array element is not tracked. >From edece21a757b81e91e706d7224258e33e087a3d0 Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Tue, 31 Mar 2026 09:55:30 +0300 Subject: [PATCH 3/5] move test into existing struct --- clang/test/Sema/warn-lifetime-safety-suggestions.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp index 3591270306827..d776c1067e4d0 100644 --- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp +++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp @@ -436,13 +436,9 @@ struct MemberArrayReturn { int* getData() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}} return arr; // expected-note {{param returned here}} } -}; - -struct MemberPointerArithmeticReturn { - int arr[10]; - int* end() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}} - return arr + 10; // expected-note {{param returned here}} - } + int* getLast() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}} + return arr + 10; // expected-note {{param returned here}} + } }; } // namespace array >From d355960fa51d80422325c9e50eaf4314b58f57bb Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Tue, 31 Mar 2026 09:58:50 +0300 Subject: [PATCH 4/5] update assert message --- clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index 7db01392cc11f..01cdba1e1ae31 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -377,14 +377,14 @@ void FactsGenerator::handlePointerArithmetic(const BinaryOperator *BO) { return; } Expr *LHS = BO->getLHS(); - assert(LHS->getType()->isPointerType() && "Unexpected operand was found"); + assert(LHS->getType()->isPointerType() && + "Pointer arithmetic must have a pointer operand"); flowOrigin(*BO, *LHS); } void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) { if (BO->isCompoundAssignmentOp()) return; - if (BO->getType()->isPointerType() && BO->isAdditiveOp()) handlePointerArithmetic(BO); handleUse(BO->getRHS()); >From 4e2061f81bf5433ee747c027c277fb01e80abafd Mon Sep 17 00:00:00 2001 From: NeKon69 <[email protected]> Date: Tue, 31 Mar 2026 12:15:27 +0300 Subject: [PATCH 5/5] switch to killAndFlowOrigin, test for subtraction --- clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp | 4 ++-- clang/test/Sema/warn-lifetime-safety.cpp | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index 01cdba1e1ae31..68017220e0a54 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -373,13 +373,13 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr, void FactsGenerator::handlePointerArithmetic(const BinaryOperator *BO) { if (Expr *RHS = BO->getRHS(); RHS->getType()->isPointerType()) { - flowOrigin(*BO, *RHS); + killAndFlowOrigin(*BO, *RHS); return; } Expr *LHS = BO->getLHS(); assert(LHS->getType()->isPointerType() && "Pointer arithmetic must have a pointer operand"); - flowOrigin(*BO, *LHS); + killAndFlowOrigin(*BO, *LHS); } void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) { diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index 4e2c69c7fb2b8..7158f68ee1727 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -2072,11 +2072,14 @@ int* static_array() { void pointer_arithmetic_use_after_scope() { int* p; + int* p2; { int a[10]{}; - p = a + 5; // expected-warning {{object whose reference is captured does not live long enough}} - } // expected-note {{destroyed here}} - (void)*p; // expected-note {{later used here}} + p = a + 5; // expected-warning {{object whose reference is captured does not live long enough}} + p2 = a - 5; // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note 2 {{destroyed here}} + (void)*p; // expected-note {{later used here}} + (void)*p2; // expected-note {{later used here}} } // FIXME: Copying a pointer value out of an array element is not tracked. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
