[clang] [LifetimeSafety] Introduce a liveness-based lifetime policy (PR #159991)
Utkarsh Saxena via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 7 10:20:09 PDT 2025
================
@@ -1174,5 +1013,187 @@ TEST_F(LifetimeAnalysisTest, LifetimeboundConversionOperator) {
)");
EXPECT_THAT(Origin("v"), HasLoansTo({"owner"}, "p1"));
}
+
+TEST_F(LifetimeAnalysisTest, LivenessDeadPointer) {
+ SetupTest(R"(
+ void target() {
+ POINT(p2);
+ MyObj s;
+ MyObj* p = &s;
+ POINT(p1);
+ }
+ )");
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p1"));
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p2"));
+}
+
+TEST_F(LifetimeAnalysisTest, LivenessSimpleReturn) {
+ SetupTest(R"(
+ MyObj* target() {
+ MyObj s;
+ MyObj* p = &s;
+ POINT(p1);
+ return p;
+ }
+ )");
+ EXPECT_THAT(Origins({"p"}), AreDefinitelyLiveAt("p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, LivenessKilledByReassignment) {
+ SetupTest(R"(
+ MyObj* target() {
+ MyObj s1, s2;
+ MyObj* p = &s1;
+ POINT(p1);
+ p = &s2;
+ POINT(p2);
+ return p;
+ }
+ )");
+ EXPECT_THAT(Origins({"p"}), AreDefinitelyLiveAt("p2"));
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, LivenessAcrossBranches) {
+ SetupTest(R"(
+ MyObj* target(bool c) {
+ MyObj x, y;
+ MyObj* p = nullptr;
+ POINT(p1);
+ if (c) {
+ p = &x;
+ POINT(p2);
+ } else {
+ p = &y;
+ POINT(p3);
+ }
+ return p;
+ }
+ )");
+ EXPECT_THAT(Origins({"p"}), AreDefinitelyLiveAt("p2"));
+ EXPECT_THAT(Origins({"p"}), AreDefinitelyLiveAt("p3"));
+ // Before the `if`, the value of `p` (`nullptr`) is always overwritten before.
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, LivenessInLoop) {
+ SetupTest(R"(
+ MyObj* target(bool c) {
+ MyObj s1, s2;
+ MyObj* p = &s1;
+ MyObj* q = &s2;
+ POINT(p1);
+ while(c) {
+ POINT(p2);
+
+ p = q;
+ POINT(p3);
+ }
+ POINT(p4);
+ return p;
+ }
+ )");
+
+ EXPECT_THAT(Origins({"p"}), AreDefinitelyLiveAt("p4"));
+ EXPECT_THAT(NoOrigins(), AreMaybeLiveAt("p4"));
+
+ EXPECT_THAT(Origins({"p", "q"}), AreMaybeLiveAt("p3"));
+
+ EXPECT_THAT(Origins({"q"}), AreDefinitelyLiveAt("p2"));
+ EXPECT_THAT(NoOrigins(), AreMaybeLiveAt("p2"));
+
+ EXPECT_THAT(Origins({"p", "q"}), AreMaybeLiveAt("p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, LivenessInLoopAndIf) {
+ // See https://github.com/llvm/llvm-project/issues/156959.
+ SetupTest(R"(
+ void target(bool cond) {
+ MyObj b;
+ while (cond) {
+ POINT(p1);
+
+ MyObj a;
+ View p = b;
+
+ POINT(p2);
+
+ if (cond) {
+ POINT(p3);
+ p = a;
+ }
+ POINT(p4);
+ (void)p;
+ POINT(p5);
+ }
+ }
+ )");
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p5"));
+ EXPECT_THAT(Origins({"p"}), AreDefinitelyLiveAt("p4"));
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p3"));
+ EXPECT_THAT(Origins({"p"}), AreMaybeLiveAt("p2"));
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, LivenessInLoopAndIf2) {
+ SetupTest(R"(
+ void target(MyObj safe, bool condition) {
+ MyObj* p = &safe;
+ MyObj* q = &safe;
+ POINT(p6);
----------------
usx95 wrote:
Thanks fixed. The code under test now has ascending annotations but the test expectations are in reverse (easier to understand the results of a backward analysis)
https://github.com/llvm/llvm-project/pull/159991
More information about the cfe-commits
mailing list