Switch to constraint-based analysis.

PiperOrigin-RevId: 483616672
diff --git a/lifetime_analysis/object.h b/lifetime_analysis/object.h
index 4925f4a..e3d4790 100644
--- a/lifetime_analysis/object.h
+++ b/lifetime_analysis/object.h
@@ -18,7 +18,7 @@
 namespace tidy {
 namespace lifetimes {
 
-constexpr bool kUseConstraintBasedAnalysis = false;
+constexpr bool kUseConstraintBasedAnalysis = true;
 
 // Any object that has a lifetime. Multiple objects might have the same
 // lifetime, but two equal objects always have the same lifetime.
diff --git a/lifetime_analysis/test/function_calls.cc b/lifetime_analysis/test/function_calls.cc
index 93f56a7..99bc890 100644
--- a/lifetime_analysis/test/function_calls.cc
+++ b/lifetime_analysis/test/function_calls.cc
@@ -54,7 +54,7 @@
       return p;
     }
   )"),
-              LifetimesAre({{"f", "(static, a)"}, {"target", "-> static"}}));
+              LifetimesAre({{"f", "(a, b)"}, {"target", "-> static"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, SimpleFnIdentityArg1) {
diff --git a/lifetime_analysis/test/records.cc b/lifetime_analysis/test/records.cc
index 2533e15..988746e 100644
--- a/lifetime_analysis/test/records.cc
+++ b/lifetime_analysis/test/records.cc
@@ -189,22 +189,28 @@
 }
 
 TEST_F(LifetimeAnalysisTest, StructMultiplePtrsSameLifetime) {
+  // TODO(veluca): here, we correctly deduce *once f gets called* that something
+  // fishy is going on, namely, that `s.a` could be pointing to a local
+  // variable. However, we should already know this from the initialization of
+  // `s`.
   EXPECT_THAT(GetLifetimes(R"(
     struct [[clang::annotate("lifetime_params", "a")]] S {
-      [[clang::annotate("member_lifetimes", "a", "a", "a")]]
-      int*** a;
       [[clang::annotate("member_lifetimes", "a", "a")]]
-      int** b;
+      int** a;
+      [[clang::annotate("member_lifetimes", "a")]]
+      int* b;
     };
     void f(S& s) {
-      **s.a = *s.b;
+      *s.a = s.b;
     }
-    void target(int** a, int* b) {
+    void target(int* a, int b) {
        S s{&a, &b};
        f(s);
     }
   )"),
-              LifetimesContain({{"target", "(a, b), a"}}));
+              LifetimesContain({{"target",
+                                 "ERROR: function returns reference to a local "
+                                 "through parameter 'a'"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, StructNonLocalPtr) {
@@ -528,8 +534,6 @@
 }
 
 TEST_F(LifetimeAnalysisTest, StructConstructorStaticPtr) {
-  // TODO(veluca): this is overly restrictive in the same way as
-  // StaticPointerOutParam.
   EXPECT_THAT(GetLifetimes(R"(
     static int x;
     struct [[clang::annotate("lifetime_params", "a")]] S {
@@ -538,12 +542,10 @@
       int* a = nullptr;
     };
   )"),
-              LifetimesAre({{"S::S", "(static, a):"}}));
+              LifetimesAre({{"S::S", "(a, b):"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, StructConstructorStaticPtrInitializer) {
-  // TODO(veluca): this is overly restrictive in the same way as
-  // StaticPointerOutParam.
   EXPECT_THAT(GetLifetimes(R"(
     static int x;
     struct [[clang::annotate("lifetime_params", "a")]] S {
@@ -552,12 +554,10 @@
       int* a = nullptr;
     };
   )"),
-              LifetimesAre({{"S::S", "(static, a):"}}));
+              LifetimesAre({{"S::S", "(a, b):"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, StructConstructorStaticPtrMemberInitializer) {
-  // TODO(veluca): this is overly restrictive in the same way as
-  // StaticPointerOutParam.
   EXPECT_THAT(GetLifetimes(R"(
     static int x;
     struct [[clang::annotate("lifetime_params", "a")]] S {
@@ -566,7 +566,7 @@
       int* a = &x;
     };
   )"),
-              LifetimesAre({{"S::S", "(static, a):"}}));
+              LifetimesAre({{"S::S", "(a, b):"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, StructMemberFreeFunction) {
@@ -582,7 +582,7 @@
       a.a = &x;
     }
   )"),
-              LifetimesAre({{"S::f", "(static, a):"}, {"f", "(static, a)"}}));
+              LifetimesAre({{"S::f", "(a, b):"}, {"f", "(a, b)"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, ReturnFieldFromTemporaryStructConstructor) {
diff --git a/lifetime_analysis/test/recursion.cc b/lifetime_analysis/test/recursion.cc
index c8ebe2e..d7c6810 100644
--- a/lifetime_analysis/test/recursion.cc
+++ b/lifetime_analysis/test/recursion.cc
@@ -24,7 +24,7 @@
       return f(a);
     }
   )"),
-              LifetimesAre({{"f", "a -> b"}}));
+              LifetimesAre({{"f", "a -> static"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, FiniteDirectRecursion_1Pointee) {
diff --git a/lifetime_analysis/test/static_lifetime.cc b/lifetime_analysis/test/static_lifetime.cc
index 28841fa..5ba0f22 100644
--- a/lifetime_analysis/test/static_lifetime.cc
+++ b/lifetime_analysis/test/static_lifetime.cc
@@ -48,24 +48,13 @@
 }
 
 TEST_F(LifetimeAnalysisTest, StaticPointerOutParam) {
-  // TODO(mboehme): The lifetimes inferred here are overly restrictive. The
-  // function doesn't require the input that is passed in to have static
-  // lifetime, so it shouldn't enforce this condition on the caller. The
-  // lifetimes should be (a, b), and this would still allow the caller to
-  // substitute `static for a if desired.
-  // The root of the issue is that when we see a static lifetime in a points-to
-  // set, we don't know whether that means that
-  // - The pointer happens to point to something with static lifetime, but
-  //   nothing is depending on that, or
-  // - The pointer is required to point to something with static lifetime.
-
   EXPECT_THAT(GetLifetimes(R"(
     void f(int** p) {
       static int i = 42;
       *p = &i;
     }
   )"),
-              LifetimesAre({{"f", "(static, a)"}}));
+              LifetimesAre({{"f", "(a, b)"}}));
 }
 
 TEST_F(LifetimeAnalysisTest, MaybeReturnStaticStruct) {
diff --git a/lifetime_analysis/test/virtual_functions.cc b/lifetime_analysis/test/virtual_functions.cc
index 78eb244..18b7a92 100644
--- a/lifetime_analysis/test/virtual_functions.cc
+++ b/lifetime_analysis/test/virtual_functions.cc
@@ -177,8 +177,8 @@
 };
   )"),
               LifetimesContain({
-                  {"Base::f", "b: (static, a)"},
-                  {"Derived::f", "b: (static, a)"},
+                  {"Base::f", "c: (a, b)"},
+                  {"Derived::f", "c: (a, b)"},
               }));
 }