diff options
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Analysis/ConstructionContext.cpp | 40 |
2 files changed, 55 insertions, 12 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 0672b3d9256..77eb1d37a40 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -760,9 +760,7 @@ private: const ConstructionContext *CC = ConstructionContext::createFromLayers(cfg->getBumpVectorContext(), Layer); - B->appendCXXRecordTypedCall( - CE, cast<TemporaryObjectConstructionContext>(CC), - cfg->getBumpVectorContext()); + B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext()); cleanupConstructionContext(CE); return; } @@ -1284,7 +1282,7 @@ void CFGBuilder::findConstructionContexts( } case Stmt::ImplicitCastExprClass: { auto *Cast = cast<ImplicitCastExpr>(Child); - // TODO: We need to support CK_ConstructorConversion, maybe other kinds? + // Should we support other implicit cast kinds? switch (Cast->getCastKind()) { case CK_NoOp: case CK_ConstructorConversion: @@ -4920,8 +4918,14 @@ static void print_construction_context(raw_ostream &OS, break; } case ConstructionContext::SimpleVariableKind: { - const auto *DSCC = cast<SimpleVariableConstructionContext>(CC); - S1 = DSCC->getDeclStmt(); + const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC); + S1 = SDSCC->getDeclStmt(); + break; + } + case ConstructionContext::CXX17ElidedCopyVariableKind: { + const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC); + S1 = CDSCC->getDeclStmt(); + S2 = CDSCC->getCXXBindTemporaryExpr(); break; } case ConstructionContext::NewAllocatedObjectKind: { @@ -4929,9 +4933,16 @@ static void print_construction_context(raw_ostream &OS, S1 = NECC->getCXXNewExpr(); break; } - case ConstructionContext::ReturnedValueKind: { - const auto *RSCC = cast<ReturnedValueConstructionContext>(CC); + case ConstructionContext::SimpleReturnedValueKind: { + const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC); + S1 = RSCC->getReturnStmt(); + break; + } + case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { + const auto *RSCC = + cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC); S1 = RSCC->getReturnStmt(); + S2 = RSCC->getCXXBindTemporaryExpr(); break; } case ConstructionContext::TemporaryObjectKind: { diff --git a/clang/lib/Analysis/ConstructionContext.cpp b/clang/lib/Analysis/ConstructionContext.cpp index 1a1bc7db8fb..68e1cc04746 100644 --- a/clang/lib/Analysis/ConstructionContext.cpp +++ b/clang/lib/Analysis/ConstructionContext.cpp @@ -64,11 +64,43 @@ const ConstructionContext *ConstructionContext::createFromLayers( // lifetime extension on the parent layer. if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) { assert(ParentLayer->isLast()); - MTE = cast<MaterializeTemporaryExpr>(ParentLayer->getTriggerStmt()); + if ((MTE = dyn_cast<MaterializeTemporaryExpr>( + ParentLayer->getTriggerStmt()))) { + // A temporary object which has both destruction and + // materialization info. + auto *CC = + C.getAllocator().Allocate<TemporaryObjectConstructionContext>(); + return new (CC) TemporaryObjectConstructionContext(BTE, MTE); + } + // C++17 *requires* elision of the constructor at the return site + // and at variable initialization site, while previous standards + // were allowing an optional elidable constructor. + if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) { + assert(!RS->getRetValue()->getType().getCanonicalType() + ->getAsCXXRecordDecl()->hasTrivialDestructor()); + auto *CC = + C.getAllocator() + .Allocate< + CXX17ElidedCopyReturnedValueConstructionContext>(); + return new (CC) + CXX17ElidedCopyReturnedValueConstructionContext(RS, BTE); + } + if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) { + assert(!cast<VarDecl>(DS->getSingleDecl())->getType() + .getCanonicalType()->getAsCXXRecordDecl() + ->hasTrivialDestructor()); + auto *CC = + C.getAllocator() + .Allocate<CXX17ElidedCopyVariableConstructionContext>(); + return new (CC) CXX17ElidedCopyVariableConstructionContext(DS, BTE); + } + llvm_unreachable("Unexpected construction context with destructor!"); } + // A temporary object that doesn't require materialization. auto *CC = C.getAllocator().Allocate<TemporaryObjectConstructionContext>(); - return new (CC) TemporaryObjectConstructionContext(BTE, MTE); + return new (CC) + TemporaryObjectConstructionContext(BTE, /*MTE=*/nullptr); } else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) { // If the object requires destruction and is not lifetime-extended, // then it must have a BTE within its MTE. @@ -82,8 +114,8 @@ const ConstructionContext *ConstructionContext::createFromLayers( } else if (const auto *RS = dyn_cast<ReturnStmt>(S)) { assert(TopLayer->isLast()); auto *CC = - C.getAllocator().Allocate<ReturnedValueConstructionContext>(); - return new (CC) ReturnedValueConstructionContext(RS); + C.getAllocator().Allocate<SimpleReturnedValueConstructionContext>(); + return new (CC) SimpleReturnedValueConstructionContext(RS); } } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) { assert(TopLayer->isLast()); |