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)"},
}));
}