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