Index: include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -95,6 +95,8 @@ void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B, ExplodedNode *Pred); + void HandleBindTemporary(const CXXBindTemporaryExpr *BTE, const CFGBlock *B, + ExplodedNode *Pred); /// Handle conditional logic for running static initializers. void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -227,6 +227,14 @@ const CFGBlock *DstT, const CFGBlock *DstF) override; + /// Called by CoreEngine. + /// Used to generate successor nodes for temporary destructors depending + /// on whether the corresponding constructor was visited. + void processBindTemporary(const CXXBindTemporaryExpr *BTE, + NodeBuilderContext &BldCtx, ExplodedNode *Pred, + ExplodedNodeSet &Dst, const CFGBlock *DstT, + const CFGBlock *DstF) override; + /// Called by CoreEngine. Used to processing branching behavior /// at static initalizers. void processStaticInitializer(const DeclStmt *DS, @@ -408,7 +416,11 @@ void VisitIncrementDecrementOperator(const UnaryOperator* U, ExplodedNode *Pred, ExplodedNodeSet &Dst); - + + void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, + ExplodedNode *Pred, ExplodedNodeSet &PreVisit, + ExplodedNodeSet &Dst); + void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst); Index: include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -72,6 +72,15 @@ const CFGBlock *DstT, const CFGBlock *DstF) = 0; + /// Called by CoreEngine. + /// Used to generate successor nodes for temporary destructors depending + /// on whether the corresponding constructor was visited. + virtual void processBindTemporary(const CXXBindTemporaryExpr *BTE, + NodeBuilderContext &BldCtx, + ExplodedNode *Pred, ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) = 0; + /// Called by CoreEngine. Used to processing branching behavior /// at static initalizers. virtual void processStaticInitializer(const DeclStmt *DS, Index: lib/Analysis/CFG.cpp =================================================================== --- lib/Analysis/CFG.cpp +++ lib/Analysis/CFG.cpp @@ -3517,57 +3517,6 @@ } CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { - if (E->isLogicalOp()) { - // Destructors for temporaries in LHS expression should be called after - // those for RHS expression. Even if this will unnecessarily create a block, - // this block will be used at least by the full expression. - autoCreateBlock(); - CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); - if (badCFG) - return nullptr; - - Succ = ConfluenceBlock; - Block = nullptr; - CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); - - if (RHSBlock) { - if (badCFG) - return nullptr; - - // If RHS expression did produce destructors we need to connect created - // blocks to CFG in same manner as for binary operator itself. - CFGBlock *LHSBlock = createBlock(false); - LHSBlock->setTerminator(CFGTerminator(E, true)); - - // For binary operator LHS block is before RHS in list of predecessors - // of ConfluenceBlock. - std::reverse(ConfluenceBlock->pred_begin(), - ConfluenceBlock->pred_end()); - - // See if this is a known constant. - TryResult KnownVal = tryEvaluateBool(E->getLHS()); - if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) - KnownVal.negate(); - - // Link LHSBlock with RHSBlock exactly the same way as for binary operator - // itself. - if (E->getOpcode() == BO_LOr) { - addSuccessor(LHSBlock, KnownVal.isTrue() ? nullptr : ConfluenceBlock); - addSuccessor(LHSBlock, KnownVal.isFalse() ? nullptr : RHSBlock); - } else { - assert (E->getOpcode() == BO_LAnd); - addSuccessor(LHSBlock, KnownVal.isFalse() ? nullptr : RHSBlock); - addSuccessor(LHSBlock, KnownVal.isTrue() ? nullptr : ConfluenceBlock); - } - - Block = LHSBlock; - return LHSBlock; - } - - Block = ConfluenceBlock; - return ConfluenceBlock; - } - if (E->isAssignmentOp()) { // For assignment operator (=) LHS expression is visited // before RHS expression. For destructors visit them in reverse order. @@ -3600,10 +3549,17 @@ Succ = B; Block = createNoReturnBlock(); } else { - autoCreateBlock(); + if (B) Succ = B; + Block = createBlock(); } appendTemporaryDtor(Block, E); + + CFGBlock *Decision = createBlock(false); + Decision->setTerminator(CFGTerminator(E, true)); + addSuccessor(Decision, Block); + addSuccessor(Decision, Succ); + Block = Decision; B = Block; } return B; @@ -3611,65 +3567,10 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( AbstractConditionalOperator *E, bool BindToTemporary) { - // First add destructors for condition expression. Even if this will - // unnecessarily create a block, this block will be used at least by the full - // expression. - autoCreateBlock(); - CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); - if (badCFG) - return nullptr; - if (BinaryConditionalOperator *BCO - = dyn_cast(E)) { - ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); - if (badCFG) - return nullptr; - } - - // Try to add block with destructors for LHS expression. - CFGBlock *LHSBlock = nullptr; - Succ = ConfluenceBlock; - Block = nullptr; - LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); - if (badCFG) - return nullptr; - - // Try to add block with destructors for RHS expression; - Succ = ConfluenceBlock; - Block = nullptr; - CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), - BindToTemporary); - if (badCFG) - return nullptr; - - if (!RHSBlock && !LHSBlock) { - // If neither LHS nor RHS expression had temporaries to destroy don't create - // more blocks. - Block = ConfluenceBlock; - return Block; - } - - Block = createBlock(false); - Block->setTerminator(CFGTerminator(E, true)); - assert(Block->getTerminator().isTemporaryDtorsBranch()); - - // See if this is a known constant. - const TryResult &KnownVal = tryEvaluateBool(E->getCond()); - - if (LHSBlock) { - addSuccessor(Block, LHSBlock, !KnownVal.isFalse()); - } else if (KnownVal.isFalse()) { - addSuccessor(Block, nullptr); - } else { - addSuccessor(Block, ConfluenceBlock); - std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); - } - - if (!RHSBlock) - RHSBlock = ConfluenceBlock; - - addSuccessor(Block, RHSBlock, !KnownVal.isTrue()); - - return Block; + CFGBlock *CondBlock = VisitForTemporaryDtors(E->getCond()); + CFGBlock *TrueBlock = VisitForTemporaryDtors(E->getTrueExpr()); + CFGBlock *FalseBlock = VisitForTemporaryDtors(E->getFalseExpr()); + return FalseBlock ? FalseBlock : (TrueBlock ? TrueBlock : CondBlock); } } // end anonymous namespace Index: lib/StaticAnalyzer/Core/CoreEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/CoreEngine.cpp +++ lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -14,6 +14,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" @@ -346,6 +347,11 @@ default: llvm_unreachable("Analysis for this terminator not implemented."); + case Stmt::CXXBindTemporaryExprClass: + HandleBindTemporary( + cast(B->getTerminator().getStmt()), B, Pred); + return; + // Model static initializers. case Stmt::DeclStmtClass: HandleStaticInit(cast(Term), B, Pred); @@ -461,6 +467,16 @@ enqueue(Dst); } +void CoreEngine::HandleBindTemporary(const CXXBindTemporaryExpr *BTE, + const CFGBlock *B, ExplodedNode *Pred) { + assert(B->succ_size() == 2); + NodeBuilderContext Ctx(*this, B, Pred); + ExplodedNodeSet Dst; + SubEng.processBindTemporary(BTE, Ctx, Pred, Dst, *(B->succ_begin()), + *(B->succ_begin() + 1)); + // Enqueue the new frontier onto the worklist. + enqueue(Dst); +} void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, ExplodedNode *Pred) { Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -757,6 +757,22 @@ // Handled due to fully linearised CFG. break; + case Stmt::CXXBindTemporaryExprClass: { + Bldr.takeNodes(Pred); + ExplodedNodeSet PreVisit; + getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this); + ExplodedNodeSet Next; + if (getAnalysisManager().options.includeTemporaryDtorsInCFG()) { + VisitCXXBindTemporaryExpr(cast(S), Pred, PreVisit, + Next); + } else { + Next = PreVisit; + } + getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this); + Bldr.addNodes(Dst); + break; + } + // Cases not handled yet; but will handle some day. case Stmt::DesignatedInitExprClass: case Stmt::ExtVectorElementExprClass: @@ -794,7 +810,6 @@ case Stmt::SizeOfPackExprClass: case Stmt::StringLiteralClass: case Stmt::ObjCStringLiteralClass: - case Stmt::CXXBindTemporaryExprClass: case Stmt::CXXPseudoDestructorExprClass: case Stmt::SubstNonTypeTemplateParmExprClass: case Stmt::CXXNullPtrLiteralExprClass: { @@ -1388,11 +1403,7 @@ if (!BO || !BO->isLogicalOp()) return Condition; - // FIXME: This is a workaround until we handle temporary destructor branches - // correctly; currently, temporary destructor branches lead to blocks that - // only have a terminator (and no statements). These blocks violate the - // invariant this function assumes. - if (B->getTerminator().isTemporaryDtorsBranch()) return Condition; + assert(!B->getTerminator().isTemporaryDtorsBranch()); // For logical operations, we still have the case where some branches // use the traditional "merge" approach and others sink the branch @@ -1421,6 +1432,7 @@ ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) { + assert(!Condition || !llvm::isa(Condition)); const LocationContext *LCtx = Pred->getLocationContext(); PrettyStackTraceLocationContext StackCrashInfo(LCtx); currBldrCtx = &BldCtx; Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -22,6 +22,12 @@ using namespace clang; using namespace ento; +typedef std::pair + CXXBindTemporaryContext; + +REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedTemporariesSet, + llvm::ImmutableSet); + void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst) { @@ -174,6 +180,25 @@ return MRMgr.getCXXTempObjectRegion(CE, LCtx); } +void ExprEngine::processBindTemporary(const CXXBindTemporaryExpr *BTE, + NodeBuilderContext &BldCtx, + ExplodedNode *Pred, ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) { + BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF); + if (Pred->getState()->contains( + std::make_pair(BTE, Pred->getStackFrame()))) { + TempDtorBuilder.markInfeasible(false); + ProgramStateRef State = Pred->getState(); + State = State->remove( + std::make_pair(BTE, Pred->getStackFrame())); + TempDtorBuilder.generateNode(State, true, Pred); + } else { + TempDtorBuilder.markInfeasible(true); + TempDtorBuilder.generateNode(Pred->getState(), false, Pred); + } +} + void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &destNodes) { @@ -478,6 +503,19 @@ Bldr.generateNode(CDE, Pred, state); } +void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, + ExplodedNode *Pred, + ExplodedNodeSet &PreVisit, + ExplodedNodeSet &Dst) { + StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx); + ProgramStateRef State = Pred->getState(); + assert(!State->contains( + std::make_pair(BTE, Pred->getStackFrame()))); + State = State->add( + std::make_pair(BTE, Pred->getStackFrame())); + StmtBldr.generateNode(BTE, Pred, State); +} + void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst) { Index: test/Analysis/temp-obj-dtors-cfg-output.cpp =================================================================== --- test/Analysis/temp-obj-dtors-cfg-output.cpp +++ test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -196,18 +196,25 @@ // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B1.3] -// CHECK: 5: [B1.4] (CXXConstructExpr, class A) -// CHECK: 6: ~A() (Temporary object destructor) -// CHECK: 7: return [B1.5]; -// CHECK: Preds (1): B2 +// CHECK: 1: return [B3.5]; +// CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] +// CHECK: 1: A() (CXXConstructExpr, class A) +// CHECK: 2: [B3.1] (BindTemporary) +// CHECK: 3: [B3.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B3.3] +// CHECK: 5: [B3.4] (CXXConstructExpr, class A) +// CHECK: T: (Temp Dtor) [B3.2] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 // CHECK: [B2 (ENTRY)] @@ -254,199 +261,262 @@ // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B1.3] -// CHECK: 5: [B1.4] (CXXConstructExpr, class A) -// CHECK: 6: ~A() (Temporary object destructor) -// CHECK: 7: return [B1.5]; -// CHECK: Preds (1): B2 +// CHECK: 1: return [B3.5]; +// CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 -// CHECK: [B0 (EXIT)] -// CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 // CHECK: Succs (1): B1 -// CHECK: [B1] +// CHECK: [B3] // CHECK: 1: A() (CXXConstructExpr, 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) -// CHECK: 7: B() (CXXConstructExpr, 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)) -// CHECK: 19: A() (CXXConstructExpr, 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) -// CHECK: 25: B() (CXXConstructExpr, 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: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: 2: [B3.1] (BindTemporary) +// CHECK: 3: [B3.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B3.3] +// CHECK: 5: [B3.4] (CXXConstructExpr, class A) +// CHECK: T: (Temp Dtor) [B3.2] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 // CHECK: [B10 (ENTRY)] // CHECK: Succs (1): B9 // CHECK: [B1] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: int b; +// CHECK: 1: int b; // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] -// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.8] && [B4.5] -// CHECK: 2: [B5.3]([B3.1]) -// CHECK: T: (Temp Dtor) [B5.8] && ... +// CHECK: T: (Temp Dtor) [B5.4] // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] -// CHECK: 1: B() (CXXConstructExpr, 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: 1: ~B() (Temporary object destructor) // CHECK: Preds (1): B5 // CHECK: Succs (1): B3 // CHECK: [B5] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: foo -// CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) -// CHECK: 4: A() (CXXConstructExpr, 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: 1: foo +// CHECK: 2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) +// CHECK: 3: A() (CXXConstructExpr, class A) +// CHECK: 4: [B5.3] (BindTemporary) +// CHECK: 5: [B5.4].operator int +// CHECK: 6: [B5.4] +// CHECK: 7: [B5.6] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 8: int([B5.7]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 9: B() (CXXConstructExpr, class B) +// CHECK: 10: [B5.9] (BindTemporary) +// CHECK: 11: [B5.10].operator int +// CHECK: 12: [B5.10] +// CHECK: 13: [B5.12] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 14: int([B5.13]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 15: [B5.8] + [B5.14] +// CHECK: 16: [B5.2]([B5.15]) +// CHECK: T: (Temp Dtor) [B5.10] // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B4 B3 // CHECK: [B6] -// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B7 // CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: [B9.5] && [B8.5] -// CHECK: 2: bool a = A() && B(); -// CHECK: T: (Temp Dtor) [B9.5] && ... +// CHECK: T: (Temp Dtor) [B9.2] // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B6 B5 // CHECK: [B8] -// CHECK: 1: B() (CXXConstructExpr, 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: 1: ~B() (Temporary object destructor) // CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] // CHECK: 1: A() (CXXConstructExpr, class A) // CHECK: 2: [B9.1] (BindTemporary) -// CHECK: 3: [B9.2].operator bool +// CHECK: 3: [B9.2].operator int // CHECK: 4: [B9.2] -// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B9.5] && ... +// CHECK: 5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 6: int([B9.5]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 7: B() (CXXConstructExpr, class B) +// CHECK: 8: [B9.7] (BindTemporary) +// CHECK: 9: [B9.8].operator int +// CHECK: 10: [B9.8] +// CHECK: 11: [B9.10] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 12: int([B9.11]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 13: [B9.6] + [B9.12] +// CHECK: 14: int a = int(A()) + int(B()); +// CHECK: T: (Temp Dtor) [B9.8] // CHECK: Preds (1): B10 // CHECK: Succs (2): B8 B7 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B10 (ENTRY)] -// CHECK: Succs (1): B9 +// CHECK: [B14 (ENTRY)] +// CHECK: Succs (1): B13 // CHECK: [B1] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: int b; +// CHECK: 1: int b; // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] -// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.8] || [B4.5] -// CHECK: 2: [B5.3]([B3.1]) -// CHECK: T: (Temp Dtor) [B5.8] || ... +// CHECK: T: (Temp Dtor) [B7.4] // CHECK: Preds (2): B4 B5 -// CHECK: Succs (2): B1 B2 +// CHECK: Succs (2): B2 B1 // CHECK: [B4] -// CHECK: 1: B() (CXXConstructExpr, 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: 1: ~B() (Temporary object destructor) // CHECK: Preds (1): B5 // CHECK: Succs (1): B3 // CHECK: [B5] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: foo -// CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) -// CHECK: 4: A() (CXXConstructExpr, 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: 1: [B7.7] && [B6.5] +// CHECK: 2: [B7.2]([B5.1]) +// CHECK: T: (Temp Dtor) [B6.2] // CHECK: Preds (2): B6 B7 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B6.1] (BindTemporary) +// CHECK: 3: [B6.2].operator bool +// CHECK: 4: [B6.2] +// CHECK: 5: [B6.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: Preds (1): B7 +// CHECK: Succs (1): B5 +// CHECK: [B7] +// CHECK: 1: foo +// CHECK: 2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) +// CHECK: 3: A() (CXXConstructExpr, class A) +// CHECK: 4: [B7.3] (BindTemporary) +// CHECK: 5: [B7.4].operator bool +// CHECK: 6: [B7.4] +// CHECK: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.7] && ... +// CHECK: Preds (2): B8 B9 +// CHECK: Succs (2): B6 B5 +// CHECK: [B8] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B9 +// CHECK: Succs (1): B7 +// CHECK: [B9] +// CHECK: T: (Temp Dtor) [B13.2] +// CHECK: Preds (2): B10 B11 +// CHECK: Succs (2): B8 B7 +// CHECK: [B10] +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B11 +// CHECK: Succs (1): B9 +// CHECK: [B11] +// CHECK: 1: [B13.5] && [B12.5] +// CHECK: 2: bool a = A() && B(); +// CHECK: T: (Temp Dtor) [B12.2] +// CHECK: Preds (2): B12 B13 +// CHECK: Succs (2): B10 B9 +// CHECK: [B12] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B12.1] (BindTemporary) +// CHECK: 3: [B12.2].operator bool +// CHECK: 4: [B12.2] +// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: Preds (1): B13 +// CHECK: Succs (1): B11 +// CHECK: [B13] +// CHECK: 1: A() (CXXConstructExpr, class A) +// 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: Preds (1): B14 +// CHECK: Succs (2): B12 B11 +// CHECK: [B0 (EXIT)] +// CHECK: Preds (1): B1 +// CHECK: [B14 (ENTRY)] +// CHECK: Succs (1): B13 +// CHECK: [B1] +// CHECK: 1: int b; +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] +// CHECK: T: (Temp Dtor) [B7.4] +// CHECK: Preds (2): B4 B5 +// CHECK: Succs (2): B2 B1 +// CHECK: [B4] // CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B5 +// CHECK: Succs (1): B3 +// CHECK: [B5] +// CHECK: 1: [B7.7] || [B6.5] +// CHECK: 2: [B7.2]([B5.1]) +// CHECK: T: (Temp Dtor) [B6.2] +// CHECK: Preds (2): B6 B7 +// CHECK: Succs (2): B4 B3 +// CHECK: [B6] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B6.1] (BindTemporary) +// CHECK: 3: [B6.2].operator bool +// CHECK: 4: [B6.2] +// CHECK: 5: [B6.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CHECK: Preds (1): B7 // CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: [B9.5] || [B8.5] -// CHECK: 2: bool a = A() || B(); -// CHECK: T: (Temp Dtor) [B9.5] || ... +// CHECK: 1: foo +// CHECK: 2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) +// CHECK: 3: A() (CXXConstructExpr, class A) +// CHECK: 4: [B7.3] (BindTemporary) +// CHECK: 5: [B7.4].operator bool +// CHECK: 6: [B7.4] +// CHECK: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.7] || ... // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] -// CHECK: 1: B() (CXXConstructExpr, 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: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] +// CHECK: T: (Temp Dtor) [B13.2] +// CHECK: Preds (2): B10 B11 +// CHECK: Succs (2): B8 B7 +// CHECK: [B10] +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B11 +// CHECK: Succs (1): B9 +// CHECK: [B11] +// CHECK: 1: [B13.5] || [B12.5] +// CHECK: 2: bool a = A() || B(); +// CHECK: T: (Temp Dtor) [B12.2] +// CHECK: Preds (2): B12 B13 +// CHECK: Succs (2): B10 B9 +// CHECK: [B12] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B12.1] (BindTemporary) +// CHECK: 3: [B12.2].operator bool +// CHECK: 4: [B12.2] +// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: Preds (1): B13 +// CHECK: Succs (1): B11 +// CHECK: [B13] // CHECK: 1: A() (CXXConstructExpr, 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: Preds (1): B10 -// CHECK: Succs (2): B7 B8 +// 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: Preds (1): B14 +// CHECK: Succs (2): B11 B12 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B11 (ENTRY)] -// CHECK: Succs (1): B10 +// CHECK: [B24 (ENTRY)] +// CHECK: Succs (1): B23 // CHECK: [B1] // CHECK: 1: int b; -// CHECK: 2: [B7.5].~A() (Implicit destructor) +// CHECK: 2: [B20.5].~A() (Implicit destructor) // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] @@ -464,76 +534,121 @@ // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] -// CHECK: 1: ~B() (Temporary object destructor) -// CHECK: 2: B() (CXXConstructExpr, 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: T: if [B6.5] // CHECK: Preds (2): B5 B6 // CHECK: Succs (2): B3 B2 // CHECK: [B5] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: Preds (1): B7 +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B6 // CHECK: Succs (1): B4 // CHECK: [B6] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: 3: ~A() (Temporary object destructor) -// CHECK: 4: ~B() (Temporary object destructor) -// CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B6.1] (BindTemporary) +// CHECK: 3: [B6.2].operator bool +// CHECK: 4: [B6.2] +// CHECK: 5: [B6.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: (Temp Dtor) [B6.2] +// CHECK: Preds (2): B7 B8 +// CHECK: Succs (2): B5 B4 // CHECK: [B7] -// CHECK: 1: [B10.5] ? [B8.6] : [B9.15] -// CHECK: 2: [B7.1] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 3: [B7.2] -// CHECK: 4: [B7.3] (CXXConstructExpr, class A) -// CHECK: 5: A a = B() ? A() : A(B()); -// CHECK: T: (Temp Dtor) [B10.5] ? ... : ... -// CHECK: Preds (2): B8 B9 -// CHECK: Succs (2): B5 B6 +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B8 +// CHECK: Succs (1): B6 // CHECK: [B8] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B8.1] (BindTemporary) -// CHECK: 3: [B8.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B8.3] -// CHECK: 5: [B8.4] (CXXConstructExpr, class A) -// CHECK: 6: [B8.5] (BindTemporary) -// CHECK: Preds (1): B10 -// CHECK: Succs (1): B7 +// CHECK: T: (Temp Dtor) [B23.2] +// CHECK: Preds (2): B9 B10 +// CHECK: Succs (2): B7 B6 // CHECK: [B9] -// CHECK: 1: B() (CXXConstructExpr, 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] -// CHECK: 9: [B9.8] (CXXConstructExpr, 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] -// CHECK: 14: [B9.13] (CXXConstructExpr, class A) -// CHECK: 15: [B9.14] (BindTemporary) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B10 -// CHECK: Succs (1): B7 +// CHECK: Succs (1): B8 // CHECK: [B10] +// CHECK: T: (Temp Dtor) [B21.2] +// CHECK: Preds (2): B11 B12 +// CHECK: Succs (2): B9 B8 +// CHECK: [B11] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B12 +// CHECK: Succs (1): B10 +// CHECK: [B12] +// CHECK: T: (Temp Dtor) [B21.6] +// CHECK: Preds (2): B13 B14 +// CHECK: Succs (2): B11 B10 +// CHECK: [B13] +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B14 +// CHECK: Succs (1): B12 +// CHECK: [B14] +// CHECK: T: (Temp Dtor) [B22.2] +// CHECK: Preds (2): B15 B16 +// CHECK: Succs (2): B13 B12 +// CHECK: [B15] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B16 +// CHECK: Succs (1): B14 +// CHECK: [B16] +// CHECK: T: (Temp Dtor) [B22.6] +// CHECK: Preds (2): B17 B18 +// CHECK: Succs (2): B15 B14 +// CHECK: [B17] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B18 +// CHECK: Succs (1): B16 +// CHECK: [B18] +// CHECK: T: (Temp Dtor) [B22.10] +// CHECK: Preds (2): B19 B20 +// CHECK: Succs (2): B17 B16 +// CHECK: [B19] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B20 +// CHECK: Succs (1): B18 +// CHECK: [B20] +// CHECK: 1: [B23.5] ? [B21.6] : [B22.15] +// CHECK: 2: [B20.1] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 3: [B20.2] +// CHECK: 4: [B20.3] (CXXConstructExpr, class A) +// CHECK: 5: A a = B() ? A() : A(B()); +// CHECK: T: (Temp Dtor) [B22.15] +// CHECK: Preds (2): B21 B22 +// CHECK: Succs (2): B19 B18 +// CHECK: [B21] +// CHECK: 1: A() (CXXConstructExpr, class A) +// CHECK: 2: [B21.1] (BindTemporary) +// CHECK: 3: [B21.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B21.3] +// CHECK: 5: [B21.4] (CXXConstructExpr, class A) +// CHECK: 6: [B21.5] (BindTemporary) +// CHECK: Preds (1): B23 +// CHECK: Succs (1): B20 +// CHECK: [B22] // CHECK: 1: B() (CXXConstructExpr, 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: Preds (1): B11 -// CHECK: Succs (2): B8 B9 +// CHECK: 2: [B22.1] (BindTemporary) +// CHECK: 3: [B22.2].operator A +// CHECK: 4: [B22.2] +// CHECK: 5: [B22.4] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 6: [B22.5] (BindTemporary) +// CHECK: 7: [B22.6] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 8: [B22.7] +// CHECK: 9: [B22.8] (CXXConstructExpr, class A) +// CHECK: 10: [B22.9] (BindTemporary) +// CHECK: 11: A([B22.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 12: [B22.11] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 13: [B22.12] +// CHECK: 14: [B22.13] (CXXConstructExpr, class A) +// CHECK: 15: [B22.14] (BindTemporary) +// CHECK: Preds (1): B23 +// CHECK: Succs (1): B20 +// CHECK: [B23] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B23.1] (BindTemporary) +// CHECK: 3: [B23.2].operator bool +// CHECK: 4: [B23.2] +// CHECK: 5: [B23.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B23.5] ? ... : ... +// CHECK: Preds (1): B24 +// CHECK: Succs (2): B21 B22 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: C() : b_(true) // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -543,12 +658,10 @@ // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: ~C() // CHECK: [B1 (ENTRY)] // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: operator bool() // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -560,7 +673,6 @@ // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: D() : b_(true) // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -570,7 +682,6 @@ // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: operator bool() // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] @@ -582,9 +693,8 @@ // CHECK: Succs (1): B0 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: int test_cond_unnamed_custom_destructor() -// CHECK: [B4 (ENTRY)] -// CHECK: Succs (1): B3 +// CHECK: [B6 (ENTRY)] +// CHECK: Succs (1): B5 // CHECK: [B1] // CHECK: 1: 0 // CHECK: 2: return [B1.1]; @@ -596,53 +706,65 @@ // CHECK: Preds (1): B3 // CHECK: Succs (1): B0 // CHECK: [B3] -// CHECK: 1: C() (CXXConstructExpr, 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: Preds (1): B4 +// CHECK: T: if [B5.5] +// CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 +// CHECK: [B4] +// CHECK: 1: ~C() (Temporary object destructor) +// CHECK: Preds (1): B5 +// CHECK: Succs (1): B3 +// CHECK: [B5] +// CHECK: 1: C() (CXXConstructExpr, struct C) +// CHECK: 2: [B5.1] (BindTemporary) +// CHECK: 3: [B5.2].operator bool +// CHECK: 4: [B5.2] +// CHECK: 5: [B5.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: (Temp Dtor) [B5.2] +// CHECK: Preds (1): B6 +// CHECK: Succs (2): B4 B3 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: int test_cond_named_custom_destructor() -// CHECK: [B5 (ENTRY)] -// CHECK: Succs (1): B4 +// CHECK: [B7 (ENTRY)] +// CHECK: Succs (1): B6 // CHECK: [B1] -// CHECK: 1: [B4.6].~C() (Implicit destructor) +// CHECK: 1: [B6.6].~C() (Implicit destructor) // CHECK: Succs (1): B0 // CHECK: [B2] // CHECK: 1: 0 // CHECK: 2: return [B2.1]; -// CHECK: 3: [B4.6].~C() (Implicit destructor) +// CHECK: 3: [B6.6].~C() (Implicit destructor) // CHECK: Preds (1): B4 // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: 1: 1 // CHECK: 2: return [B3.1]; -// CHECK: 3: [B4.6].~C() (Implicit destructor) +// CHECK: 3: [B6.6].~C() (Implicit destructor) // CHECK: Preds (1): B4 // CHECK: Succs (1): B0 // CHECK: [B4] +// CHECK: 1: c +// CHECK: 2: [B4.1].operator bool +// CHECK: 3: [B4.1] +// CHECK: 4: [B4.3] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: if [B4.4] +// CHECK: Preds (2): B5 B6 +// CHECK: Succs (2): B3 B2 +// CHECK: [B5] +// CHECK: 1: ~C() (Temporary object destructor) +// CHECK: Preds (1): B6 +// CHECK: Succs (1): B4 +// CHECK: [B6] // CHECK: 1: C() (CXXConstructExpr, struct C) -// CHECK: 2: [B4.1] (BindTemporary) -// CHECK: 3: [B4.2] (ImplicitCastExpr, NoOp, const struct C) -// CHECK: 4: [B4.3] -// CHECK: 5: [B4.4] (CXXConstructExpr, struct C) +// CHECK: 2: [B6.1] (BindTemporary) +// CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const struct C) +// CHECK: 4: [B6.3] +// CHECK: 5: [B6.4] (CXXConstructExpr, struct C) // CHECK: 6: C c = C(); -// CHECK: 7: ~C() (Temporary object destructor) -// CHECK: 8: c -// CHECK: 9: [B4.8].operator bool -// CHECK: 10: [B4.8] -// CHECK: 11: [B4.10] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: if [B4.11] -// CHECK: Preds (1): B5 -// CHECK: Succs (2): B3 B2 +// CHECK: T: (Temp Dtor) [B6.2] +// CHECK: Preds (1): B7 +// CHECK: Succs (2): B5 B4 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B3 -// CHECK: int test_cond_unnamed_auto_destructor() // CHECK: [B4 (ENTRY)] // CHECK: Succs (1): B3 // CHECK: [B1] @@ -665,7 +787,6 @@ // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: int test_cond_named_auto_destructor() // CHECK: [B4 (ENTRY)] // CHECK: Succs (1): B3 // CHECK: [B1] @@ -693,431 +814,604 @@ // CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: [B14 (ENTRY)] -// CHECK: Succs (1): B13 +// CHECK: [B36 (ENTRY)] +// CHECK: Succs (1): B35 // CHECK: [B1] -// CHECK: 1: ~B() (Temporary object destructor) -// CHECK: 2: int b; -// CHECK: 3: [B10.4].~A() (Implicit destructor) +// CHECK: 1: int b; +// CHECK: 2: [B32.4].~A() (Implicit destructor) // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: Preds (1): B4 +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: 3: ~A() (Temporary object destructor) -// CHECK: 4: ~B() (Temporary object destructor) -// CHECK: Preds (1): B4 -// CHECK: Succs (1): B1 +// CHECK: T: (Temp Dtor) [B18.4] +// CHECK: Preds (2): B4 B5 +// CHECK: Succs (2): B2 B1 // CHECK: [B4] -// CHECK: 1: [B7.8] ? [B5.6] : [B6.15] -// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 3: [B4.2] -// CHECK: 4: [B7.3]([B4.3]) -// CHECK: T: (Temp Dtor) [B7.8] ? ... : ... -// CHECK: Preds (2): B5 B6 -// CHECK: Succs (2): B2 B3 +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B5 +// CHECK: Succs (1): B3 // CHECK: [B5] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B5.1] (BindTemporary) -// CHECK: 3: [B5.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B5.3] -// CHECK: 5: [B5.4] (CXXConstructExpr, class A) -// CHECK: 6: [B5.5] (BindTemporary) -// CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: T: (Temp Dtor) [B16.2] +// CHECK: Preds (2): B6 B7 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] -// CHECK: 1: B() (CXXConstructExpr, 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] -// CHECK: 9: [B6.8] (CXXConstructExpr, 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] -// CHECK: 14: [B6.13] (CXXConstructExpr, class A) -// CHECK: 15: [B6.14] (BindTemporary) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: ~B() (Temporary object destructor) -// CHECK: 2: foo -// CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 4: B() (CXXConstructExpr, 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: T: (Temp Dtor) [B16.6] // CHECK: Preds (2): B8 B9 -// CHECK: Succs (2): B5 B6 +// CHECK: Succs (2): B6 B5 // CHECK: [B8] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: Preds (1): B10 +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B9 // CHECK: Succs (1): B7 // CHECK: [B9] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: 3: ~B() (Temporary object destructor) -// CHECK: Preds (1): B10 -// CHECK: Succs (1): B7 +// CHECK: T: (Temp Dtor) [B17.2] +// CHECK: Preds (2): B10 B11 +// CHECK: Succs (2): B8 B7 // CHECK: [B10] -// CHECK: 1: [B13.5] ? [B11.6] : [B12.15] -// CHECK: 2: [B10.1] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 3: [B10.2] -// CHECK: 4: const A &a = B() ? A() : A(B()); -// CHECK: T: (Temp Dtor) [B13.5] ? ... : ... -// CHECK: Preds (2): B11 B12 -// CHECK: Succs (2): B8 B9 +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B11 +// CHECK: Succs (1): B9 // CHECK: [B11] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B11.1] (BindTemporary) -// CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B11.3] -// CHECK: 5: [B11.4] (CXXConstructExpr, class A) -// CHECK: 6: [B11.5] (BindTemporary) -// CHECK: Preds (1): B13 -// CHECK: Succs (1): B10 +// CHECK: T: (Temp Dtor) [B17.6] +// CHECK: Preds (2): B12 B13 +// CHECK: Succs (2): B10 B9 // CHECK: [B12] -// CHECK: 1: B() (CXXConstructExpr, 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] -// CHECK: 9: [B12.8] (CXXConstructExpr, 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] -// CHECK: 14: [B12.13] (CXXConstructExpr, class A) -// CHECK: 15: [B12.14] (BindTemporary) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B13 -// CHECK: Succs (1): B10 +// CHECK: Succs (1): B11 // CHECK: [B13] +// CHECK: T: (Temp Dtor) [B17.10] +// CHECK: Preds (2): B14 B15 +// CHECK: Succs (2): B12 B11 +// CHECK: [B14] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B15 +// CHECK: Succs (1): B13 +// CHECK: [B15] +// CHECK: 1: [B18.7] ? [B16.6] : [B17.15] +// CHECK: 2: [B15.1] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 3: [B15.2] +// CHECK: 4: [B18.2]([B15.3]) +// CHECK: T: (Temp Dtor) [B17.15] +// CHECK: Preds (2): B16 B17 +// CHECK: Succs (2): B14 B13 +// CHECK: [B16] +// CHECK: 1: A() (CXXConstructExpr, class A) +// CHECK: 2: [B16.1] (BindTemporary) +// CHECK: 3: [B16.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B16.3] +// CHECK: 5: [B16.4] (CXXConstructExpr, class A) +// CHECK: 6: [B16.5] (BindTemporary) +// CHECK: Preds (1): B18 +// CHECK: Succs (1): B15 +// CHECK: [B17] // CHECK: 1: B() (CXXConstructExpr, 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: Preds (1): B14 -// CHECK: Succs (2): B11 B12 +// CHECK: 2: [B17.1] (BindTemporary) +// CHECK: 3: [B17.2].operator A +// CHECK: 4: [B17.2] +// CHECK: 5: [B17.4] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 6: [B17.5] (BindTemporary) +// CHECK: 7: [B17.6] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 8: [B17.7] +// CHECK: 9: [B17.8] (CXXConstructExpr, class A) +// CHECK: 10: [B17.9] (BindTemporary) +// CHECK: 11: A([B17.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 12: [B17.11] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 13: [B17.12] +// CHECK: 14: [B17.13] (CXXConstructExpr, class A) +// CHECK: 15: [B17.14] (BindTemporary) +// CHECK: Preds (1): B18 +// CHECK: Succs (1): B15 +// CHECK: [B18] +// CHECK: 1: foo +// CHECK: 2: [B18.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 3: B() (CXXConstructExpr, class B) +// CHECK: 4: [B18.3] (BindTemporary) +// CHECK: 5: [B18.4].operator bool +// CHECK: 6: [B18.4] +// CHECK: 7: [B18.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B18.7] ? ... : ... +// CHECK: Preds (2): B19 B20 +// CHECK: Succs (2): B16 B17 +// CHECK: [B19] +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B20 +// CHECK: Succs (1): B18 +// CHECK: [B20] +// CHECK: T: (Temp Dtor) [B35.2] +// CHECK: Preds (2): B21 B22 +// CHECK: Succs (2): B19 B18 +// CHECK: [B21] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B22 +// CHECK: Succs (1): B20 +// CHECK: [B22] +// CHECK: T: (Temp Dtor) [B33.2] +// CHECK: Preds (2): B23 B24 +// CHECK: Succs (2): B21 B20 +// CHECK: [B23] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B24 +// CHECK: Succs (1): B22 +// CHECK: [B24] +// CHECK: T: (Temp Dtor) [B33.6] +// CHECK: Preds (2): B25 B26 +// CHECK: Succs (2): B23 B22 +// CHECK: [B25] +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B26 +// CHECK: Succs (1): B24 +// CHECK: [B26] +// CHECK: T: (Temp Dtor) [B34.2] +// CHECK: Preds (2): B27 B28 +// CHECK: Succs (2): B25 B24 +// CHECK: [B27] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B28 +// CHECK: Succs (1): B26 +// CHECK: [B28] +// CHECK: T: (Temp Dtor) [B34.6] +// CHECK: Preds (2): B29 B30 +// CHECK: Succs (2): B27 B26 +// CHECK: [B29] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B30 +// CHECK: Succs (1): B28 +// CHECK: [B30] +// CHECK: T: (Temp Dtor) [B34.10] +// CHECK: Preds (2): B31 B32 +// CHECK: Succs (2): B29 B28 +// CHECK: [B31] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B32 +// CHECK: Succs (1): B30 +// CHECK: [B32] +// CHECK: 1: [B35.5] ? [B33.6] : [B34.15] +// CHECK: 2: [B32.1] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 3: [B32.2] +// CHECK: 4: const A &a = B() ? A() : A(B()); +// CHECK: T: (Temp Dtor) [B34.15] +// CHECK: Preds (2): B33 B34 +// CHECK: Succs (2): B31 B30 +// CHECK: [B33] +// CHECK: 1: A() (CXXConstructExpr, class A) +// CHECK: 2: [B33.1] (BindTemporary) +// CHECK: 3: [B33.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B33.3] +// CHECK: 5: [B33.4] (CXXConstructExpr, class A) +// CHECK: 6: [B33.5] (BindTemporary) +// CHECK: Preds (1): B35 +// CHECK: Succs (1): B32 +// CHECK: [B34] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B34.1] (BindTemporary) +// CHECK: 3: [B34.2].operator A +// CHECK: 4: [B34.2] +// CHECK: 5: [B34.4] (ImplicitCastExpr, UserDefinedConversion, class A) +// CHECK: 6: [B34.5] (BindTemporary) +// CHECK: 7: [B34.6] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 8: [B34.7] +// CHECK: 9: [B34.8] (CXXConstructExpr, class A) +// CHECK: 10: [B34.9] (BindTemporary) +// CHECK: 11: A([B34.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A) +// CHECK: 12: [B34.11] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 13: [B34.12] +// CHECK: 14: [B34.13] (CXXConstructExpr, class A) +// CHECK: 15: [B34.14] (BindTemporary) +// CHECK: Preds (1): B35 +// CHECK: Succs (1): B32 +// CHECK: [B35] +// CHECK: 1: B() (CXXConstructExpr, class B) +// CHECK: 2: [B35.1] (BindTemporary) +// CHECK: 3: [B35.2].operator bool +// CHECK: 4: [B35.2] +// CHECK: 5: [B35.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B35.5] ? ... : ... +// CHECK: Preds (1): B36 +// CHECK: Succs (2): B33 B34 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B8 (ENTRY)] -// CHECK: Succs (1): B7 +// CHECK: [B11 (ENTRY)] +// CHECK: Succs (1): B10 // CHECK: [B1] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: int b; -// CHECK: 3: [B4.5].~A() (Implicit destructor) +// CHECK: 1: int b; +// CHECK: 2: [B7.5].~A() (Implicit destructor) // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] // CHECK: 1: ~A() (Temporary object destructor) -// CHECK: Preds (1): B4 +// CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: Preds (1): B4 -// CHECK: Succs (1): B1 +// CHECK: T: (Temp Dtor) [B8.4] +// CHECK: Preds (2): B4 B5 +// CHECK: Succs (2): B2 B1 // CHECK: [B4] -// CHECK: 1: [B7.2] ?: [B6.6] -// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 3: [B4.2] -// CHECK: 4: [B4.3] (CXXConstructExpr, class A) -// CHECK: 5: A a = A() ?: A(); -// CHECK: T: (Temp Dtor) [B7.5] ? ... : ... -// CHECK: Preds (2): B5 B6 -// CHECK: Succs (2): B2 B3 +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B5 +// CHECK: Succs (1): B3 // CHECK: [B5] -// CHECK: 1: [B7.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 2: [B5.1] -// CHECK: 3: [B5.2] (CXXConstructExpr, class A) -// CHECK: 4: [B5.3] (BindTemporary) -// CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: T: (Temp Dtor) [B9.2] +// CHECK: Preds (2): B6 B7 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B6.1] (BindTemporary) -// CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B6.3] -// CHECK: 5: [B6.4] (CXXConstructExpr, class A) -// CHECK: 6: [B6.5] (BindTemporary) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: Succs (1): B5 // CHECK: [B7] +// CHECK: 1: [B10.2] ?: [B9.6] +// CHECK: 2: [B7.1] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 3: [B7.2] +// CHECK: 4: [B7.3] (CXXConstructExpr, class A) +// CHECK: 5: A a = A() ?: A(); +// CHECK: T: (Temp Dtor) [B9.6] +// CHECK: Preds (2): B8 B9 +// CHECK: Succs (2): B6 B5 +// CHECK: [B8] +// CHECK: 1: [B10.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 2: [B8.1] +// CHECK: 3: [B8.2] (CXXConstructExpr, class A) +// CHECK: 4: [B8.3] (BindTemporary) +// CHECK: Preds (1): B10 +// CHECK: Succs (1): B7 +// CHECK: [B9] // CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B7.1] (BindTemporary) -// CHECK: 3: [B7.2].operator bool -// CHECK: 4: [B7.2] -// CHECK: 5: [B7.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B7.5] ? ... : ... -// CHECK: Preds (1): B8 -// CHECK: Succs (2): B5 B6 +// CHECK: 2: [B9.1] (BindTemporary) +// CHECK: 3: [B9.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B9.3] +// CHECK: 5: [B9.4] (CXXConstructExpr, class A) +// CHECK: 6: [B9.5] (BindTemporary) +// CHECK: Preds (1): B10 +// CHECK: Succs (1): B7 +// CHECK: [B10] +// CHECK: 1: A() (CXXConstructExpr, class A) +// 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: Preds (1): B11 +// CHECK: Succs (2): B8 B9 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B13 (ENTRY)] -// CHECK: Succs (1): B12 +// CHECK: [B20 (ENTRY)] +// CHECK: Succs (1): B19 // CHECK: [B1] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: int b; -// CHECK: 3: [B9.4].~A() (Implicit destructor) +// CHECK: 1: int b; +// CHECK: 2: [B16.4].~A() (Implicit destructor) // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] // CHECK: 1: ~A() (Temporary object destructor) -// CHECK: Preds (1): B4 +// CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: ~A() (Temporary object destructor) -// CHECK: Preds (1): B4 -// CHECK: Succs (1): B1 +// CHECK: T: (Temp Dtor) [B8.4] +// CHECK: Preds (2): B4 B5 +// CHECK: Succs (2): B2 B1 // CHECK: [B4] -// CHECK: 1: [B7.5] ?: [B6.6] -// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 3: [B4.2] -// CHECK: 4: [B7.3]([B4.3]) -// CHECK: T: (Temp Dtor) [B7.8] ? ... : ... -// CHECK: Preds (2): B5 B6 -// CHECK: Succs (2): B2 B3 +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B5 +// CHECK: Succs (1): B3 // CHECK: [B5] -// CHECK: 1: [B7.5] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 2: [B5.1] -// CHECK: 3: [B5.2] (CXXConstructExpr, class A) -// CHECK: 4: [B5.3] (BindTemporary) -// CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: T: (Temp Dtor) [B9.2] +// CHECK: Preds (2): B6 B7 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B6.1] (BindTemporary) -// CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B6.3] -// CHECK: 5: [B6.4] (CXXConstructExpr, class A) -// CHECK: 6: [B6.5] (BindTemporary) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B7 -// CHECK: Succs (1): B4 +// CHECK: Succs (1): B5 // CHECK: [B7] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: foo -// CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 4: A() (CXXConstructExpr, class A) -// 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: Preds (2): B9 B8 -// CHECK: Succs (2): B5 B6 +// CHECK: 1: [B10.4] ?: [B9.6] +// CHECK: 2: [B7.1] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 3: [B7.2] +// CHECK: 4: [B10.2]([B7.3]) +// CHECK: T: (Temp Dtor) [B9.6] +// CHECK: Preds (2): B8 B9 +// CHECK: Succs (2): B6 B5 // CHECK: [B8] -// CHECK: 1: ~A() (Temporary object destructor) -// CHECK: Preds (1): B9 +// CHECK: 1: [B10.4] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 2: [B8.1] +// CHECK: 3: [B8.2] (CXXConstructExpr, class A) +// CHECK: 4: [B8.3] (BindTemporary) +// CHECK: Preds (1): B10 // CHECK: Succs (1): B7 // CHECK: [B9] -// CHECK: 1: [B12.2] ?: [B11.6] -// CHECK: 2: [B9.1] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 3: [B9.2] -// CHECK: 4: const A &a = A() ?: A(); -// CHECK: T: (Temp Dtor) [B12.5] ? ... : ... -// CHECK: Preds (2): B10 B11 -// CHECK: Succs (2): B7 B8 +// CHECK: 1: A() (CXXConstructExpr, class A) +// CHECK: 2: [B9.1] (BindTemporary) +// CHECK: 3: [B9.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B9.3] +// CHECK: 5: [B9.4] (CXXConstructExpr, class A) +// CHECK: 6: [B9.5] (BindTemporary) +// CHECK: Preds (1): B10 +// CHECK: Succs (1): B7 // CHECK: [B10] -// CHECK: 1: [B12.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 2: [B10.1] -// CHECK: 3: [B10.2] (CXXConstructExpr, class A) +// CHECK: 1: foo +// CHECK: 2: [B10.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 3: A() (CXXConstructExpr, class A) // CHECK: 4: [B10.3] (BindTemporary) -// CHECK: Preds (1): B12 -// CHECK: Succs (1): B9 +// CHECK: 5: [B10.4].operator bool +// CHECK: 6: [B10.4] +// CHECK: 7: [B10.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B10.7] ? ... : ... +// CHECK: Preds (2): B11 B12 +// CHECK: Succs (2): B8 B9 // CHECK: [B11] -// CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B11.1] (BindTemporary) -// CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B11.3] -// CHECK: 5: [B11.4] (CXXConstructExpr, class A) -// CHECK: 6: [B11.5] (BindTemporary) +// CHECK: 1: ~A() (Temporary object destructor) // CHECK: Preds (1): B12 -// CHECK: Succs (1): B9 +// CHECK: Succs (1): B10 // CHECK: [B12] +// CHECK: T: (Temp Dtor) [B17.4] +// CHECK: Preds (2): B13 B14 +// CHECK: Succs (2): B11 B10 +// CHECK: [B13] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B14 +// CHECK: Succs (1): B12 +// CHECK: [B14] +// CHECK: T: (Temp Dtor) [B18.2] +// CHECK: Preds (2): B15 B16 +// CHECK: Succs (2): B13 B12 +// CHECK: [B15] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B16 +// CHECK: Succs (1): B14 +// CHECK: [B16] +// CHECK: 1: [B19.2] ?: [B18.6] +// CHECK: 2: [B16.1] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 3: [B16.2] +// CHECK: 4: const A &a = A() ?: A(); +// CHECK: T: (Temp Dtor) [B18.6] +// CHECK: Preds (2): B17 B18 +// CHECK: Succs (2): B15 B14 +// CHECK: [B17] +// CHECK: 1: [B19.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 2: [B17.1] +// CHECK: 3: [B17.2] (CXXConstructExpr, class A) +// CHECK: 4: [B17.3] (BindTemporary) +// CHECK: Preds (1): B19 +// CHECK: Succs (1): B16 +// CHECK: [B18] // CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B12.1] (BindTemporary) -// CHECK: 3: [B12.2].operator bool -// CHECK: 4: [B12.2] -// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B12.5] ? ... : ... -// CHECK: Preds (1): B13 -// CHECK: Succs (2): B10 B11 +// CHECK: 2: [B18.1] (BindTemporary) +// CHECK: 3: [B18.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B18.3] +// CHECK: 5: [B18.4] (CXXConstructExpr, class A) +// CHECK: 6: [B18.5] (BindTemporary) +// CHECK: Preds (1): B19 +// CHECK: Succs (1): B16 +// CHECK: [B19] +// CHECK: 1: A() (CXXConstructExpr, class A) +// CHECK: 2: [B19.1] (BindTemporary) +// CHECK: 3: [B19.2].operator bool +// CHECK: 4: [B19.2] +// CHECK: 5: [B19.4] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B19.5] ? ... : ... +// CHECK: Preds (1): B20 +// CHECK: Succs (2): B17 B18 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] +// CHECK: 1: int b; +// CHECK: 2: [B3.6].~A() (Implicit destructor) +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] // CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B1.3] -// CHECK: 5: [B1.4] (CXXConstructExpr, class A) +// CHECK: 2: [B3.1] (BindTemporary) +// CHECK: 3: [B3.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B3.3] +// CHECK: 5: [B3.4] (CXXConstructExpr, class A) // CHECK: 6: A a = A(); -// CHECK: 7: ~A() (Temporary object destructor) -// CHECK: 8: int b; -// CHECK: 9: [B1.6].~A() (Implicit destructor) -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: T: (Temp Dtor) [B3.2] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] +// CHECK: 1: int b; +// CHECK: 2: [B3.5].~A() (Implicit destructor) +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] // CHECK: 1: A() (CXXConstructExpr, class A) -// CHECK: 2: [B1.1] (BindTemporary) -// CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 4: [B1.3] +// CHECK: 2: [B3.1] (BindTemporary) +// CHECK: 3: [B3.2] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 4: [B3.3] // CHECK: 5: const A &a = A(); // CHECK: 6: foo -// CHECK: 7: [B1.6] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 7: [B3.6] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) // CHECK: 8: A() (CXXConstructExpr, class A) -// CHECK: 9: [B1.8] (BindTemporary) -// CHECK: 10: [B1.9] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 11: [B1.10] -// CHECK: 12: [B1.7]([B1.11]) -// CHECK: 13: ~A() (Temporary object destructor) -// CHECK: 14: int b; -// CHECK: 15: [B1.5].~A() (Implicit destructor) -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: 9: [B3.8] (BindTemporary) +// CHECK: 10: [B3.9] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 11: [B3.10] +// CHECK: 12: [B3.7]([B3.11]) +// CHECK: T: (Temp Dtor) [B3.9] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] +// CHECK: 1: int b; +// CHECK: 2: [B3.8].~A() (Implicit destructor) +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] // CHECK: 1: A::make -// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) -// CHECK: 3: [B1.2]() -// CHECK: 4: [B1.3] (BindTemporary) -// CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 6: [B1.5] -// CHECK: 7: [B1.6] (CXXConstructExpr, class A) +// CHECK: 2: [B3.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) +// CHECK: 3: [B3.2]() +// CHECK: 4: [B3.3] (BindTemporary) +// CHECK: 5: [B3.4] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 6: [B3.5] +// CHECK: 7: [B3.6] (CXXConstructExpr, class A) // CHECK: 8: A a = A::make(); -// CHECK: 9: ~A() (Temporary object destructor) -// CHECK: 10: int b; -// CHECK: 11: [B1.8].~A() (Implicit destructor) -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: T: (Temp Dtor) [B3.4] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] +// CHECK: 1: int b; +// CHECK: 2: [B3.7].~A() (Implicit destructor) +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] // CHECK: 1: A::make -// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) -// CHECK: 3: [B1.2]() -// CHECK: 4: [B1.3] (BindTemporary) -// CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 6: [B1.5] +// CHECK: 2: [B3.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) +// CHECK: 3: [B3.2]() +// CHECK: 4: [B3.3] (BindTemporary) +// CHECK: 5: [B3.4] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 6: [B3.5] // CHECK: 7: const A &a = A::make(); // CHECK: 8: foo -// CHECK: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 9: [B3.8] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) // CHECK: 10: A::make -// CHECK: 11: [B1.10] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) -// CHECK: 12: [B1.11]() -// CHECK: 13: [B1.12] (BindTemporary) -// CHECK: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 15: [B1.14] -// CHECK: 16: [B1.9]([B1.15]) -// CHECK: 17: ~A() (Temporary object destructor) -// CHECK: 18: int b; -// CHECK: 19: [B1.7].~A() (Implicit destructor) -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: 11: [B3.10] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) +// CHECK: 12: [B3.11]() +// CHECK: 13: [B3.12] (BindTemporary) +// CHECK: 14: [B3.13] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 15: [B3.14] +// CHECK: 16: [B3.9]([B3.15]) +// CHECK: T: (Temp Dtor) [B3.13] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] +// CHECK: 1: int b; +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] // CHECK: 1: int a; // CHECK: 2: A() (CXXConstructExpr, 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: 3: [B3.2] (BindTemporary) +// CHECK: 4: [B3.3].operator int +// CHECK: 5: [B3.3] +// CHECK: 6: [B3.5] (ImplicitCastExpr, UserDefinedConversion, int) // CHECK: 7: a -// CHECK: 8: [B1.7] = [B1.6] -// CHECK: 9: ~A() (Temporary object destructor) -// CHECK: 10: int b; -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: 8: [B3.7] = [B3.6] +// CHECK: T: (Temp Dtor) [B3.3] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 +// CHECK: [B6 (ENTRY)] +// CHECK: Succs (1): B5 // CHECK: [B1] +// CHECK: 1: /*implicit*/int() +// CHECK: 2: b([B1.1]) (Member initializer) +// CHECK: Preds (2): B2 B3 +// CHECK: Succs (1): B0 +// CHECK: [B2] +// CHECK: 1: ~A() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B1 +// CHECK: [B3] +// CHECK: T: (Temp Dtor) [B5.2] +// CHECK: Preds (2): B4 B5 +// CHECK: Succs (2): B2 B1 +// CHECK: [B4] +// CHECK: 1: ~B() (Temporary object destructor) +// CHECK: Preds (1): B5 +// CHECK: Succs (1): B3 +// CHECK: [B5] // CHECK: 1: A() (CXXConstructExpr, 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) +// CHECK: 2: [B5.1] (BindTemporary) +// CHECK: 3: [B5.2].operator int +// CHECK: 4: [B5.2] +// CHECK: 5: [B5.4] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 6: int([B5.5]) (CXXFunctionalCastExpr, NoOp, int) // CHECK: 7: B() (CXXConstructExpr, 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() -// CHECK: 18: b([B1.17]) (Member initializer) -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 +// CHECK: 8: [B5.7] (BindTemporary) +// CHECK: 9: [B5.8].operator int +// CHECK: 10: [B5.8] +// CHECK: 11: [B5.10] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 12: int([B5.11]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 13: [B5.6] + [B5.12] +// CHECK: 14: a([B5.13]) (Member initializer) +// CHECK: T: (Temp Dtor) [B5.8] +// CHECK: Preds (1): B6 +// CHECK: Succs (2): B4 B3 // CHECK: [B0 (EXIT)] // CHECK: Preds (1): B1 -// CHECK: [B3 (ENTRY)] -// CHECK: Succs (1): B2 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] // CHECK: 1: int b; +// CHECK: Preds (2): B2(Unreachable) B3 // CHECK: Succs (1): B0 // CHECK: [B2 (NORETURN)] -// CHECK: 1: int a; -// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn) -// CHECK: 3: [B2.2] (BindTemporary) -// CHECK: 4: [B2.3].f -// CHECK: 5: [B2.4]() -// CHECK: 6: ~NoReturn() (Temporary object destructor) +// CHECK: 1: ~NoReturn() (Temporary object destructor) // CHECK: Preds (1): B3 // CHECK: Succs (1): B0 +// CHECK: [B3] +// CHECK: 1: int a; +// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn) +// CHECK: 3: [B3.2] (BindTemporary) +// CHECK: 4: [B3.3].f +// CHECK: 5: [B3.4]() +// CHECK: T: (Temp Dtor) [B3.3] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: [B3 (ENTRY)] -// CHECK: Succs (1): B2 +// CHECK: [B4 (ENTRY)] +// CHECK: Succs (1): B3 // CHECK: [B1] // CHECK: 1: int b; +// CHECK: Preds (2): B2(Unreachable) B3 // CHECK: Succs (1): B0 // CHECK: [B2 (NORETURN)] +// CHECK: 1: ~NoReturn() (Temporary object destructor) +// CHECK: Preds (1): B3 +// CHECK: Succs (1): B0 +// CHECK: [B3] // CHECK: 1: int a; // CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn) -// CHECK: 3: [B2.2] (BindTemporary) +// CHECK: 3: [B3.2] (BindTemporary) // CHECK: 4: 47 -// CHECK: 5: ... , [B2.4] -// CHECK: 6: ~NoReturn() (Temporary object destructor) -// CHECK: Preds (1): B3 -// CHECK: Succs (1): B0 +// CHECK: 5: ... , [B3.4] +// CHECK: T: (Temp Dtor) [B3.3] +// CHECK: Preds (1): B4 +// CHECK: Succs (2): B2 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (2): B1 B2 -// CHECK: int testConsistencyNestedSimple(bool value) // CHECK: [B9 (ENTRY)] // CHECK: Succs (1): B8 // CHECK: [B1] @@ -1132,7 +1426,7 @@ // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: T: if [B5.1] -// CHECK: Preds (1): B5 +// CHECK: Preds (2): B4(Unreachable) B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4 (NORETURN)] // CHECK: 1: ~NoReturn() (Temporary object destructor) @@ -1140,9 +1434,9 @@ // CHECK: Succs (1): B0 // CHECK: [B5] // CHECK: 1: [B7.3] || [B6.7] -// CHECK: T: (Temp Dtor) [B7.3] || ... +// CHECK: T: (Temp Dtor) [B6.4] // CHECK: Preds (2): B6 B7 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] // CHECK: 1: check // CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &)) @@ -1168,7 +1462,6 @@ // CHECK: Succs (2): B7 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B4 -// CHECK: int testConsistencyNestedComplex(bool value) // CHECK: [B10 (ENTRY)] // CHECK: Succs (1): B9 // CHECK: [B1] @@ -1183,7 +1476,7 @@ // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: T: if [B5.1] -// CHECK: Preds (1): B5 +// CHECK: Preds (2): B4(Unreachable) B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4 (NORETURN)] // CHECK: 1: ~NoReturn() (Temporary object destructor) @@ -1191,9 +1484,9 @@ // CHECK: Succs (1): B0 // CHECK: [B5] // CHECK: 1: [B8.3] || [B7.3] || [B6.7] -// CHECK: T: (Temp Dtor) [B8.3] || [B7.3] || ... +// CHECK: T: (Temp Dtor) [B6.4] // CHECK: Preds (3): B6 B7 B8 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] // CHECK: 1: check // CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &)) @@ -1226,7 +1519,6 @@ // CHECK: Succs (2): B8 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B4 -// CHECK: int testConsistencyNestedNormalReturn(bool value) // CHECK: [B10 (ENTRY)] // CHECK: Succs (1): B9 // CHECK: [B1] @@ -1241,7 +1533,7 @@ // CHECK: Succs (1): B0 // CHECK: [B3] // CHECK: T: if [B5.1] -// CHECK: Preds (1): B5 +// CHECK: Preds (2): B4(Unreachable) B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4 (NORETURN)] // CHECK: 1: ~NoReturn() (Temporary object destructor) @@ -1249,9 +1541,9 @@ // CHECK: Succs (1): B0 // CHECK: [B5] // CHECK: 1: [B8.3] || [B7.2] || [B6.7] -// CHECK: T: (Temp Dtor) [B8.3] || [B7.2] || ... +// CHECK: T: (Temp Dtor) [B6.4] // CHECK: Preds (3): B6 B7 B8 -// CHECK: Succs (2): B3 B4 +// CHECK: Succs (2): B4 B3 // CHECK: [B6] // CHECK: 1: check // CHECK: 2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &)) @@ -1283,3 +1575,4 @@ // CHECK: Succs (2): B8 B1 // CHECK: [B0 (EXIT)] // CHECK: Preds (3): B1 B2 B4 + Index: test/Analysis/temporaries.cpp =================================================================== --- test/Analysis/temporaries.cpp +++ test/Analysis/temporaries.cpp @@ -193,8 +193,7 @@ (i == 4 || i == 4 || compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) || i != 4) { - // FIXME: This shouldn't cause a warning. - clang_analyzer_eval(true); // expected-warning{{TRUE}} + clang_analyzer_eval(true); // no warning, unreachable code } } @@ -211,8 +210,7 @@ void testConsistencyNestedComplex(bool value) { if (value) { if (!value || !value || check(NoReturnDtor())) { - // FIXME: This shouldn't cause a warning. - clang_analyzer_eval(true); // expected-warning{{TRUE}} + clang_analyzer_eval(true); // no warning, unreachable code } } } @@ -225,6 +223,76 @@ } } } + // PR16664 and PR18159 + void testConsistencyNestedComplexMidBranch(bool value) { + if (value) { + if (!value || !value || check(NoReturnDtor()) || value) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + // PR16664 and PR18159 + void testConsistencyNestedComplexNestedBranch(bool value) { + if (value) { + if (!value || (!value || check(NoReturnDtor()) || value)) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + // PR16664 and PR18159 + void testConsistencyNestedVariableModification(bool value) { + bool other = true; + if (value) { + if (!other || !value || (other = false) || check(NoReturnDtor()) || + !other) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + void testTernary(bool value) { + if (value) { + bool b = value && value ? check(NoReturnDtor()) : true; + clang_analyzer_eval(true); // no warning, unreachable code + } + if (value) { + bool b = !value && !value ? true : check(NoReturnDtor()); + clang_analyzer_eval(true); // no warning, unreachable code + } + } + + void testLoop() { + for (int i = 0; i < 10; ++i) { + if (i < 3 && (i >= 2 || check(NoReturnDtor()))) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } + + bool testRecursiveFrames(bool isInner) { + if (isInner || check(NoReturnDtor()) || testRecursiveFrames(true)) { + *(volatile int *)0 = 1; // expected-warning{{null pointer}} + } + } + void testRecursiveFramesStart() { testRecursiveFrames(false); } + + struct Dtor { + ~Dtor(); + }; + extern bool check(const Dtor &); + + void testMultipleTemporaries(bool value) { + if (value) { + // FIXME: Find a way to verify construction order. + // ~Dtor should run before ~NoReturnDtor() because construction order is + // guaranteed by comma operator. + if (!value || check((NoReturnDtor(), Dtor())) || value) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + } void testBinaryOperatorShortcut(bool value) { if (value) {