[clang] [LifetimeSafety] Propagate loans through pointer arithmetic (PR #189546)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 00:06:18 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-analysis
Author: NeKon69
<details>
<summary>Changes</summary>
This PR adds loan propagation for pointer arithmetic.
It also updates the tests to match the new behavior.
Fixes #<!-- -->180933
---
Full diff: https://github.com/llvm/llvm-project/pull/189546.diff
4 Files Affected:
- (modified) clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h (+2)
- (modified) clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp (+13-2)
- (modified) clang/test/Sema/warn-lifetime-safety-suggestions.cpp (+3)
- (modified) clang/test/Sema/warn-lifetime-safety.cpp (+3-4)
``````````diff
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..01cdba1e1ae31 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -371,11 +371,22 @@ 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() &&
+ "Pointer arithmetic must have a pointer operand");
+ 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->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..d776c1067e4d0 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -436,6 +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}}
}
+ 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
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.
``````````
</details>
https://github.com/llvm/llvm-project/pull/189546
More information about the cfe-commits
mailing list