Skip to content

Commit 1d6324a

Browse files
usx95git-crd
authored andcommitted
[LifetimeSafety] Ignore parentheses when tracking expressions (llvm#167245)
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.
1 parent 03ed866 commit 1d6324a

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

clang/lib/Analysis/LifetimeSafety/Origins.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Origin &OriginManager::addOrigin(OriginID ID, const clang::Expr &E) {
3434

3535
// TODO: Mark this method as const once we remove the call to getOrCreate.
3636
OriginID OriginManager::get(const Expr &E) {
37+
if (auto *ParenIgnored = E.IgnoreParens(); ParenIgnored != &E)
38+
return get(*ParenIgnored);
3739
auto It = ExprToOriginID.find(&E);
3840
if (It != ExprToOriginID.end())
3941
return It->second;

clang/test/Sema/warn-lifetime-safety.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,3 +655,34 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) {
655655
} // expected-note 4 {{destroyed here}}
656656
(void)*p; // expected-note 4 {{later used here}}
657657
}
658+
659+
void parentheses(bool cond) {
660+
MyObj* p;
661+
{
662+
MyObj a;
663+
p = &((((a)))); // expected-warning {{object whose reference is captured does not live long enough}}
664+
} // expected-note {{destroyed here}}
665+
(void)*p; // expected-note {{later used here}}
666+
667+
{
668+
MyObj a;
669+
p = ((GetPointer((a)))); // expected-warning {{object whose reference is captured does not live long enough}}
670+
} // expected-note {{destroyed here}}
671+
(void)*p; // expected-note {{later used here}}
672+
673+
{
674+
MyObj a, b, c, d;
675+
p = &(cond ? (cond ? a // expected-warning {{object whose reference is captured does not live long enough}}.
676+
: b) // expected-warning {{object whose reference is captured does not live long enough}}.
677+
: (cond ? c // expected-warning {{object whose reference is captured does not live long enough}}.
678+
: d)); // expected-warning {{object whose reference is captured does not live long enough}}.
679+
} // expected-note 4 {{destroyed here}}
680+
(void)*p; // expected-note 4 {{later used here}}
681+
682+
{
683+
MyObj a, b, c, d;
684+
p = ((cond ? (((cond ? &a : &b))) // expected-warning 2 {{object whose reference is captured does not live long enough}}.
685+
: &(((cond ? c : d))))); // expected-warning 2 {{object whose reference is captured does not live long enough}}.
686+
} // expected-note 4 {{destroyed here}}
687+
(void)*p; // expected-note 4 {{later used here}}
688+
}

clang/unittests/Analysis/LifetimeSafetyTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,23 @@ TEST_F(LifetimeAnalysisTest, GslPointerInConditionalOperator) {
700700
EXPECT_THAT(Origin("v"), HasLoansTo({"a", "b"}, "p1"));
701701
}
702702

703+
TEST_F(LifetimeAnalysisTest, ExtraParenthesis) {
704+
SetupTest(R"(
705+
void target() {
706+
MyObj a;
707+
View x = ((View((((a))))));
708+
View y = ((View{(((x)))}));
709+
View z = ((View(((y)))));
710+
View p = ((View{((x))}));
711+
POINT(p1);
712+
}
713+
)");
714+
EXPECT_THAT(Origin("x"), HasLoansTo({"a"}, "p1"));
715+
EXPECT_THAT(Origin("y"), HasLoansTo({"a"}, "p1"));
716+
EXPECT_THAT(Origin("z"), HasLoansTo({"a"}, "p1"));
717+
EXPECT_THAT(Origin("p"), HasLoansTo({"a"}, "p1"));
718+
}
719+
703720
// FIXME: Handle temporaries.
704721
TEST_F(LifetimeAnalysisTest, ViewFromTemporary) {
705722
SetupTest(R"(

0 commit comments

Comments
 (0)