================
@@ -1202,5 +1284,198 @@ TEST_F(LifetimeAnalysisTest, LivenessOutsideLoop) {
EXPECT_THAT(Origins({"p"}), MaybeLiveAt("p1"));
}
+TEST_F(LifetimeAnalysisTest, SimpleReturnStackAddress) {
+ SetupTest(R"(
+ MyObj* target() {
+ MyObj s;
+ MyObj* p = &s;
+ POINT(p1);
+ return p;
+ }
+ )");
+ EXPECT_THAT("s", HasLiveLoanAtExpiry("p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, ConditionalAssignUnconditionalReturn) {
+ SetupTest(R"(
+ MyObj* target(bool c) {
+ MyObj s1;
+ MyObj* p = nullptr;
+ if (c) {
+ p = &s1;
+ }
+ POINT(P);
+ return p;
+ }
+ )");
+ EXPECT_THAT("s1", HasLiveLoanAtExpiry("P"));
+}
+
+TEST_F(LifetimeAnalysisTest, MultipleAssignments) {
+ SetupTest(R"(
+ MyObj* target() {
+ MyObj s;
+ MyObj* p1 = &s;
+ MyObj* p2 = &s;
+ POINT(P);
+ return p2;
+ }
+ )");
+ // Test if atleast one loan to "s" is live;
+ EXPECT_THAT("s", HasLiveLoanAtExpiry("P"));
+}
+
+TEST_F(LifetimeAnalysisTest, ConditionalAssignBothBranches) {
+ SetupTest(R"(
+ MyObj* target(bool c) {
+ MyObj s1;
+ static MyObj s2;
+ MyObj* p = nullptr;
+ if (c) {
+ p = &s1;
+ } else {
+ p = &s2;
+ }
+ POINT(P);
+ return p;
+ }
+ )");
+ EXPECT_THAT("s1", HasLiveLoanAtExpiry("P"));
+}
+
+TEST_F(LifetimeAnalysisTest, ReassignFromSafeToLocalThenReturn) {
+ SetupTest(R"(
+ MyObj* target() {
+ static MyObj safe_obj;
+ MyObj local_obj;
+ MyObj* p = &safe_obj;
+
+ p = &local_obj;
+ POINT(P);
+ return p;
+ }
+ )");
+ EXPECT_THAT("local_obj", HasLiveLoanAtExpiry("P"));
+}
+
+TEST_F(LifetimeAnalysisTest, PointerChainToLocal) {
+ SetupTest(R"(
+ MyObj* target() {
+ MyObj local_obj;
+ MyObj* p1 = &local_obj;
+ MyObj* p2 = p1;
+ POINT(P);
+ return p2;
+ }
+ )");
+ EXPECT_THAT("local_obj", HasLiveLoanAtExpiry("P"));
+}
+
+TEST_F(LifetimeAnalysisTest, MultipleAssignmentMultipleReturn) {
+ SetupTest(R"(
+ MyObj* target(bool c1, bool c2) {
+ static MyObj global_obj;
+ MyObj local_obj1;
+ MyObj local_obj2;
+ MyObj* p = nullptr;
+ if(c1){
+ p = &local_obj1;
+ POINT(C1);
+ return p;
+ }
+ else if(c2){
+ p = &local_obj2;
+ POINT(C2);
+ return p;
+ }
+ p = &global_obj;
+ POINT(C3);
+ return p;
+ }
+ )");
+
+ EXPECT_THAT("local_obj1", HasLiveLoanAtExpiry("C1"));
+ EXPECT_THAT("local_obj2", HasLiveLoanAtExpiry("C2"));
+
+ EXPECT_THAT("local_obj1", testing::Not(HasLiveLoanAtExpiry("C3")));
+ EXPECT_THAT("local_obj2", testing::Not(HasLiveLoanAtExpiry("C3")));
+}
+
+TEST_F(LifetimeAnalysisTest, MultipleAssignmentsSingleReturn) {
+ SetupTest(R"(
+ MyObj* target(bool c1, bool c2) {
+ static MyObj global_obj;
+ MyObj local_obj1;
+ MyObj local_obj2;
+ MyObj* p = nullptr;
+ if(c1){
+ p = &local_obj1;
+ }
+ else if(c2){
+ p = &local_obj2;
+ }
+ else{
+ p = &global_obj;
+ }
+ POINT(P);
+ return p;
+ }
+ )");
+ // Expect permissive warning at return statement with both local_obj1 and
+ // local_obj2 as culprit loans
+ EXPECT_THAT("local_obj1", HasLiveLoanAtExpiry("P"));
+ EXPECT_THAT("local_obj2", HasLiveLoanAtExpiry("P"));
+}
+
+TEST_F(LifetimeAnalysisTest, UseAfterScopeThenReturn) {
+ SetupTest(R"(
+ MyObj* target() {
+ MyObj* p;
+ {
+ MyObj local_obj;
+ p = &local_obj;
+ POINT(p1);
+ }
+ POINT(p2);
+ return p;
+ }
+ )");
+ // Expect a Use-after-scope warning because `p` in `return p` is a use even
+ // before return
+ EXPECT_THAT(Origin("p"), HasLoansTo({"local_obj"}, "p2"));
+ EXPECT_THAT(Origins({"p"}), MustBeLiveAt("p2"));
+
+ EXPECT_THAT(Origin("p"), HasLoansTo({"local_obj"}, "p1"));
+ EXPECT_THAT(Origins({"p"}), MustBeLiveAt("p1"));
+
+ EXPECT_THAT("local_obj", HasLiveLoanAtExpiry("p2"));
+}
+
+TEST_F(LifetimeAnalysisTest, ReturnBeforeUseAfterScope) {
+ SetupTest(R"(
+ MyObj* target(bool c) {
+ MyObj* p;
+ static MyObj global_obj;
+ {
+ MyObj local_obj;
+ p = &local_obj;
+ if(c){
+ POINT(p1);
+ return p;
+ }
+ }
+ POINT(p2);
+ return &global_obj;
+ }
+ )");
+ // Expect a return stack address warning as return is before use after scope
+ EXPECT_THAT("local_obj", HasLiveLoanAtExpiry("p1"));
+
+ EXPECT_THAT(NoOrigins(), AreLiveAt("p2"));
----------------
usx95 wrote:
I am confused: why are no origins alive here. An origin associated with the
expression `&global_obj` should have been live because it escapes.
Can you please add the list of generated for this function. Maybe I am missing
something.
https://github.com/llvm/llvm-project/pull/165370
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits