[llvm-branch-commits] [clang] [LifetimeSafety] Add origin tracking for pointer dereference (PR #170006)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Dec 3 23:20:16 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Utkarsh Saxena (usx95)
<details>
<summary>Changes</summary>
Fix lifetime safety analysis for pointer dereference operations by properly tracking origin flow.
Added support in `FactsGenerator::VisitUnaryOperator()` to handle the dereference operator (`UO_Deref`). This change ensures that when a pointer is dereferenced, the origin of the pointer is properly propagated to the dereference expression.
---
Full diff: https://github.com/llvm/llvm-project/pull/170006.diff
3 Files Affected:
- (modified) clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp (+4)
- (modified) clang/test/Sema/warn-lifetime-safety-dataflow.cpp (+6)
- (modified) clang/test/Sema/warn-lifetime-safety.cpp (+11-11)
``````````diff
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 4f05d7ea94aa7..b27dcb6163449 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -218,6 +218,10 @@ void FactsGenerator::VisitUnaryOperator(const UnaryOperator *UO) {
// origin of this UnaryOperator expression.
killAndFlowOrigin(*UO, *SubExpr);
}
+ if (UO->getOpcode() == UO_Deref) {
+ const Expr *SubExpr = UO->getSubExpr();
+ killAndFlowOrigin(*UO, *SubExpr);
+ }
}
void FactsGenerator::VisitReturnStmt(const ReturnStmt *RS) {
diff --git a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
index 6d5711deba1cf..6fc7c776f935c 100644
--- a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
@@ -152,6 +152,12 @@ void pointer_indirection() {
// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
// CHECK-NEXT: Src: [[O_PP_INNER]] (Decl: pp, Type : int *)
// CHECK: OriginFlow:
+// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int *&)
+// CHECK-NEXT: Src: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int **)
+// CHECK: OriginFlow:
+// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: UnaryOperator, Type : int *)
+// CHECK-NEXT: Src: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
+// CHECK: OriginFlow:
// CHECK-NEXT: Dest: {{[0-9]+}} (Expr: ImplicitCastExpr, Type : int *)
// CHECK-NEXT: Src: {{[0-9]+}} (Expr: UnaryOperator, Type : int *)
// CHECK: OriginFlow:
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index e62c3b69b040b..f22c73cfeb784 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -596,10 +596,10 @@ const int* return_pointer_to_parameter_via_reference(int a, int b, bool cond) {
const int* d = &c;
return d; // expected-note 2 {{returned here}}
}
-// FIXME: Dereference of a pointer does not track the reference.
+
const int& return_pointer_to_parameter_via_reference_1(int a) {
- const int* d = &a;
- return *d;
+ const int* d = &a; // expected-warning {{address of stack memory is returned later}}
+ return *d; // expected-note {{returned here}}
}
const int& get_ref_to_local() {
@@ -1118,24 +1118,24 @@ struct MyObjStorage {
const MyObj *end() const { return objs + 1; }
};
-// FIXME: Detect use-after-scope. Dereference pointer does not propagate the origins.
void range_based_for_use_after_scope() {
View v;
{
MyObjStorage s;
- for (const MyObj &o : s) {
+ for (const MyObj &o : s) { // expected-warning {{object whose reference is captured does not live long enough}}
v = o;
}
- }
- v.use();
+ } // expected-note {{destroyed here}}
+ v.use(); // expected-note {{later used here}}
}
-// FIXME: Detect use-after-return. Dereference pointer does not propagate the origins.
+
View range_based_for_use_after_return() {
MyObjStorage s;
- for (const MyObj &o : s) {
- return o;
+ for (const MyObj &o : s) { // expected-warning {{address of stack memory is returned later}}
+ return o; // expected-note {{returned here}}
}
- return *s.begin();
+ return *s.begin(); // expected-warning {{address of stack memory is returned later}}
+ // expected-note at -1 {{returned here}}
}
void range_based_for_not_reference() {
``````````
</details>
https://github.com/llvm/llvm-project/pull/170006
More information about the llvm-branch-commits
mailing list