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());
}
}
return Block;
}
- bool IsReference = false;
bool HasTemporaries = false;
// Guard static initializers under a branch.
// 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());
}
}
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
-// 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)
}
+// 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