-
Notifications
You must be signed in to change notification settings - Fork 15.6k
[LifetimeSafety] Add origin tracking for pointer dereference #170006
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/usx95/11-29-implicit_lifetimebound_for_std_namespace
Are you sure you want to change the base?
[LifetimeSafety] Add origin tracking for pointer dereference #170006
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
🐧 Linux x64 Test ResultsThe build failed before running any tests. Click on a failure below to see the details. tools/clang/lib/Analysis/LifetimeSafety/CMakeFiles/obj.clangAnalysisLifetimeSafety.dir/Origins.cpp.oIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
363a78c to
f19ea1b
Compare
349c748 to
a3842ac
Compare
f19ea1b to
6b70da3
Compare
3ead2ab to
f53324e
Compare
a71af86 to
651cb0b
Compare
1c7deeb to
1ad3ce7
Compare
ddc91c3 to
2ac7726
Compare
1ad3ce7 to
4ce85f5
Compare
4ce85f5 to
ceda23e
Compare
|
@llvm/pr-subscribers-clang-analysis @llvm/pr-subscribers-clang Author: Utkarsh Saxena (usx95) ChangesFix lifetime safety analysis for pointer dereference operations by properly tracking origin flow. Added support in Full diff: https://github.com/llvm/llvm-project/pull/170006.diff 3 Files Affected:
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@-1 {{returned here}}
}
void range_based_for_not_reference() {
|
Xazax-hun
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks!
Do we want to have some built-in handling for overloaded operators as well? It could be a follow-up PR though.
I suspect that this PR might not address the case when the dereference is the LHS on an assignment (like *p = a). But I think that could be a follow-up PR. We might need to change the assignment handling for more complicated LHS expression to handle things like (cond? a : b) = p.
ceda23e to
9308d55
Compare
2ac7726 to
5be82f0
Compare
Added some more tests for overloaded operators. I think they used to work before through CallExpr handling.
Right. This case is added in the tests as a TODO. |
| // origin of this UnaryOperator expression. | ||
| killAndFlowOrigin(*UO, *SubExpr); | ||
| } | ||
| if (UO->getOpcode() == UO_Deref) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: move to a switch now that you have 2 cases.

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.