Skip to content

Conversation

@usx95
Copy link
Contributor

@usx95 usx95 commented Nov 9, 2025

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.

Copy link
Contributor Author

usx95 commented Nov 9, 2025

@usx95 usx95 force-pushed the users/usx95/11-09-lifetime-safety-paren branch from 0daf453 to 818b350 Compare November 9, 2025 20:39
@usx95 usx95 changed the title lifetime-safety-paren [LifetimeSafety] Ignore parentheses when tracking expressions Nov 9, 2025
@usx95 usx95 marked this pull request as ready for review November 9, 2025 20:41
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:analysis clang:temporal-safety Issue/FR relating to the lifetime analysis in Clang (-Wdangling, -Wreturn-local-addr) labels Nov 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 9, 2025

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-temporal-safety

@llvm/pr-subscribers-clang-analysis

Author: Utkarsh Saxena (usx95)

Changes

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 --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"(

@usx95 usx95 force-pushed the users/usx95/11-09-lifetime-safety-paren branch from 818b350 to 8e0d7d8 Compare November 9, 2025 21:00
@usx95 usx95 requested a review from ymand November 9, 2025 21:32
@usx95 usx95 force-pushed the users/usx95/11-09-lifetime-safety-cxx-conditional branch from b90459c to c678379 Compare November 10, 2025 23:34
@usx95 usx95 force-pushed the users/usx95/11-09-lifetime-safety-paren branch from 8e0d7d8 to 164b957 Compare November 10, 2025 23:34
@usx95 usx95 moved this to In Progress in Lifetime Safety in Clang Nov 11, 2025
Base automatically changed from users/usx95/11-09-lifetime-safety-cxx-conditional to main November 12, 2025 15:58
@usx95 usx95 force-pushed the users/usx95/11-09-lifetime-safety-paren branch from 164b957 to b3d6437 Compare November 12, 2025 18:05
@usx95 usx95 merged commit 342bf57 into main Nov 12, 2025
10 checks passed
@usx95 usx95 deleted the users/usx95/11-09-lifetime-safety-paren branch November 12, 2025 23:13
@github-project-automation github-project-automation bot moved this from In Progress to Done in Lifetime Safety in Clang Nov 12, 2025
git-crd pushed a commit to git-crd/crd-llvm-project that referenced this pull request Nov 13, 2025
…67245)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:analysis clang:temporal-safety Issue/FR relating to the lifetime analysis in Clang (-Wdangling, -Wreturn-local-addr) clang Clang issues not falling into any other category

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants