[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