Make test more readable.

http://reviews.llvm.org/D4696

Files:
  lib/Analysis/CFG.cpp
  test/Analysis/cfg.cpp
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -1000,21 +1000,17 @@
   if (!BuildOpts.AddInitializers)
     return Block;
 
-  bool IsReference = false;
   bool HasTemporaries = false;
 
   // Destructors of temporaries in initialization expression should be called
   // after initialization finishes.
   Expr *Init = I->getInit();
   if (Init) {
-    if (FieldDecl *FD = I->getAnyMember())
-      IsReference = FD->getType()->isReferenceType();
     HasTemporaries = isa<ExprWithCleanups>(Init);
 
     if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
       // Generate destructors for temporaries in initialization expression.
-      VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
-          IsReference);
+      VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr());
     }
   }
 
@@ -1946,7 +1942,6 @@
     return Block;
   }
 
-  bool IsReference = false;
   bool HasTemporaries = false;
 
   // Guard static initializers under a branch.
@@ -1968,13 +1963,11 @@
   // after initialization finishes.
   Expr *Init = VD->getInit();
   if (Init) {
-    IsReference = VD->getType()->isReferenceType();
     HasTemporaries = isa<ExprWithCleanups>(Init);
 
     if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
       // Generate destructors for temporaries in initialization expression.
-      VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
-          IsReference);
+      VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr());
     }
   }
 
@@ -3492,13 +3485,32 @@
       E = cast<CastExpr>(E)->getSubExpr();
       goto tryAgain;
 
+    case Stmt::CXXFunctionalCastExprClass:
+      // For functional cast we want BindToTemporary to be passed further.
+      E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
+      goto tryAgain;
+
     case Stmt::ParenExprClass:
       E = cast<ParenExpr>(E)->getSubExpr();
       goto tryAgain;
 
-    case Stmt::MaterializeTemporaryExprClass:
-      E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr();
+    case Stmt::MaterializeTemporaryExprClass: {
+      const MaterializeTemporaryExpr* MTE = cast<MaterializeTemporaryExpr>(E);
+      BindToTemporary = (MTE->getStorageDuration() != SD_FullExpression);
+      SmallVector<const Expr *, 2> CommaLHSs;
+      SmallVector<SubobjectAdjustment, 2> Adjustments;
+      // Find the expression whose lifetime needs to be extended.
+      E = const_cast<Expr *>(
+          cast<MaterializeTemporaryExpr>(E)
+              ->GetTemporaryExpr()
+              ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+      // Visit the skipped comma operator left-hand sides for other temporaries.
+      for (const Expr *CommaLHS : CommaLHSs) {
+        VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
+                               /*BindToTemporary=*/false);
+      }
       goto tryAgain;
+    }
 
     case Stmt::BlockExprClass:
       // Don't recurse into blocks; their subexpressions don't get evaluated
Index: test/Analysis/cfg.cpp
===================================================================
--- test/Analysis/cfg.cpp
+++ test/Analysis/cfg.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 %s > %t 2>&1
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 %s > %t 2>&1
 // RUN: FileCheck --input-file=%t %s
 
 // CHECK-LABEL: void checkWrap(int i)
@@ -377,6 +377,61 @@
 }
 
 
+// CHECK-LABEL: void test_lifetime_extended_temporaries()
+// CHECK: [B1]
+struct LifetimeExtend { LifetimeExtend(int); ~LifetimeExtend(); };
+struct Aggregate { const LifetimeExtend a; const LifetimeExtend b; };
+struct AggregateRef { const LifetimeExtend &a; const LifetimeExtend &b; };
+void test_lifetime_extended_temporaries() {
+  // CHECK: LifetimeExtend(1);
+  // CHECK-NEXT: : 1
+  // CHECK-NEXT: ~LifetimeExtend()
+  // CHECK-NOT: ~LifetimeExtend()
+  {
+    const LifetimeExtend &l = LifetimeExtend(1);
+    1;
+  }
+  // CHECK: LifetimeExtend(2)
+  // CHECK-NEXT: ~LifetimeExtend()
+  // CHECK-NEXT: : 2
+  // CHECK-NOT: ~LifetimeExtend()
+  {
+    // No life-time extension.
+    const int &l = (LifetimeExtend(2), 2);
+    2;
+  }
+  // CHECK: LifetimeExtend(3)
+  // CHECK-NEXT: : 3
+  // CHECK-NEXT: ~LifetimeExtend()
+  // CHECK-NOT: ~LifetimeExtend()
+  {
+    // The last one is lifetime extended.
+    const LifetimeExtend &l = (3, LifetimeExtend(3));
+    3;
+  }
+  // CHECK: LifetimeExtend(4)
+  // CHECK-NEXT: ~LifetimeExtend()
+  // CHECK-NEXT: ~LifetimeExtend()
+  // CHECK-NEXT: : 4
+  // CHECK-NOT: ~LifetimeExtend()
+  {
+    Aggregate a{LifetimeExtend(4), LifetimeExtend(4)};
+    4;
+  }
+  // CHECK: LifetimeExtend(5)
+  // CHECK-NEXT: : 5
+  // FIXME: We want to emit the destructors of the lifetime
+  // extended variables here.
+  // CHECK-NOT: ~LifetimeExtend()
+  {
+    AggregateRef a{LifetimeExtend(5), LifetimeExtend(5)};
+    5;
+  }
+  // FIXME: Add tests for lifetime extension via subobject
+  // references (LifetimeExtend().some_member).
+}
+
+
 // CHECK-LABEL: int *PR18472()
 // CHECK: [B2 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B1
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to