[llvm-branch-commits] [clang] [LifetimeSafety] Ignore parentheses when tracking expressions (PR #167245)
Utkarsh Saxena via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Nov 9 13:00:52 PST 2025
https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/167245
>From 8e0d7d89d011eb5b3ddc76c3a4d6fc32ad9abe54 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <usx at google.com>
Date: Sun, 9 Nov 2025 20:23:40 +0000
Subject: [PATCH] lifetime-safety-paren
---
clang/lib/Analysis/LifetimeSafety/Origins.cpp | 2 ++
clang/test/Sema/warn-lifetime-safety.cpp | 31 +++++++++++++++++++
.../unittests/Analysis/LifetimeSafetyTest.cpp | 17 ++++++++++
3 files changed, 50 insertions(+)
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..00e5ca23c8503 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -635,3 +635,34 @@ 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}}
+
+ {
+ MyObj a, b, c, d;
+ p = ((cond ? (((cond ? &a : &b))) // expected-warning 2 {{object whose reference is captured does not live long enough}}.
+ : &(((cond ? c : d))))); // expected-warning 2 {{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"(
More information about the llvm-branch-commits
mailing list