[llvm-branch-commits] [clang] [LifetimeSafety] Ignore parentheses when tracking expressions (PR #167245)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Nov 9 12:42:01 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-analysis
Author: Utkarsh Saxena (usx95)
<details>
<summary>Changes</summary>
Add support for handling parenthesized expressions in lifetime safety analysis.
Modified the `OriginManager::get` method to ignore parentheses when retrieving origins by recursively calling itself on the unparenthesized expression. This ensures that expressions with extra parentheses are properly analyzed for lifetime safety issues.
---
Full diff: https://github.com/llvm/llvm-project/pull/167245.diff
3 Files Affected:
- (modified) clang/lib/Analysis/LifetimeSafety/Origins.cpp (+2)
- (modified) clang/test/Sema/warn-lifetime-safety.cpp (+24)
- (modified) clang/unittests/Analysis/LifetimeSafetyTest.cpp (+17)
``````````diff
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index ea51a75324e06..0f2eaa94a5987 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -34,6 +34,8 @@ Origin &OriginManager::addOrigin(OriginID ID, const clang::Expr &E) {
// TODO: Mark this method as const once we remove the call to getOrCreate.
OriginID OriginManager::get(const Expr &E) {
+ if (auto *ParenIgnored = E.IgnoreParens(); ParenIgnored != &E)
+ return get(*ParenIgnored);
auto It = ExprToOriginID.find(&E);
if (It != ExprToOriginID.end())
return It->second;
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index 3057ac9385736..52165c4236988 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -635,3 +635,27 @@ void conditional_operator(bool cond) {
} // expected-note 4 {{destroyed here}}
(void)*p; // expected-note 4 {{later used here}}
}
+
+void parentheses(bool cond) {
+ MyObj* p;
+ {
+ MyObj a;
+ p = &((((a)))); // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+
+ {
+ MyObj a;
+ p = ((GetPointer((a)))); // expected-warning {{object whose reference is captured does not live long enough}}
+ } // expected-note {{destroyed here}}
+ (void)*p; // expected-note {{later used here}}
+
+ {
+ MyObj a, b, c, d;
+ p = &(cond ? cond ? a // expected-warning {{object whose reference is captured does not live long enough}}.
+ : b // expected-warning {{object whose reference is captured does not live long enough}}.
+ : cond ? c // expected-warning {{object whose reference is captured does not live long enough}}.
+ : d); // expected-warning {{object whose reference is captured does not live long enough}}.
+ } // expected-note 4 {{destroyed here}}
+ (void)*p; // expected-note 4 {{later used here}}
+}
diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
index 9d61d56e078e3..601308c53f9a9 100644
--- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -700,6 +700,23 @@ TEST_F(LifetimeAnalysisTest, GslPointerInConditionalOperator) {
EXPECT_THAT(Origin("v"), HasLoansTo({"a", "b"}, "p1"));
}
+TEST_F(LifetimeAnalysisTest, ExtraParenthesis) {
+ SetupTest(R"(
+ void target() {
+ MyObj a;
+ View x = ((View((((a))))));
+ View y = ((View{(((x)))}));
+ View z = ((View(((y)))));
+ View p = ((View{((x))}));
+ POINT(p1);
+ }
+ )");
+ EXPECT_THAT(Origin("x"), HasLoansTo({"a"}, "p1"));
+ EXPECT_THAT(Origin("y"), HasLoansTo({"a"}, "p1"));
+ EXPECT_THAT(Origin("z"), HasLoansTo({"a"}, "p1"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"a"}, "p1"));
+}
+
// FIXME: Handle temporaries.
TEST_F(LifetimeAnalysisTest, ViewFromTemporary) {
SetupTest(R"(
``````````
</details>
https://github.com/llvm/llvm-project/pull/167245
More information about the llvm-branch-commits
mailing list