We've started seeing an assertion failure after this commit: assert.h assertion failed at llvm/tools/clang/lib/Analysis/CFG.cpp:1266 in void (anonymous namespace)::CFGBuilder::findConstructionContexts(const clang::ConstructionContextLayer *, clang::Stmt *): CE->getNumArgs() == 1
The stack trace is: ::CFGBuilder::findConstructionContexts ::CFGBuilder::VisitReturnStmt ::CFGBuilder::Visit ::CFGBuilder::addStmt ::CFGBuilder::VisitCompoundStmt ::CFGBuilder::Visit ::CFGBuilder::addStmt ::CFGBuilder::buildCFG clang::CFG::buildCFG clang::AnalysisDeclContext::getCFG clang::ento::AnalysisManager::getCFG ::AnalysisConsumer::HandleCode clang::RecursiveASTVisitor::TraverseDecl clang::RecursiveASTVisitor::TraverseDeclContextHelper clang::RecursiveASTVisitor::TraverseDecl clang::RecursiveASTVisitor::TraverseDeclContextHelper clang::RecursiveASTVisitor::TraverseDecl ::AnalysisConsumer::runAnalysisOnTranslationUnit ::AnalysisConsumer::HandleTranslationUnit No test case yet. On Thu, Jun 28, 2018 at 2:09 AM Artem Dergachev via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: dergachev > Date: Wed Jun 27 17:04:54 2018 > New Revision: 335795 > > URL: http://llvm.org/viewvc/llvm-project?rev=335795&view=rev > Log: > [CFG] [analyzer] Add construction contexts that explain pre-C++17 copy > elision. > > Before C++17 copy elision was optional, even if the elidable copy/move > constructor had arbitrary side effects. The elidable constructor is present > in the AST, but marked as elidable. > > In these cases CFG now contains additional information that allows its > clients > to figure out if a temporary object is only being constructed so that to > pass > it to an elidable constructor. If so, it includes a reference to the > elidable > constructor's construction context, so that the client could elide the > elidable constructor and construct the object directly at its final > destination. > > Differential Revision: https://reviews.llvm.org/D47616 > > Modified: > cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h > cfe/trunk/include/clang/Analysis/CFG.h > cfe/trunk/include/clang/Analysis/ConstructionContext.h > cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h > cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp > cfe/trunk/lib/Analysis/CFG.cpp > cfe/trunk/lib/Analysis/ConstructionContext.cpp > cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp > cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp > cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp > cfe/trunk/test/Analysis/analyzer-config.c > cfe/trunk/test/Analysis/analyzer-config.cpp > cfe/trunk/test/Analysis/cfg-rich-constructors.cpp > cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp > > Modified: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h (original) > +++ cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h Wed Jun 27 > 17:04:54 2018 > @@ -451,6 +451,7 @@ public: > bool addStaticInitBranches = false, > bool addCXXNewAllocator = true, > bool addRichCXXConstructors = true, > + bool markElidedCXXConstructors = true, > CodeInjector *injector = nullptr); > > AnalysisDeclContext *getContext(const Decl *D); > > Modified: cfe/trunk/include/clang/Analysis/CFG.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Analysis/CFG.h (original) > +++ cfe/trunk/include/clang/Analysis/CFG.h Wed Jun 27 17:04:54 2018 > @@ -1025,6 +1025,7 @@ public: > bool AddCXXNewAllocator = false; > bool AddCXXDefaultInitExprInCtors = false; > bool AddRichCXXConstructors = false; > + bool MarkElidedCXXConstructors = false; > > BuildOptions() = default; > > > Modified: cfe/trunk/include/clang/Analysis/ConstructionContext.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ConstructionContext.h?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Analysis/ConstructionContext.h (original) > +++ cfe/trunk/include/clang/Analysis/ConstructionContext.h Wed Jun 27 > 17:04:54 2018 > @@ -107,7 +107,10 @@ public: > 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 @@ class TemporaryObjectConstructionContext > 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 @@ public: > } > > 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; > } > }; > > > Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h > (original) > +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Wed Jun > 27 17:04:54 2018 > @@ -327,6 +327,9 @@ private: > /// \sa naiveCTUEnabled > Optional<bool> NaiveCTU; > > + /// \sa shouldElideConstructors > + Optional<bool> ElideConstructors; > + > > /// A helper function that retrieves option for a given full-qualified > /// checker name. > @@ -703,6 +706,13 @@ public: > /// 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<AnalyzerOptions>; > > Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original) > +++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Wed Jun 27 17:04:54 2018 > @@ -71,7 +71,8 @@ AnalysisDeclContextManager::AnalysisDecl > 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 @@ AnalysisDeclContextManager::AnalysisDecl > cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch; > cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator; > cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors; > + cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors; > } > > void AnalysisDeclContextManager::clear() { Contexts.clear(); } > > Modified: cfe/trunk/lib/Analysis/CFG.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/lib/Analysis/CFG.cpp (original) > +++ cfe/trunk/lib/Analysis/CFG.cpp Wed Jun 27 17:04:54 2018 > @@ -1252,10 +1252,22 @@ void CFGBuilder::findConstructionContext > 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<CXXConstructExpr>(Child)); > + // Support pre-C++17 copy elision AST. > + auto *CE = cast<CXXConstructExpr>(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 @@ void CFGBuilder::findConstructionContext > } > case Stmt::CXXBindTemporaryExprClass: { > auto *BTE = cast<CXXBindTemporaryExpr>(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<CXXConstructExpr>(Layer->getTriggerStmt())) { > + if (CE->isElidable()) { > + auto *MTE = cast<MaterializeTemporaryExpr>(Child); > + findConstructionContexts(withExtraLayer(MTE), > MTE->GetTemporaryExpr()); > + } > + } > break; > } > case Stmt::ConditionalOperatorClass: { > @@ -4931,7 +4954,7 @@ static void print_initializer(raw_ostrea > static void print_construction_context(raw_ostream &OS, > StmtPrinterHelper &Helper, > const ConstructionContext *CC) { > - const Stmt *S1 = nullptr, *S2 = nullptr; > + SmallVector<const Stmt *, 3> Stmts; > switch (CC->getKind()) { > case ConstructionContext::SimpleConstructorInitializerKind: { > OS << ", "; > @@ -4944,52 +4967,56 @@ static void print_construction_context(r > const auto *CICC = > > cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC); > print_initializer(OS, Helper, CICC->getCXXCtorInitializer()); > - S2 = CICC->getCXXBindTemporaryExpr(); > + Stmts.push_back(CICC->getCXXBindTemporaryExpr()); > break; > } > case ConstructionContext::SimpleVariableKind: { > const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC); > - S1 = SDSCC->getDeclStmt(); > + Stmts.push_back(SDSCC->getDeclStmt()); > break; > } > case ConstructionContext::CXX17ElidedCopyVariableKind: { > const auto *CDSCC = > cast<CXX17ElidedCopyVariableConstructionContext>(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<NewAllocatedObjectConstructionContext>(CC); > - S1 = NECC->getCXXNewExpr(); > + Stmts.push_back(NECC->getCXXNewExpr()); > break; > } > case ConstructionContext::SimpleReturnedValueKind: { > const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC); > - S1 = RSCC->getReturnStmt(); > + Stmts.push_back(RSCC->getReturnStmt()); > break; > } > case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { > const auto *RSCC = > cast<CXX17ElidedCopyReturnedValueConstructionContext>(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<TemporaryObjectConstructionContext>(CC); > - S1 = TOCC->getCXXBindTemporaryExpr(); > - S2 = TOCC->getMaterializedTemporaryExpr(); > + case ConstructionContext::SimpleTemporaryObjectKind: { > + const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC); > + Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); > + Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); > break; > } > + case ConstructionContext::ElidedTemporaryObjectKind: { > + const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC); > + Stmts.push_back(TOCC->getCXXBindTemporaryExpr()); > + Stmts.push_back(TOCC->getMaterializedTemporaryExpr()); > + Stmts.push_back(TOCC->getConstructorAfterElision()); > + break; > } > - if (S1) { > - OS << ", "; > - Helper.handledStmt(const_cast<Stmt *>(S1), OS); > - } > - if (S2) { > - OS << ", "; > - Helper.handledStmt(const_cast<Stmt *>(S2), OS); > } > + for (auto I: Stmts) > + if (I) { > + OS << ", "; > + Helper.handledStmt(const_cast<Stmt *>(I), OS); > + } > } > > static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, > > Modified: cfe/trunk/lib/Analysis/ConstructionContext.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ConstructionContext.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/lib/Analysis/ConstructionContext.cpp (original) > +++ cfe/trunk/lib/Analysis/ConstructionContext.cpp Wed Jun 27 17:04:54 2018 > @@ -61,7 +61,6 @@ const ConstructionContext *ConstructionC > // 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 @@ const ConstructionContext *ConstructionC > // both destruction and materialization info attached to it in > the AST. > if ((MTE = dyn_cast<MaterializeTemporaryExpr>( > ParentLayer->getTriggerStmt()))) { > - return create<TemporaryObjectConstructionContext>(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<CXXConstructExpr>(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<SimpleTemporaryObjectConstructionContext>(C, > BTE, > + > MTE); > + } else { > + return create<ElidedTemporaryObjectConstructionContext>( > + C, BTE, MTE, ElidedCE, ElidedCC); > + } > + } > + assert(ParentLayer->isLast()); > + return create<SimpleTemporaryObjectConstructionContext>(C, BTE, > MTE); > } > + assert(ParentLayer->isLast()); > + > // This is a constructor into a function argument. Not > implemented yet. > if (isa<CallExpr>(ParentLayer->getTriggerStmt())) > return nullptr; > @@ -99,7 +123,11 @@ const ConstructionContext *ConstructionC > llvm_unreachable("Unexpected construction context with > destructor!"); > } > // A temporary object that doesn't require materialization. > - return create<TemporaryObjectConstructionContext>(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<SimpleTemporaryObjectConstructionContext>(C, BTE, > + > /*MTE=*/nullptr); > } > if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) { > // If the object requires destruction and is not lifetime-extended, > @@ -110,8 +138,28 @@ const ConstructionContext *ConstructionC > 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<CXXConstructExpr>(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<SimpleTemporaryObjectConstructionContext>(C, > nullptr, > + MTE); > + } > + return create<ElidedTemporaryObjectConstructionContext>( > + C, nullptr, MTE, ElidedCE, ElidedCC); > + } > assert(TopLayer->isLast()); > - return create<TemporaryObjectConstructionContext>(C, nullptr, MTE); > + return create<SimpleTemporaryObjectConstructionContext>(C, nullptr, > MTE); > } > if (const auto *RS = dyn_cast<ReturnStmt>(S)) { > assert(TopLayer->isLast()); > > Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp Wed Jun 27 > 17:04:54 2018 > @@ -31,6 +31,7 @@ AnalysisManager::AnalysisManager( > Options.shouldConditionalizeStaticInitializers(), > /*addCXXNewAllocator=*/true, > Options.includeRichConstructorsInCFG(), > + Options.shouldElideConstructors(), > injector), > Ctx(ASTCtx), Diags(diags), LangOpts(lang), PathConsumers(PDC), > CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), > > Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Wed Jun 27 > 17:04:54 2018 > @@ -321,6 +321,12 @@ bool AnalyzerOptions::shouldSerializeSta > /* Default = */ false); > } > > +bool AnalyzerOptions::shouldElideConstructors() { > + return getBooleanOption(ElideConstructors, > + "elide-constructors", > + /* Default = */ true); > +} > + > int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal, > const CheckerBase *C, > bool SearchInParents) { > > Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Jun 27 > 17:04:54 2018 > @@ -209,7 +209,11 @@ std::pair<ProgramStateRef, SVal> ExprEng > } > 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<TemporaryObjectConstructionContext>(CC); > const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); > const MaterializeTemporaryExpr *MTE = > TCC->getMaterializedTemporaryExpr(); > > Modified: cfe/trunk/test/Analysis/analyzer-config.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-config.c?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/test/Analysis/analyzer-config.c (original) > +++ cfe/trunk/test/Analysis/analyzer-config.c Wed Jun 27 17:04:54 2018 > @@ -18,6 +18,7 @@ void foo() { > // 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 @@ void foo() { > // CHECK-NEXT: unroll-loops = false > // CHECK-NEXT: widen-loops = false > // CHECK-NEXT: [stats] > -// CHECK-NEXT: num-entries = 23 > +// CHECK-NEXT: num-entries = 24 > > Modified: cfe/trunk/test/Analysis/analyzer-config.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-config.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/test/Analysis/analyzer-config.cpp (original) > +++ cfe/trunk/test/Analysis/analyzer-config.cpp Wed Jun 27 17:04:54 2018 > @@ -32,6 +32,7 @@ public: > // 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 @@ public: > // CHECK-NEXT: unroll-loops = false > // CHECK-NEXT: widen-loops = false > // CHECK-NEXT: [stats] > -// CHECK-NEXT: num-entries = 30 > +// CHECK-NEXT: num-entries = 31 > > Modified: cfe/trunk/test/Analysis/cfg-rich-constructors.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cfg-rich-constructors.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/test/Analysis/cfg-rich-constructors.cpp (original) > +++ cfe/trunk/test/Analysis/cfg-rich-constructors.cpp Wed Jun 27 17:04:54 > 2018 > @@ -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 @@ void simpleVariableWithOperatorNewInBrac > // 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 @@ void simpleVariableInitializedByValue() > // 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 @@ void simpleVariableWithTernaryOperator(b > // 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 @@ void referenceVariableWithInitializer() > // 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 @@ public: > // 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 @@ public: > // 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 @@ C returnBracesWithMultipleItems() { > } > > // 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 @@ C returnTemporary() { > // 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 @@ C returnTemporaryWithArgument() { > // 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 @@ C returnTemporaryConstructedByFunction() > // 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 @@ public: > > // 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 @@ D returnTemporary() { > // 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 @@ void temporaryInCondition() { > } > > // 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 @@ void temporaryInCondition() { > // 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 @@ void temporaryInConditionVariable() { > > // 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 @@ void temporaryInConditionVariable() { > // 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 @@ void temporaryInForLoopConditionVariable > } > > > -// 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 @@ void referenceVariableWithInitializer() > // 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 @@ void referenceVariableWithInitializer() > // 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 @@ public: > // 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 @@ void implicitConstructionConversionFromT > // 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) > > Modified: cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp?rev=335795&r1=335794&r2=335795&view=diff > > ============================================================================== > --- cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp (original) > +++ cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp Wed Jun 27 > 17:04:54 2018 > @@ -235,7 +235,7 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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 @@ const C &bar3(bool coin) { > // 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] > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits