Index: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h =================================================================== --- cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h +++ cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h @@ -451,6 +451,7 @@ bool addStaticInitBranches = false, bool addCXXNewAllocator = true, bool addRichCXXConstructors = true, + bool markElidedCXXConstructors = true, CodeInjector *injector = nullptr); AnalysisDeclContext *getContext(const Decl *D); Index: cfe/trunk/include/clang/Analysis/CFG.h =================================================================== --- cfe/trunk/include/clang/Analysis/CFG.h +++ cfe/trunk/include/clang/Analysis/CFG.h @@ -1025,6 +1025,7 @@ bool AddCXXNewAllocator = false; bool AddCXXDefaultInitExprInCtors = false; bool AddRichCXXConstructors = false; + bool MarkElidedCXXConstructors = false; BuildOptions() = default; Index: cfe/trunk/include/clang/Analysis/ConstructionContext.h =================================================================== --- cfe/trunk/include/clang/Analysis/ConstructionContext.h +++ cfe/trunk/include/clang/Analysis/ConstructionContext.h @@ -107,7 +107,10 @@ INITIALIZER_BEGIN = SimpleConstructorInitializerKind, INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind, NewAllocatedObjectKind, - TemporaryObjectKind, + SimpleTemporaryObjectKind, + ElidedTemporaryObjectKind, + TEMPORARY_BEGIN = SimpleTemporaryObjectKind, + TEMPORARY_END = ElidedTemporaryObjectKind, SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind, RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, @@ -305,16 +308,15 @@ const CXXBindTemporaryExpr *BTE; const MaterializeTemporaryExpr *MTE; - friend class ConstructionContext; // Allows to create<>() itself. - +protected: explicit TemporaryObjectConstructionContext( - const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) - : ConstructionContext(ConstructionContext::TemporaryObjectKind), - BTE(BTE), MTE(MTE) { + ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE, + const MaterializeTemporaryExpr *MTE) + : ConstructionContext(K), BTE(BTE), MTE(MTE) { // Both BTE and MTE can be null here, all combinations possible. // Even though for now at least one should be non-null, we simply haven't - // implemented this case yet (this would be a temporary in the middle of - // nowhere that doesn't have a non-trivial destructor). + // implemented the other case yet (this would be a temporary in the middle + // of nowhere that doesn't have a non-trivial destructor). } public: @@ -334,7 +336,67 @@ } static bool classof(const ConstructionContext *CC) { - return CC->getKind() == TemporaryObjectKind; + return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END; + } +}; + +/// Represents a temporary object that is not constructed for the purpose of +/// being immediately copied/moved by an elidable copy/move-constructor. +/// This includes temporary objects "in the middle of nowhere" like T(123) and +/// lifetime-extended temporaries. +class SimpleTemporaryObjectConstructionContext + : public TemporaryObjectConstructionContext { + friend class ConstructionContext; // Allows to create<>() itself. + + explicit SimpleTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) + : TemporaryObjectConstructionContext( + ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {} + +public: + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == SimpleTemporaryObjectKind; + } +}; + +/// Represents a temporary object that is constructed for the sole purpose +/// of being immediately copied by an elidable copy/move constructor. +/// For example, T t = T(123); includes a temporary T(123) that is immediately +/// copied to variable t. In such cases the elidable copy can (but not +/// necessarily should) be omitted ("elided") accodring to the rules of the +/// language; the constructor would then construct variable t directly. +/// This construction context contains information of the elidable constructor +/// and its respective construction context. +class ElidedTemporaryObjectConstructionContext + : public TemporaryObjectConstructionContext { + const CXXConstructExpr *ElidedCE; + const ConstructionContext *ElidedCC; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit ElidedTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE, + const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC) + : TemporaryObjectConstructionContext( + ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE), + ElidedCE(ElidedCE), ElidedCC(ElidedCC) { + // Elided constructor and its context should be either both specified + // or both unspecified. In the former case, the constructor must be + // elidable. + assert(ElidedCE && ElidedCE->isElidable() && ElidedCC); + } + +public: + const CXXConstructExpr *getConstructorAfterElision() const { + return ElidedCE; + } + + const ConstructionContext *getConstructionContextAfterElision() const { + return ElidedCC; + } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == ElidedTemporaryObjectKind; } }; Index: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -327,6 +327,9 @@ /// \sa naiveCTUEnabled Optional NaiveCTU; + /// \sa shouldElideConstructors + Optional ElideConstructors; + /// A helper function that retrieves option for a given full-qualified /// checker name. @@ -703,6 +706,13 @@ /// This is an experimental feature to inline functions from another /// translation units. bool naiveCTUEnabled(); + + /// Returns true if elidable C++ copy-constructors and move-constructors + /// should be actually elided during analysis. Both behaviors are allowed + /// by the C++ standard, and the analyzer, like CodeGen, defaults to eliding. + /// Starting with C++17 some elisions become mandatory, and in these cases + /// the option will be ignored. + bool shouldElideConstructors(); }; using AnalyzerOptionsRef = IntrusiveRefCntPtr; Index: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp =================================================================== --- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp +++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp @@ -71,7 +71,8 @@ bool addInitializers, bool addTemporaryDtors, bool addLifetime, bool addLoopExit, bool addScopes, bool synthesizeBodies, bool addStaticInitBranch, bool addCXXNewAllocator, - bool addRichCXXConstructors, CodeInjector *injector) + bool addRichCXXConstructors, bool markElidedCXXConstructors, + CodeInjector *injector) : Injector(injector), FunctionBodyFarm(ASTCtx, injector), SynthesizeBodies(synthesizeBodies) { cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; @@ -84,6 +85,7 @@ cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch; cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator; cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors; + cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors; } void AnalysisDeclContextManager::clear() { Contexts.clear(); } Index: cfe/trunk/lib/Analysis/CFG.cpp =================================================================== --- cfe/trunk/lib/Analysis/CFG.cpp +++ cfe/trunk/lib/Analysis/CFG.cpp @@ -1252,10 +1252,22 @@ if (!Child) return; + auto withExtraLayer = [this, Layer](Stmt *S) { + return ConstructionContextLayer::create(cfg->getBumpVectorContext(), S, + Layer); + }; + switch(Child->getStmtClass()) { case Stmt::CXXConstructExprClass: case Stmt::CXXTemporaryObjectExprClass: { - consumeConstructionContext(Layer, cast(Child)); + // Support pre-C++17 copy elision AST. + auto *CE = cast(Child); + if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) { + assert(CE->getNumArgs() == 1); + findConstructionContexts(withExtraLayer(CE), CE->getArg(0)); + } + + consumeConstructionContext(Layer, CE); break; } // FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr. @@ -1294,10 +1306,21 @@ } case Stmt::CXXBindTemporaryExprClass: { auto *BTE = cast(Child); - findConstructionContexts( - ConstructionContextLayer::create(cfg->getBumpVectorContext(), - BTE, Layer), - BTE->getSubExpr()); + findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr()); + break; + } + case Stmt::MaterializeTemporaryExprClass: { + // Normally we don't want to search in MaterializeTemporaryExpr because + // it indicates the beginning of a temporary object construction context, + // so it shouldn't be found in the middle. However, if it is the beginning + // of an elidable copy or move construction context, we need to include it. + if (const auto *CE = + dyn_cast_or_null(Layer->getTriggerStmt())) { + if (CE->isElidable()) { + auto *MTE = cast(Child); + findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr()); + } + } break; } case Stmt::ConditionalOperatorClass: { @@ -4931,7 +4954,7 @@ static void print_construction_context(raw_ostream &OS, StmtPrinterHelper &Helper, const ConstructionContext *CC) { - const Stmt *S1 = nullptr, *S2 = nullptr; + SmallVector Stmts; switch (CC->getKind()) { case ConstructionContext::SimpleConstructorInitializerKind: { OS << ", "; @@ -4944,52 +4967,56 @@ const auto *CICC = cast(CC); print_initializer(OS, Helper, CICC->getCXXCtorInitializer()); - S2 = CICC->getCXXBindTemporaryExpr(); + Stmts.push_back(CICC->getCXXBindTemporaryExpr()); break; } case ConstructionContext::SimpleVariableKind: { const auto *SDSCC = cast(CC); - S1 = SDSCC->getDeclStmt(); + Stmts.push_back(SDSCC->getDeclStmt()); break; } case ConstructionContext::CXX17ElidedCopyVariableKind: { const auto *CDSCC = cast(CC); - S1 = CDSCC->getDeclStmt(); - S2 = CDSCC->getCXXBindTemporaryExpr(); + Stmts.push_back(CDSCC->getDeclStmt()); + Stmts.push_back(CDSCC->getCXXBindTemporaryExpr()); break; } case ConstructionContext::NewAllocatedObjectKind: { const auto *NECC = cast(CC); - S1 = NECC->getCXXNewExpr(); + Stmts.push_back(NECC->getCXXNewExpr()); break; } case ConstructionContext::SimpleReturnedValueKind: { const auto *RSCC = cast(CC); - S1 = RSCC->getReturnStmt(); + Stmts.push_back(RSCC->getReturnStmt()); break; } case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { const auto *RSCC = cast(CC); - S1 = RSCC->getReturnStmt(); - S2 = RSCC->getCXXBindTemporaryExpr(); + Stmts.push_back(RSCC->getReturnStmt()); + Stmts.push_back(RSCC->getCXXBindTemporaryExpr()); break; } - case ConstructionContext::TemporaryObjectKind: { - const auto *TOCC = cast(CC); - S1 = TOCC->getCXXBindTemporaryExpr(); - S2 = TOCC->getMaterializedTemporaryExpr(); + case ConstructionContext::SimpleTemporaryObjectKind: { + const auto *TOCC = cast(CC); + Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); + Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); break; } + case ConstructionContext::ElidedTemporaryObjectKind: { + const auto *TOCC = cast(CC); + Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); + Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); + Stmts.push_back(TOCC->getConstructorAfterElision()); + break; } - if (S1) { - OS << ", "; - Helper.handledStmt(const_cast(S1), OS); - } - if (S2) { - OS << ", "; - Helper.handledStmt(const_cast(S2), OS); } + for (auto I: Stmts) + if (I) { + OS << ", "; + Helper.handledStmt(const_cast(I), OS); + } } static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, Index: cfe/trunk/lib/Analysis/ConstructionContext.cpp =================================================================== --- cfe/trunk/lib/Analysis/ConstructionContext.cpp +++ cfe/trunk/lib/Analysis/ConstructionContext.cpp @@ -61,7 +61,6 @@ // For temporaries with destructors, there may or may not be // lifetime extension on the parent layer. if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) { - assert(ParentLayer->isLast()); // C++17 *requires* elision of the constructor at the return site // and at variable/member initialization site, while previous standards // were allowing an optional elidable constructor. @@ -77,8 +76,33 @@ // both destruction and materialization info attached to it in the AST. if ((MTE = dyn_cast( ParentLayer->getTriggerStmt()))) { - return create(C, BTE, MTE); + // Handle pre-C++17 copy and move elision. + const CXXConstructExpr *ElidedCE = nullptr; + const ConstructionContext *ElidedCC = nullptr; + if (const ConstructionContextLayer *ElidedLayer = + ParentLayer->getParent()) { + ElidedCE = cast(ElidedLayer->getTriggerStmt()); + assert(ElidedCE->isElidable()); + // We're creating a construction context that might have already + // been created elsewhere. Maybe we should unique our construction + // contexts. That's what we often do, but in this case it's unlikely + // to bring any benefits. + ElidedCC = createFromLayers(C, ElidedLayer->getParent()); + if (!ElidedCC) { + // We may fail to create the elided construction context. + // In this case, skip copy elision entirely. + return create(C, BTE, + MTE); + } else { + return create( + C, BTE, MTE, ElidedCE, ElidedCC); + } + } + assert(ParentLayer->isLast()); + return create(C, BTE, MTE); } + assert(ParentLayer->isLast()); + // This is a constructor into a function argument. Not implemented yet. if (isa(ParentLayer->getTriggerStmt())) return nullptr; @@ -99,7 +123,11 @@ llvm_unreachable("Unexpected construction context with destructor!"); } // A temporary object that doesn't require materialization. - return create(C, BTE, /*MTE=*/nullptr); + // In particular, it shouldn't require copy elision, because + // copy/move constructors take a reference, which requires + // materialization to obtain the glvalue. + return create(C, BTE, + /*MTE=*/nullptr); } if (const auto *MTE = dyn_cast(S)) { // If the object requires destruction and is not lifetime-extended, @@ -110,8 +138,28 @@ MTE->getStorageDuration() != SD_FullExpression)) return nullptr; + // Handle pre-C++17 copy and move elision. + const CXXConstructExpr *ElidedCE = nullptr; + const ConstructionContext *ElidedCC = nullptr; + if (const ConstructionContextLayer *ElidedLayer = TopLayer->getParent()) { + ElidedCE = cast(ElidedLayer->getTriggerStmt()); + assert(ElidedCE->isElidable()); + // We're creating a construction context that might have already + // been created elsewhere. Maybe we should unique our construction + // contexts. That's what we often do, but in this case it's unlikely + // to bring any benefits. + ElidedCC = createFromLayers(C, ElidedLayer->getParent()); + if (!ElidedCC) { + // We may fail to create the elided construction context. + // In this case, skip copy elision entirely. + return create(C, nullptr, + MTE); + } + return create( + C, nullptr, MTE, ElidedCE, ElidedCC); + } assert(TopLayer->isLast()); - return create(C, nullptr, MTE); + return create(C, nullptr, MTE); } if (const auto *RS = dyn_cast(S)) { assert(TopLayer->isLast()); Index: cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -31,6 +31,7 @@ Options.shouldConditionalizeStaticInitializers(), /*addCXXNewAllocator=*/true, Options.includeRichConstructorsInCFG(), + Options.shouldElideConstructors(), injector), Ctx(ASTCtx), Diags(diags), LangOpts(lang), PathConsumers(PDC), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), Index: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -321,6 +321,12 @@ /* Default = */ false); } +bool AnalyzerOptions::shouldElideConstructors() { + return getBooleanOption(ElideConstructors, + "elide-constructors", + /* Default = */ true); +} + int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal, const CheckerBase *C, bool SearchInParents) { Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -209,7 +209,11 @@ } llvm_unreachable("Unhandled return value construction context!"); } - case ConstructionContext::TemporaryObjectKind: { + case ConstructionContext::ElidedTemporaryObjectKind: + assert(AMgr.getAnalyzerOptions().shouldElideConstructors()); + // FALL-THROUGH + case ConstructionContext::SimpleTemporaryObjectKind: { + // TODO: Copy elision implementation goes here. const auto *TCC = cast(CC); const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); Index: cfe/trunk/test/Analysis/analyzer-config.c =================================================================== --- cfe/trunk/test/Analysis/analyzer-config.c +++ cfe/trunk/test/Analysis/analyzer-config.c @@ -18,6 +18,7 @@ // CHECK-NEXT: cfg-rich-constructors = true // CHECK-NEXT: cfg-scopes = false // CHECK-NEXT: cfg-temporary-dtors = true +// CHECK-NEXT: elide-constructors = true // CHECK-NEXT: exploration_strategy = unexplored_first_queue // CHECK-NEXT: faux-bodies = true // CHECK-NEXT: graph-trim-interval = 1000 @@ -35,4 +36,4 @@ // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 23 +// CHECK-NEXT: num-entries = 24 Index: cfe/trunk/test/Analysis/analyzer-config.cpp =================================================================== --- cfe/trunk/test/Analysis/analyzer-config.cpp +++ cfe/trunk/test/Analysis/analyzer-config.cpp @@ -32,6 +32,7 @@ // CHECK-NEXT: cfg-rich-constructors = true // CHECK-NEXT: cfg-scopes = false // CHECK-NEXT: cfg-temporary-dtors = true +// CHECK-NEXT: elide-constructors = true // CHECK-NEXT: experimental-enable-naive-ctu-analysis = false // CHECK-NEXT: exploration_strategy = unexplored_first_queue // CHECK-NEXT: faux-bodies = true @@ -50,4 +51,4 @@ // CHECK-NEXT: unroll-loops = false // CHECK-NEXT: widen-loops = false // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 30 +// CHECK-NEXT: num-entries = 31 Index: cfe/trunk/test/Analysis/cfg-rich-constructors.cpp =================================================================== --- cfe/trunk/test/Analysis/cfg-rich-constructors.cpp +++ cfe/trunk/test/Analysis/cfg-rich-constructors.cpp @@ -1,7 +1,11 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w %s > %t 2>&1 -// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11 %s +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ELIDE,CXX11-ELIDE %s // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w %s > %t 2>&1 -// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17 %s +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,ELIDE,CXX17-ELIDE %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++11 -w -analyzer-config elide-constructors=false %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,NOELIDE,CXX11-NOELIDE %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++17 -w -analyzer-config elide-constructors=false %s > %t 2>&1 +// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX17,NOELIDE,CXX17-NOELIDE %s class C { public: @@ -99,10 +103,12 @@ // CHECK: void simpleVariableInitializedByValue() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX11-NEXT: 4: [B1.3] // CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C) // CXX11-NEXT: 6: C c = C::get(); +// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX17-NEXT: 4: C c = C::get(); void simpleVariableInitializedByValue() { C c = C::get(); @@ -122,17 +128,21 @@ // CHECK: [B2] // CHECK-NEXT: 1: C::get // CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) +// CXX11-ELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B2.5]) +// CXX11-NOELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) // CXX11-NEXT: 4: [B2.3] -// CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C) +// CXX11-ELIDE-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], [B1.3], class C) +// CXX11-NOELIDE-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C) // CXX17-NEXT: 3: [B2.2]() // CHECK: [B3] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) -// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) +// CXX11-ELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], [B3.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) // CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B3.4] -// CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C) +// CXX11-ELIDE-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], [B1.3], class C) +// CXX11-NOELIDE-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C) // CXX17-NEXT: 3: [B3.2] (CXXConstructExpr, class C) // CXX17-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK: [B4] @@ -146,7 +156,9 @@ // CHECK: void simpleVariableWithElidableCopy() // CHECK: 1: 0 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) -// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX11-ELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], [B1.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) // CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B1.4] // CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C) @@ -185,14 +197,16 @@ // CHECK: [B2] // CHECK-NEXT: 1: C::get // CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) +// CXX11-ELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B2.5]) +// CXX11-NOELIDE-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B2.4]) // CXX11-NEXT: 4: [B2.3] // CXX11-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.3], class C) // CXX17-NEXT: 3: [B2.2]() (CXXRecordTypedCall, [B1.3]) // CHECK: [B3] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) -// CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) +// CXX11-ELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], [B3.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) // CXX11-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B3.4] // CXX11-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.3], class C) @@ -242,7 +256,8 @@ // CHECK-NEXT: 7: CFGNewAllocator(C *) // CHECK-NEXT: 8: C::get // CHECK-NEXT: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11]) +// CXX11-ELIDE-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11], [B1.12]) +// CXX11-NOELIDE-NEXT: 10: [B1.9]() (CXXRecordTypedCall, [B1.11]) // CXX11-NEXT: 11: [B1.10] // CXX11-NEXT: 12: [B1.11] (CXXConstructExpr, [B1.13], class C) // CXX11-NEXT: 13: new C([B1.12]) @@ -270,7 +285,8 @@ // CHECK: F() // CHECK: 1: E::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class ctor_initializers::E (*)( -// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) // CXX11-NEXT: 4: [B1.3] (BindTemporary) // CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class ctor_initializers::E) // CXX11-NEXT: 6: [B1.5] @@ -326,10 +342,12 @@ } // CHECK: C returnTemporary() -// CHECK: 1: C() (CXXConstructExpr, [B1.2], class C) +// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B1.2], [B1.3], class C) +// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B1.2], class C) // CXX11-NEXT: 2: [B1.1] // CXX11-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C) // CXX11-NEXT: 4: return [B1.3]; +// CXX17: 1: C() (CXXConstructExpr, [B1.2], class C) // CXX17-NEXT: 2: return [B1.1]; C returnTemporary() { return C(); @@ -338,7 +356,9 @@ // CHECK: C returnTemporaryWithArgument() // CHECK: 1: nullptr // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) -// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX11-ELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], [B1.6], class C) +// CXX11-NOELIDE-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) +// CXX17-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C) // CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 5: [B1.4] // CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C) @@ -352,10 +372,12 @@ // CHECK: C returnTemporaryConstructedByFunction() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX11-NEXT: 4: [B1.3] // CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.6], class C) // CXX11-NEXT: 6: return [B1.5]; +// CXX17-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX17-NEXT: 4: return [B1.3]; C returnTemporaryConstructedByFunction() { return C::get(); @@ -364,9 +386,11 @@ // CHECK: C returnChainOfCopies() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) -// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4]) // CXX11-NEXT: 4: [B1.3] -// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C) +// CXX11-ELIDE-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], [B1.8], class C) +// CXX11-NOELIDE-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C) // CXX11-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CXX11-NEXT: 7: [B1.6] // CXX11-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C) @@ -390,7 +414,8 @@ // FIXME: There should be no temporary destructor in C++17. // CHECK: return_stmt_with_dtor::D returnTemporary() -// CXX11: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D) +// CXX11-ELIDE: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class return_stmt_with_dtor::D) +// CXX11-NOELIDE: 1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], [B1.4], class return_stmt_with_dtor::D) // CXX11-NEXT: 2: [B1.1] (BindTemporary) // CXX11-NEXT: 3: [B1.2] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D) // CXX11-NEXT: 4: [B1.3] @@ -409,7 +434,8 @@ // CHECK: void returnByValueIntoVariable() // CHECK: 1: returnTemporary // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class return_stmt_with_dtor::D (*)(void)) -// CXX11-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// CXX11-ELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7]) +// CXX11-NOELIDE-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) // CXX11-NEXT: 4: [B1.3] (BindTemporary) // CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D) // CXX11-NEXT: 6: [B1.5] @@ -451,7 +477,8 @@ } // CHECK: void temporaryInConditionVariable() -// CHECK: 1: C() (CXXConstructExpr, [B2.2], class C) +// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C) +// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX11-NEXT: 2: [B2.1] // CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C) // CXX11-NEXT: 4: C c = C(); @@ -461,6 +488,7 @@ // CXX11-NEXT: 8: [B2.6] // CXX11-NEXT: 9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX11-NEXT: T: if [B2.9] +// CXX17: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX17-NEXT: 2: C c = C(); // CXX17-NEXT: 3: c // CXX17-NEXT: 4: [B2.3] (ImplicitCastExpr, NoOp, const class C) @@ -475,7 +503,8 @@ // CHECK: void temporaryInForLoopConditionVariable() // CHECK: [B2] -// CXX11-NEXT: 1: C() (CXXConstructExpr, [B2.2], class C) +// CXX11-ELIDE-NEXT: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C) +// CXX11-NOELIDE-NEXT: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX11-NEXT: 2: [B2.1] // CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C) // CXX11-NEXT: 4: C c2 = C(); @@ -494,7 +523,8 @@ // CXX17-NEXT: 7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX17-NEXT: T: for (...; [B2.7]; ) // CHECK: [B3] -// CXX11-NEXT: 1: C() (CXXConstructExpr, [B3.2], class C) +// CXX11-ELIDE-NEXT: 1: C() (CXXConstructExpr, [B3.2], [B3.3], class C) +// CXX11-NOELIDE-NEXT: 1: C() (CXXConstructExpr, [B3.2], class C) // CXX11-NEXT: 2: [B3.1] // CXX11-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.4], class C) // CXX11-NEXT: 4: C c1 = C(); @@ -505,9 +535,9 @@ } -// FIXME: Find construction context for the loop condition variable. // CHECK: void temporaryInWhileLoopConditionVariable() -// CXX11: 1: C() (CXXConstructExpr, [B2.2], class C) +// CXX11-ELIDE: 1: C() (CXXConstructExpr, [B2.2], [B2.3], class C) +// CXX11-NOELIDE: 1: C() (CXXConstructExpr, [B2.2], class C) // CXX11-NEXT: 2: [B2.1] // CXX11-NEXT: 3: [B2.2] (CXXConstructExpr, [B2.4], class C) // CXX11-NEXT: 4: C c = C(); @@ -603,7 +633,8 @@ // CXX11: [B5] // CXX11-NEXT: 1: D::get // CXX11-NEXT: 2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void)) -// CXX11-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6]) +// CXX11-ELIDE-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6], [B5.7]) +// CXX11-NOELIDE-NEXT: 3: [B5.2]() (CXXRecordTypedCall, [B5.4], [B5.6]) // CXX11-NEXT: 4: [B5.3] (BindTemporary) // CXX11-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 6: [B5.5] @@ -611,7 +642,8 @@ // CXX11-NEXT: 8: [B5.7] (BindTemporary) // CXX11: [B6] // CXX11-NEXT: 1: 0 -// CXX11-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D) +// CXX11-ELIDE-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], [B6.7], class temporary_object_expr_with_dtors::D) +// CXX11-NOELIDE-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 3: [B6.2] (BindTemporary) // CXX11-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) // CXX11-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) @@ -699,7 +731,8 @@ // CHECK: 1: implicit_constructor_conversion::A() (CXXConstructExpr, [B1.3], class implicit_constructor_conversion::A) // CXX11-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A) // CXX11-NEXT: 3: [B1.2] -// CXX11-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], class implicit_constructor_conversion::B) +// CXX11-ELIDE-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], [B1.9], class implicit_constructor_conversion::B) +// CXX11-NOELIDE-NEXT: 4: [B1.3] (CXXConstructExpr, [B1.6], [B1.8], class implicit_constructor_conversion::B) // CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B) // CXX11-NEXT: 6: [B1.5] (BindTemporary) // CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B) @@ -724,7 +757,8 @@ // CHECK-NEXT: 3: [B1.2]() (CXXRecordTypedCall, [B1.5]) // CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A) // CHECK-NEXT: 5: [B1.4] -// CXX11-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], class implicit_constructor_conversion::B) +// CXX11-ELIDE-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], [B1.11], class implicit_constructor_conversion::B) +// CXX11-NOELIDE-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.8], [B1.10], class implicit_constructor_conversion::B) // CXX11-NEXT: 7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_conversion::B) // CXX11-NEXT: 8: [B1.7] (BindTemporary) // CXX11-NEXT: 9: [B1.8] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B) Index: cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp =================================================================== --- cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -235,7 +235,7 @@ // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -295,7 +295,7 @@ // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -550,12 +550,12 @@ // CHECK: Succs (2): B6 B5 // CHECK: [B8] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B8.2], [B8.4], [B8.5], class A) // CHECK: 2: [B8.1] (BindTemporary) // CHECK: 3: [B8.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B8.3] // WARNINGS: 5: [B8.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], class A) +// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], [B7.4], class A) // CHECK: 6: [B8.5] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -570,13 +570,13 @@ // 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], 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], class A) +// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], [B7.4], class A) // CHECK: 15: [B9.14] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -680,7 +680,7 @@ // CHECK: Succs (1): B0 // CHECK: [B4] // WARNINGS: 1: C() (CXXConstructExpr, struct C) -// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], struct C) +// ANALYZER: 1: C() (CXXConstructExpr, [B4.2], [B4.4], [B4.5], struct C) // CHECK: 2: [B4.1] (BindTemporary) // CHECK: 3: [B4.2] (ImplicitCastExpr, NoOp, const struct C) // CHECK: 4: [B4.3] @@ -733,7 +733,7 @@ // CHECK: Succs (1): B0 // CHECK: [B3] // CXX98-WARNINGS: 1: D() (CXXConstructExpr, struct D) -// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], struct D) +// CXX98-ANALYZER: 1: D() (CXXConstructExpr, [B3.3], [B3.4], struct D) // CXX98: 2: [B3.1] (ImplicitCastExpr, NoOp, const struct D) // CXX98: 3: [B3.2] // CXX98-WARNINGS: 4: [B3.3] (CXXConstructExpr, struct D) @@ -745,7 +745,7 @@ // CXX98: 9: [B3.8] (ImplicitCastExpr, UserDefinedConversion, _Bool) // CXX98: T: if [B3.9] // CXX11-WARNINGS: 1: D() (CXXConstructExpr, struct D) -// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D) +// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], [B3.3], struct D) // CXX11: 2: [B3.1] // CXX11-WARNINGS: 3: [B3.2] (CXXConstructExpr, struct D) // CXX11-ANALYZER: 3: [B3.2] (CXXConstructExpr, [B3.4], struct D) @@ -789,7 +789,7 @@ // CHECK: Succs (2): B3 B2 // CHECK: [B5] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B5.2], [B5.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B5.2], [B5.4], [B5.5], class A) // CHECK: 2: [B5.1] (BindTemporary) // CHECK: 3: [B5.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B5.3] @@ -809,7 +809,7 @@ // 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], 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) @@ -852,7 +852,7 @@ // CHECK: Succs (2): B9 B8 // CHECK: [B11] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B11.2], [B11.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B11.2], [B11.4], [B11.5], class A) // CHECK: 2: [B11.1] (BindTemporary) // CHECK: 3: [B11.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B11.3] @@ -872,7 +872,7 @@ // 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], 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) @@ -935,7 +935,7 @@ // CHECK: Succs (1): B4 // CHECK: [B6] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], [B6.5], class A) // CHECK: 2: [B6.1] (BindTemporary) // CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B6.3] @@ -1001,7 +1001,7 @@ // CHECK: Succs (1): B4 // CHECK: [B6] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B6.2], [B6.4], [B6.5], class A) // CHECK: 2: [B6.1] (BindTemporary) // CHECK: 3: [B6.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B6.3] @@ -1086,7 +1086,7 @@ // CHECK: Succs (1): B1 // CHECK: [B1] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], class A) +// ANALYZER: 1: A() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class A) // CHECK: 2: [B1.1] (BindTemporary) // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] @@ -1130,7 +1130,7 @@ // CHECK: 1: A::make // CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) // WARNINGS: 3: [B1.2]() -// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6]) +// ANALYZER: 3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7]) // CHECK: 4: [B1.3] (BindTemporary) // CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) // CHECK: 6: [B1.5]