From 3ef733230abb3cb8a8b7327fe8081525ffc5a61d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 27 Jul 2018 17:13:18 +0000 Subject: [PATCH] Add missing temporary materialization conversion on left-hand side of . in some member function calls. Specifically, when calling a conversion function, we would fail to create the AST node representing materialization of the class object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338135 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CFG.cpp | 8 +- lib/Sema/SemaExpr.cpp | 6 + lib/Sema/SemaExprCXX.cpp | 25 +- lib/Sema/SemaInit.cpp | 10 - lib/Sema/SemaOverload.cpp | 7 + test/Analysis/cfg-rich-constructors.cpp | 55 +-- test/Analysis/lambda-notes.cpp | 2 +- test/Analysis/temp-obj-dtors-cfg-output.cpp | 439 +++++++++--------- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp | 2 +- test/CodeGenCXX/stack-reuse-miscompile.cpp | 36 +- test/CodeGenObjCXX/literals.mm | 14 +- 11 files changed, 325 insertions(+), 279 deletions(-) diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index b895087e51..8a3ab15458 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -4408,9 +4408,11 @@ tryAgain: auto *LE = cast(E); CFGBlock *B = Block; for (Expr *Init : LE->capture_inits()) { - if (CFGBlock *R = VisitForTemporaryDtors( - Init, /*BindToTemporary=*/false, Context)) - B = R; + if (Init) { + if (CFGBlock *R = VisitForTemporaryDtors( + Init, /*BindToTemporary=*/false, Context)) + B = R; + } } return B; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index effaa888f0..60abd718e2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7138,6 +7138,10 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, E = E->IgnoreImpCasts(); E = E->IgnoreConversionOperator(); E = E->IgnoreImpCasts(); + if (auto *MTE = dyn_cast(E)) { + E = MTE->GetTemporaryExpr(); + E = E->IgnoreImpCasts(); + } // Built-in binary operator. if (BinaryOperator *OP = dyn_cast(E)) { @@ -7185,6 +7189,8 @@ static bool ExprLooksBoolean(Expr *E) { return OP->getOpcode() == UO_LNot; if (E->getType()->isPointerType()) return true; + // FIXME: What about overloaded operator calls returning "unspecified boolean + // type"s (commonly pointer-to-members)? return false; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 30876c09a9..a1168fa34d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -7114,10 +7114,17 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, CXXConversionDecl *Method, bool HadMultipleCandidates) { + // Convert the expression to match the conversion function's implicit object + // parameter. + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, + FoundDecl, Method); + if (Exp.isInvalid()) + return true; + if (Method->getParent()->isLambda() && Method->getConversionType()->isBlockPointerType()) { // This is a lambda coversion to block pointer; check if the argument - // is a LambdaExpr. + // was a LambdaExpr. Expr *SubE = E; CastExpr *CE = dyn_cast(SubE); if (CE && CE->getCastKind() == CK_NoOp) @@ -7134,22 +7141,16 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, DiagnosticErrorTrap Trap(Diags); PushExpressionEvaluationContext( ExpressionEvaluationContext::PotentiallyEvaluated); - ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(), - E->getExprLoc(), - Method, E); + ExprResult BlockExp = BuildBlockForLambdaConversion( + Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get()); PopExpressionEvaluationContext(); - if (Exp.isInvalid()) - Diag(E->getExprLoc(), diag::note_lambda_to_block_conv); - return Exp; + if (BlockExp.isInvalid()) + Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv); + return BlockExp; } } - ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, - FoundDecl, Method); - if (Exp.isInvalid()) - return true; - MemberExpr *ME = new (Context) MemberExpr( Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(), Context.BoundMemberTy, VK_RValue, OK_Ordinary); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0dddbdc36f..3ee5ec4a49 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -7406,16 +7406,6 @@ InitializationSequence::Perform(Sema &S, if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); - // FIXME: Should we move this initialization into a separate - // derived-to-base conversion? I believe the answer is "no", because - // we don't want to turn off access control here for c-style casts. - CurInit = S.PerformObjectArgumentInitialization(CurInit.get(), - /*Qualifier=*/nullptr, - FoundFn, Conversion); - if (CurInit.isInvalid()) - return ExprError(); - - // Build the actual call to the conversion function. CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, HadMultipleCandidates); if (CurInit.isInvalid()) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index a0b9498cdf..08af485ef4 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5165,6 +5165,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From, FromRecordType = From->getType(); DestType = ImplicitParamRecordType; FromClassification = From->Classify(Context); + + // When performing member access on an rvalue, materialize a temporary. + if (From->isRValue()) { + From = CreateMaterializeTemporaryExpr(FromRecordType, From, + Method->getRefQualifier() != + RefQualifierKind::RQ_RValue); + } } // Note that we always use the true parent context when performing diff --git a/test/Analysis/cfg-rich-constructors.cpp b/test/Analysis/cfg-rich-constructors.cpp index ce3e5f84ba..6780cf1a7b 100644 --- a/test/Analysis/cfg-rich-constructors.cpp +++ b/test/Analysis/cfg-rich-constructors.cpp @@ -464,14 +464,14 @@ void simpleTemporary() { C(); } -// TODO: Should provide construction context for the constructor, // CHECK: void temporaryInCondition() -// CHECK: 1: C() (CXXConstructExpr, class C) -// CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, NoOp, const class C) -// CHECK-NEXT: 3: [B2.2].operator bool -// CHECK-NEXT: 4: [B2.2] -// CHECK-NEXT: 5: [B2.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK-NEXT: T: if [B2.5] +// CHECK: 1: C() (CXXConstructExpr, [B2.2], class C) +// CHECK-NEXT: 2: [B2.1] +// CHECK-NEXT: 3: [B2.2] (ImplicitCastExpr, NoOp, const class C) +// CHECK-NEXT: 4: [B2.3].operator bool +// CHECK-NEXT: 5: [B2.3] +// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK-NEXT: T: if [B2.6] void temporaryInCondition() { if (C()); } @@ -583,14 +583,15 @@ void simpleTemporary() { } // CHECK: void temporaryInCondition() -// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B2.2], class temporary_object_expr_with_dtors::D) +// CHECK: 1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B2.2], [B2.3], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 2: [B2.1] (BindTemporary) -// CHECK-NEXT: 3: [B2.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) -// CHECK-NEXT: 4: [B2.3].operator bool -// CHECK-NEXT: 5: [B2.3] -// CHECK-NEXT: 6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK-NEXT: 7: ~temporary_object_expr_with_dtors::D() (Temporary object destructor) -// CHECK-NEXT: T: if [B2.6] +// CHECK-NEXT: 3: [B2.2] +// CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 5: [B2.4].operator bool +// CHECK-NEXT: 6: [B2.4] +// CHECK-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK-NEXT: 8: ~temporary_object_expr_with_dtors::D() (Temporary object destructor) +// CHECK-NEXT: T: if [B2.7] void temporaryInCondition() { if (D()); } @@ -693,23 +694,25 @@ void referenceWithFunctionalCast() { // Test the condition constructor, we don't care about branch constructors here. // CHECK: void constructorInTernaryCondition() // CXX11: 1: 1 -// CXX11-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], [B7.5], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 3: [B7.2] (BindTemporary) // CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B7.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) -// CXX11-NEXT: 5: [B7.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) -// CXX11-NEXT: 6: [B7.5].operator bool -// CXX11-NEXT: 7: [B7.5] -// CXX11-NEXT: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11-NEXT: T: [B7.8] ? ... : ... +// CXX11-NEXT: 5: [B7.4] +// CXX11-NEXT: 6: [B7.5] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CXX11-NEXT: 7: [B7.6].operator bool +// CXX11-NEXT: 8: [B7.6] +// CXX11-NEXT: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CXX11-NEXT: T: [B7.9] ? ... : ... // CXX17: 1: 1 -// CXX17-NEXT: 2: [B4.1] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D) +// CXX17-NEXT: 2: [B4.1] (CXXConstructExpr, [B4.3], [B4.5], class temporary_object_expr_with_dtors::D) // CXX17-NEXT: 3: [B4.2] (BindTemporary) // CXX17-NEXT: 4: temporary_object_expr_with_dtors::D([B4.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) -// CXX17-NEXT: 5: [B4.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) -// CXX17-NEXT: 6: [B4.5].operator bool -// CXX17-NEXT: 7: [B4.5] -// CXX17-NEXT: 8: [B4.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX17-NEXT: T: [B4.8] ? ... : ... +// CXX17-NEXT: 5: [B4.4] +// CXX17-NEXT: 6: [B4.5] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CXX17-NEXT: 7: [B4.6].operator bool +// CXX17-NEXT: 8: [B4.6] +// CXX17-NEXT: 9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CXX17-NEXT: T: [B4.9] ? ... : ... void constructorInTernaryCondition() { const D &d = D(1) ? D(2) : D(3); } diff --git a/test/Analysis/lambda-notes.cpp b/test/Analysis/lambda-notes.cpp index 7abff35df1..d4318284df 100644 --- a/test/Analysis/lambda-notes.cpp +++ b/test/Analysis/lambda-notes.cpp @@ -69,7 +69,7 @@ void diagnosticFromLambda() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: line12 -// CHECK-NEXT: col5 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp index e2c6267630..d08b01cd39 100644 --- a/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -311,44 +311,48 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) // CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2].operator int -// CHECK: 4: [B1.2] -// CHECK: 5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int) -// WARNINGS: 7: B() (CXXConstructExpr, class B) -// ANALYZER: 7: B() (CXXConstructExpr, [B1.8], class B) -// CHECK: 8: [B1.7] (BindTemporary) -// CHECK: 9: [B1.8].operator int -// CHECK: 10: [B1.8] -// CHECK: 11: [B1.10] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 12: int([B1.11]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 13: [B1.6] + [B1.12] -// CHECK: 14: int a = int(A()) + int(B()); -// CHECK: 15: ~B() (Temporary object destructor) -// CHECK: 16: ~A() (Temporary object destructor) -// CHECK: 17: foo -// CHECK: 18: [B1.17] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) -// WARNINGS: 19: A() (CXXConstructExpr, class A) -// ANALYZER: 19: A() (CXXConstructExpr, [B1.20], class A) -// CHECK: 20: [B1.19] (BindTemporary) -// CHECK: 21: [B1.20].operator int -// CHECK: 22: [B1.20] -// CHECK: 23: [B1.22] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 24: int([B1.23]) (CXXFunctionalCastExpr, NoOp, int) -// WARNINGS: 25: B() (CXXConstructExpr, class B) -// ANALYZER: 25: B() (CXXConstructExpr, [B1.26], class B) -// CHECK: 26: [B1.25] (BindTemporary) -// CHECK: 27: [B1.26].operator int -// CHECK: 28: [B1.26] -// CHECK: 29: [B1.28] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 30: int([B1.29]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 31: [B1.24] + [B1.30] -// CHECK: 32: [B1.18]([B1.31]) -// CHECK: 33: ~B() (Temporary object destructor) -// CHECK: 34: ~A() (Temporary object destructor) -// CHECK: 35: int b; +// CHECK: 3: [B1.2] +// CHECK: 4: [B1.3].operator int +// CHECK: 5: [B1.3] +// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 7: int([B1.6]) (CXXFunctionalCastExpr, NoOp, int) +// WARNINGS: 8: B() (CXXConstructExpr, class B) +// ANALYZER: 8: B() (CXXConstructExpr, [B1.9], [B1.10], class B) +// CHECK: 9: [B1.8] (BindTemporary) +// CHECK: 10: [B1.9] +// CHECK: 11: [B1.10].operator int +// CHECK: 12: [B1.10] +// CHECK: 13: [B1.12] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 15: [B1.7] + [B1.14] +// CHECK: 16: int a = int(A()) + int(B()); +// CHECK: 17: ~B() (Temporary object destructor) +// CHECK: 18: ~A() (Temporary object destructor) +// CHECK: 19: foo +// CHECK: 20: [B1.19] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) +// WARNINGS: 21: A() (CXXConstructExpr, class A) +// ANALYZER: 21: A() (CXXConstructExpr, [B1.22], [B1.23], class A) +// CHECK: 22: [B1.21] (BindTemporary) +// CHECK: 23: [B1.22] +// CHECK: 24: [B1.23].operator int +// CHECK: 25: [B1.23] +// CHECK: 26: [B1.25] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 27: int([B1.26]) (CXXFunctionalCastExpr, NoOp, int) +// WARNINGS: 28: B() (CXXConstructExpr, class B) +// ANALYZER: 28: B() (CXXConstructExpr, [B1.29], [B1.30], class B) +// CHECK: 29: [B1.28] (BindTemporary) +// CHECK: 30: [B1.29] +// CHECK: 31: [B1.30].operator int +// CHECK: 32: [B1.30] +// CHECK: 33: [B1.32] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 34: int([B1.33]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 35: [B1.27] + [B1.34] +// CHECK: 36: [B1.20]([B1.35]) +// CHECK: 37: ~B() (Temporary object destructor) +// CHECK: 38: ~A() (Temporary object destructor) +// CHECK: 39: int b; // CHECK: Preds (1): B2 // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] @@ -365,18 +369,19 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.8] && [B4.5] +// CHECK: 1: [B5.9] && [B4.6] // CHECK: 2: [B5.3]([B3.1]) // CHECK: T: (Temp Dtor) [B4.2] // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], [B4.3], class B) // CHECK: 2: [B4.1] (BindTemporary) -// CHECK: 3: [B4.2].operator bool -// CHECK: 4: [B4.2] -// CHECK: 5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B4.2] +// CHECK: 4: [B4.3].operator bool +// CHECK: 5: [B4.3] +// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B5 // CHECK: Succs (1): B3 // CHECK: [B5] @@ -384,12 +389,13 @@ const C &bar3(bool coin) { // CHECK: 2: foo // CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) // WARNINGS: 4: A() (CXXConstructExpr, class A) -// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], class A) +// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], [B5.6], class A) // CHECK: 5: [B5.4] (BindTemporary) -// CHECK: 6: [B5.5].operator bool -// CHECK: 7: [B5.5] -// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B5.8] && ... +// CHECK: 6: [B5.5] +// CHECK: 7: [B5.6].operator bool +// CHECK: 8: [B5.6] +// CHECK: 9: [B5.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B5.9] && ... // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B4 B3 // CHECK: [B6] @@ -397,28 +403,30 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: [B9.5] && [B8.5] +// CHECK: 1: [B9.6] && [B8.6] // CHECK: 2: bool a = A() && B(); // CHECK: T: (Temp Dtor) [B8.2] // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], [B8.3], class B) // CHECK: 2: [B8.1] (BindTemporary) -// CHECK: 3: [B8.2].operator bool -// CHECK: 4: [B8.2] -// CHECK: 5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B8.2] +// CHECK: 4: [B8.3].operator bool +// CHECK: 5: [B8.3] +// CHECK: 6: [B8.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], [B9.3], class A) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator bool -// CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B9.5] && ... +// CHECK: 3: [B9.2] +// CHECK: 4: [B9.3].operator bool +// CHECK: 5: [B9.3] +// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B9.6] && ... // CHECK: Preds (1): B10 // CHECK: Succs (2): B8 B7 // CHECK: [B0 (EXIT)] @@ -435,18 +443,19 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.8] || [B4.5] +// CHECK: 1: [B5.9] || [B4.6] // CHECK: 2: [B5.3]([B3.1]) // CHECK: T: (Temp Dtor) [B4.2] // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B4.2], [B4.3], class B) // CHECK: 2: [B4.1] (BindTemporary) -// CHECK: 3: [B4.2].operator bool -// CHECK: 4: [B4.2] -// CHECK: 5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B4.2] +// CHECK: 4: [B4.3].operator bool +// CHECK: 5: [B4.3] +// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B5 // CHECK: Succs (1): B3 // CHECK: [B5] @@ -454,12 +463,13 @@ const C &bar3(bool coin) { // CHECK: 2: foo // CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) // WARNINGS: 4: A() (CXXConstructExpr, class A) -// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], class A) +// ANALYZER: 4: A() (CXXConstructExpr, [B5.5], [B5.6], class A) // CHECK: 5: [B5.4] (BindTemporary) -// CHECK: 6: [B5.5].operator bool -// CHECK: 7: [B5.5] -// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B5.8] || ... +// CHECK: 6: [B5.5] +// CHECK: 7: [B5.6].operator bool +// CHECK: 8: [B5.6] +// CHECK: 9: [B5.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B5.9] || ... // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B3 B4 // CHECK: [B6] @@ -467,28 +477,30 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: [B9.5] || [B8.5] +// CHECK: 1: [B9.6] || [B8.6] // CHECK: 2: bool a = A() || B(); // CHECK: T: (Temp Dtor) [B8.2] // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B8.2], [B8.3], class B) // CHECK: 2: [B8.1] (BindTemporary) -// CHECK: 3: [B8.2].operator bool -// CHECK: 4: [B8.2] -// CHECK: 5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 3: [B8.2] +// CHECK: 4: [B8.3].operator bool +// CHECK: 5: [B8.3] +// CHECK: 6: [B8.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B9.2], [B9.3], class A) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator bool -// CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B9.5] || ... +// CHECK: 3: [B9.2] +// CHECK: 4: [B9.3].operator bool +// CHECK: 5: [B9.3] +// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B9.6] || ... // CHECK: Preds (1): B10 // CHECK: Succs (2): B7 B8 // CHECK: [B0 (EXIT)] @@ -517,13 +529,14 @@ const C &bar3(bool coin) { // CHECK: [B4] // CHECK: 1: ~B() (Temporary object destructor) // WARNINGS: 2: B() (CXXConstructExpr, class B) -// ANALYZER: 2: B() (CXXConstructExpr, [B4.3], class B) +// ANALYZER: 2: B() (CXXConstructExpr, [B4.3], [B4.4], class B) // CHECK: 3: [B4.2] (BindTemporary) -// CHECK: 4: [B4.3].operator bool -// CHECK: 5: [B4.3] -// CHECK: 6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: 7: ~B() (Temporary object destructor) -// CHECK: T: if [B4.6] +// CHECK: 4: [B4.3] +// CHECK: 5: [B4.4].operator bool +// CHECK: 6: [B4.4] +// CHECK: 7: [B4.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 8: ~B() (Temporary object destructor) +// CHECK: T: if [B4.7] // CHECK: Preds (2): B5 B6 // CHECK: Succs (2): B3 B2 // CHECK: [B5] @@ -539,7 +552,7 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 // CHECK: [B7] -// CHECK: 1: [B10.5] ? [B8.6] : [B9.15] +// CHECK: 1: [B10.6] ? [B8.6] : [B9.16] // CHECK: 2: [B7.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B7.2] // WARNINGS: 4: [B7.3] (CXXConstructExpr, class A) @@ -561,33 +574,35 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B7 // CHECK: [B9] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B9.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B9.2], [B9.3], class B) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator A -// CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, class A) -// CHECK: 6: [B9.5] (BindTemporary) -// CHECK: 7: [B9.6] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 8: [B9.7] -// WARNINGS: 9: [B9.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B9.8] (CXXConstructExpr, [B9.10], [B9.13], [B9.14], class A) -// CHECK: 10: [B9.9] (BindTemporary) -// CHECK: 11: A([B9.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) -// CHECK: 12: [B9.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B9.12] -// WARNINGS: 14: [B9.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], [B7.4], class A) -// CHECK: 15: [B9.14] (BindTemporary) +// CHECK: 3: [B9.2] +// CHECK: 4: [B9.3].operator A +// CHECK: 5: [B9.3] +// CHECK: 6: [B9.5] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 7: [B9.6] (BindTemporary) +// CHECK: 8: [B9.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 9: [B9.8] +// WARNINGS: 10: [B9.9] (CXXConstructExpr, class A) +// ANALYZER: 10: [B9.9] (CXXConstructExpr, [B9.11], [B9.14], [B9.15], class A) +// CHECK: 11: [B9.10] (BindTemporary) +// CHECK: 12: A([B9.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 13: [B9.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 14: [B9.13] +// WARNINGS: 15: [B9.14] (CXXConstructExpr, class A) +// ANALYZER: 15: [B9.14] (CXXConstructExpr, [B9.16], [B7.3], [B7.4], class A) +// CHECK: 16: [B9.15] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 // CHECK: [B10] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B10.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B10.2], [B10.3], class B) // CHECK: 2: [B10.1] (BindTemporary) -// CHECK: 3: [B10.2].operator bool -// CHECK: 4: [B10.2] -// CHECK: 5: [B10.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B10.5] ? ... : ... +// CHECK: 3: [B10.2] +// CHECK: 4: [B10.3].operator bool +// CHECK: 5: [B10.3] +// CHECK: 6: [B10.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B10.6] ? ... : ... // CHECK: Preds (1): B11 // CHECK: Succs (2): B8 B9 // CHECK: [B0 (EXIT)] @@ -650,13 +665,14 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B0 // CHECK: [B3] // WARNINGS: 1: C() (CXXConstructExpr, struct C) -// ANALYZER: 1: C() (CXXConstructExpr, [B3.2], struct C) +// ANALYZER: 1: C() (CXXConstructExpr, [B3.2], [B3.3], struct C) // CHECK: 2: [B3.1] (BindTemporary) -// CHECK: 3: [B3.2].operator bool -// CHECK: 4: [B3.2] -// CHECK: 5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: 6: ~C() (Temporary object destructor) -// CHECK: T: if [B3.5] +// CHECK: 3: [B3.2] +// CHECK: 4: [B3.3].operator bool +// CHECK: 5: [B3.3] +// CHECK: 6: [B3.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: 7: ~C() (Temporary object destructor) +// CHECK: T: if [B3.6] // CHECK: Preds (1): B4 // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] @@ -710,11 +726,13 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B3 // CHECK: Succs (1): B0 // CHECK: [B3] -// CHECK: 1: D() (CXXConstructExpr, struct D) -// CHECK: 2: [B3.1].operator bool -// CHECK: 3: [B3.1] -// CHECK: 4: [B3.3] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: if [B3.4] +// WARNINGS: 1: D() (CXXConstructExpr, struct D) +// ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D) +// CHECK: 2: [B3.1] +// CHECK: 3: [B3.2].operator bool +// CHECK: 4: [B3.2] +// CHECK: 5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: if [B3.5] // CHECK: Preds (1): B4 // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] @@ -780,7 +798,7 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] -// CHECK: 1: [B7.8] ? [B5.6] : [B6.15] +// CHECK: 1: [B7.9] ? [B5.6] : [B6.16] // CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B4.2] // CHECK: 4: [B7.3]([B4.3]) @@ -800,23 +818,24 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B4 // CHECK: [B6] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B6.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B6.2], [B6.3], class B) // CHECK: 2: [B6.1] (BindTemporary) -// CHECK: 3: [B6.2].operator A -// CHECK: 4: [B6.2] -// CHECK: 5: [B6.4] (ImplicitCastExpr, UserDefinedConversion, class A) -// CHECK: 6: [B6.5] (BindTemporary) -// CHECK: 7: [B6.6] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 8: [B6.7] -// WARNINGS: 9: [B6.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B6.8] (CXXConstructExpr, [B6.10], [B6.13], [B6.14], class A) -// CHECK: 10: [B6.9] (BindTemporary) -// CHECK: 11: A([B6.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) -// CHECK: 12: [B6.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B6.12] -// WARNINGS: 14: [B6.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B6.13] (CXXConstructExpr, [B6.15], [B4.3], class A) -// CHECK: 15: [B6.14] (BindTemporary) +// CHECK: 3: [B6.2] +// CHECK: 4: [B6.3].operator A +// CHECK: 5: [B6.3] +// CHECK: 6: [B6.5] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 7: [B6.6] (BindTemporary) +// CHECK: 8: [B6.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 9: [B6.8] +// WARNINGS: 10: [B6.9] (CXXConstructExpr, class A) +// ANALYZER: 10: [B6.9] (CXXConstructExpr, [B6.11], [B6.14], [B6.15], class A) +// CHECK: 11: [B6.10] (BindTemporary) +// CHECK: 12: A([B6.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 13: [B6.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 14: [B6.13] +// WARNINGS: 15: [B6.14] (CXXConstructExpr, class A) +// ANALYZER: 15: [B6.14] (CXXConstructExpr, [B6.16], [B4.3], class A) +// CHECK: 16: [B6.15] (BindTemporary) // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 // CHECK: [B7] @@ -824,12 +843,13 @@ const C &bar3(bool coin) { // CHECK: 2: foo // CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) // WARNINGS: 4: B() (CXXConstructExpr, class B) -// ANALYZER: 4: B() (CXXConstructExpr, [B7.5], class B) +// ANALYZER: 4: B() (CXXConstructExpr, [B7.5], [B7.6], class B) // CHECK: 5: [B7.4] (BindTemporary) -// CHECK: 6: [B7.5].operator bool -// CHECK: 7: [B7.5] -// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B7.8] ? ... : ... +// CHECK: 6: [B7.5] +// CHECK: 7: [B7.6].operator bool +// CHECK: 8: [B7.6] +// CHECK: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.9] ? ... : ... // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] @@ -843,7 +863,7 @@ const C &bar3(bool coin) { // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 // CHECK: [B10] -// CHECK: 1: [B13.5] ? [B11.6] : [B12.15] +// CHECK: 1: [B13.6] ? [B11.6] : [B12.16] // CHECK: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B10.2] // CHECK: 4: const A &a = B() ? A() : A(B()); @@ -863,33 +883,35 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B10 // CHECK: [B12] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B12.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B12.2], [B12.3], class B) // CHECK: 2: [B12.1] (BindTemporary) -// CHECK: 3: [B12.2].operator A -// CHECK: 4: [B12.2] -// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, class A) -// CHECK: 6: [B12.5] (BindTemporary) -// CHECK: 7: [B12.6] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 8: [B12.7] -// WARNINGS: 9: [B12.8] (CXXConstructExpr, class A) -// ANALYZER: 9: [B12.8] (CXXConstructExpr, [B12.10], [B12.13], [B12.14], class A) -// CHECK: 10: [B12.9] (BindTemporary) -// CHECK: 11: A([B12.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) -// CHECK: 12: [B12.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B12.12] -// WARNINGS: 14: [B12.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B12.13] (CXXConstructExpr, [B10.3], class A) -// CHECK: 15: [B12.14] (BindTemporary) +// CHECK: 3: [B12.2] +// CHECK: 4: [B12.3].operator A +// CHECK: 5: [B12.3] +// CHECK: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 7: [B12.6] (BindTemporary) +// CHECK: 8: [B12.7] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 9: [B12.8] +// WARNINGS: 10: [B12.9] (CXXConstructExpr, class A) +// ANALYZER: 10: [B12.9] (CXXConstructExpr, [B12.11], [B12.14], [B12.15], class A) +// CHECK: 11: [B12.10] (BindTemporary) +// CHECK: 12: A([B12.11]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 13: [B12.12] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 14: [B12.13] +// WARNINGS: 15: [B12.14] (CXXConstructExpr, class A) +// ANALYZER: 15: [B12.14] (CXXConstructExpr, [B10.3], class A) +// CHECK: 16: [B12.15] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 // CHECK: [B13] // WARNINGS: 1: B() (CXXConstructExpr, class B) -// ANALYZER: 1: B() (CXXConstructExpr, [B13.2], class B) +// ANALYZER: 1: B() (CXXConstructExpr, [B13.2], [B13.3], class B) // CHECK: 2: [B13.1] (BindTemporary) -// CHECK: 3: [B13.2].operator bool -// CHECK: 4: [B13.2] -// CHECK: 5: [B13.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B13.5] ? ... : ... +// CHECK: 3: [B13.2] +// CHECK: 4: [B13.3].operator bool +// CHECK: 5: [B13.3] +// CHECK: 6: [B13.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B13.6] ? ... : ... // CHECK: Preds (1): B14 // CHECK: Succs (2): B11 B12 // CHECK: [B0 (EXIT)] @@ -949,15 +971,11 @@ const C &bar3(bool coin) { // ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B7.2], [B7.3], class A) // ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B7.2], class A) // CHECK: 2: [B7.1] (BindTemporary) -// CXX98: 3: [B7.2].operator bool -// CXX98: 4: [B7.2] -// CXX98: 5: [B7.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX98: T: [B7.5] ? ... : ... -// CXX11: 3: [B7.2] -// CXX11: 4: [B7.3].operator bool -// CXX11: 5: [B7.3] -// CXX11: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11: T: [B7.6] ? ... : ... +// CHECK: 3: [B7.2] +// CHECK: 4: [B7.3].operator bool +// CHECK: 5: [B7.3] +// CHECK: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.6] ? ... : ... // CHECK: Preds (1): B8 // CHECK: Succs (2): B5 B6 // CHECK: [B0 (EXIT)] @@ -1017,15 +1035,11 @@ const C &bar3(bool coin) { // ANALYZER-CXX98: 3: A() (CXXConstructExpr, [B7.4], class A) // ANALYZER-CXX11: 3: A() (CXXConstructExpr, class A) // CHECK: 4: [B7.3] (BindTemporary) -// CXX98: 5: [B7.4].operator bool -// CXX98: 6: [B7.4] -// CXX98: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX98: T: [B7.7] ? ... : ... -// CXX11: 5: [B7.4] -// CXX11: 6: [B7.5].operator bool -// CXX11: 7: [B7.5] -// CXX11: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11: T: [B7.8] ? ... : ... +// CHECK: 5: [B7.4] +// CHECK: 6: [B7.5].operator bool +// CHECK: 7: [B7.5] +// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.8] ? ... : ... // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] @@ -1069,15 +1083,11 @@ const C &bar3(bool coin) { // ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B12.2], [B12.3], class A) // ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B12.2], class A) // CHECK: 2: [B12.1] (BindTemporary) -// CXX98: 3: [B12.2].operator bool -// CXX98: 4: [B12.2] -// CXX98: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX98: T: [B12.5] ? ... : ... -// CXX11: 3: [B12.2] -// CXX11: 4: [B12.3].operator bool -// CXX11: 5: [B12.3] -// CXX11: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CXX11: T: [B12.6] ? ... : ... +// CHECK: 3: [B12.2] +// CHECK: 4: [B12.3].operator bool +// CHECK: 5: [B12.3] +// CHECK: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B12.6] ? ... : ... // CHECK: Preds (1): B13 // CHECK: Succs (2): B10 B11 // CHECK: [B0 (EXIT)] @@ -1177,15 +1187,16 @@ const C &bar3(bool coin) { // CHECK: [B1] // CHECK: 1: int a; // WARNINGS: 2: A() (CXXConstructExpr, class A) -// ANALYZER: 2: A() (CXXConstructExpr, [B1.3], class A) +// ANALYZER: 2: A() (CXXConstructExpr, [B1.3], [B1.4], class A) // CHECK: 3: [B1.2] (BindTemporary) -// CHECK: 4: [B1.3].operator int -// CHECK: 5: [B1.3] -// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 7: a -// CHECK: 8: [B1.7] = [B1.6] -// CHECK: 9: ~A() (Temporary object destructor) -// CHECK: 10: int b; +// CHECK: 4: [B1.3] +// CHECK: 5: [B1.4].operator int +// CHECK: 6: [B1.4] +// CHECK: 7: [B1.6] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 8: a +// CHECK: 9: [B1.8] = [B1.7] +// CHECK: 10: ~A() (Temporary object destructor) +// CHECK: 11: int b; // CHECK: Preds (1): B2 // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] @@ -1194,25 +1205,27 @@ const C &bar3(bool coin) { // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) // CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2].operator int -// CHECK: 4: [B1.2] -// CHECK: 5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int) -// WARNINGS: 7: B() (CXXConstructExpr, class B) -// ANALYZER: 7: B() (CXXConstructExpr, [B1.8], class B) -// CHECK: 8: [B1.7] (BindTemporary) -// CHECK: 9: [B1.8].operator int -// CHECK: 10: [B1.8] -// CHECK: 11: [B1.10] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 12: int([B1.11]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 13: [B1.6] + [B1.12] -// CHECK: 14: a([B1.13]) (Member initializer) -// CHECK: 15: ~B() (Temporary object destructor) -// CHECK: 16: ~A() (Temporary object destructor) -// CHECK: 17: /*implicit*/(int)0 -// CHECK: 18: b([B1.17]) (Member initializer) +// CHECK: 3: [B1.2] +// CHECK: 4: [B1.3].operator int +// CHECK: 5: [B1.3] +// CHECK: 6: [B1.5] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 7: int([B1.6]) (CXXFunctionalCastExpr, NoOp, int) +// WARNINGS: 8: B() (CXXConstructExpr, class B) +// ANALYZER: 8: B() (CXXConstructExpr, [B1.9], [B1.10], class B) +// CHECK: 9: [B1.8] (BindTemporary) +// CHECK: 10: [B1.9] +// CHECK: 11: [B1.10].operator int +// CHECK: 12: [B1.10] +// CHECK: 13: [B1.12] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 15: [B1.7] + [B1.14] +// CHECK: 16: a([B1.15]) (Member initializer) +// CHECK: 17: ~B() (Temporary object destructor) +// CHECK: 18: ~A() (Temporary object destructor) +// CHECK: 19: /*implicit*/(int)0 +// CHECK: 20: b([B1.19]) (Member initializer) // CHECK: Preds (1): B2 // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp index 370f732fd9..88ad6a4a3c 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -35,7 +35,7 @@ template struct ConstexprMember { constexpr R F() const { return 0; } }; constexpr int d = ConstexprMember().F(); // ok -constexpr int e = ConstexprMember().F(); // expected-error {{constant expression}} expected-note {{non-literal type 'const NonLiteral' cannot be used in a constant expression}} +constexpr int e = ConstexprMember().F(); // expected-error {{constant expression}} expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} template struct ConstexprCtor { constexpr ConstexprCtor(P...) {} diff --git a/test/CodeGenCXX/stack-reuse-miscompile.cpp b/test/CodeGenCXX/stack-reuse-miscompile.cpp index 3b860a5739..4e824d94f5 100644 --- a/test/CodeGenCXX/stack-reuse-miscompile.cpp +++ b/test/CodeGenCXX/stack-reuse-miscompile.cpp @@ -1,8 +1,4 @@ -// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s - -// This test should not to generate llvm.lifetime.start/llvm.lifetime.end for -// f function because all temporary objects in this function are used for the -// final result +// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -disable-llvm-passes -std=c++03 %s -o - | FileCheck %s --implicit-check-not=llvm.lifetime class S { char *ptr; @@ -23,14 +19,36 @@ public: const char * f(S s) { +// It's essential that the lifetimes of all three T temporaries here are +// overlapping. They must all remain alive through the call to str(). +// // CHECK: [[T1:%.*]] = alloca %class.T, align 4 // CHECK: [[T2:%.*]] = alloca %class.T, align 4 // CHECK: [[T3:%.*]] = alloca %class.T, align 4 -// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T1]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) -// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T2]], [2 x i32] %{{.*}}) -// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T3]], %class.T* [[T1]], %class.T* dereferenceable(16) [[T2]]) -// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T3]]) +// +// FIXME: We could defer starting the lifetime of the return object of concat +// until the call. +// CHECK: [[T1i8:%.*]] = bitcast %class.T* [[T1]] to i8* +// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T1i8]]) +// +// CHECK: [[T2i8:%.*]] = bitcast %class.T* [[T2]] to i8* +// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T2i8]]) +// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T2]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) +// +// CHECK: [[T3i8:%.*]] = bitcast %class.T* [[T3]] to i8* +// CHECK: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[T3i8]]) +// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T3]], [2 x i32] %{{.*}}) +// +// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T1]], %class.T* [[T2]], %class.T* dereferenceable(16) [[T3]]) +// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T1]]) +// +// CHECK: call void @llvm.lifetime.end.p0i8( +// CHECK: call void @llvm.lifetime.end.p0i8( +// CHECK: call void @llvm.lifetime.end.p0i8( // CHECK: ret i8* [[T6]] return T("[").concat(T(s)).str(); } + +// CHECK: declare {{.*}}llvm.lifetime.start +// CHECK: declare {{.*}}llvm.lifetime.end diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm index 6a112312bd..a42070b00c 100644 --- a/test/CodeGenObjCXX/literals.mm +++ b/test/CodeGenObjCXX/literals.mm @@ -18,19 +18,25 @@ struct Y { void test_array() { // CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8* // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*] + // CHECK: [[TMPX:%[a-zA-Z0-9.]+]] = alloca % + // CHECK: [[TMPY:%[a-zA-Z0-9.]+]] = alloca % // Initializing first element // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]]) // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 - // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK-NEXT: [[TMP_CAST:%.*]] = bitcast {{.*}} [[TMPX]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]]) + // CHECK-NEXT: call void @_ZN1XC1Ev({{.*}} [[TMPX]]) // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 - // CHECK-NEXT: invoke void @_ZN1YC1Ev + // CHECK-NEXT: [[TMP_CAST:%.*]] = bitcast {{.*}} [[TMPY]] to i8* + // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP_CAST]]) + // CHECK-NEXT: invoke void @_ZN1YC1Ev({{.*}} [[TMPY]]) // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] @@ -75,14 +81,14 @@ void test_array_instantiation() { // CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]]) // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0 - // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK: call void @_ZN1XC1Ev // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] // Initializing the second element // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 1 - // CHECK-NEXT: invoke void @_ZN1YC1Ev + // CHECK: invoke void @_ZN1YC1Ev // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] -- 2.40.0