diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-03-22 21:37:39 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-03-22 21:37:39 +0000 |
commit | 317291e34031d61f0ac6a91647df3ac23d82f2a0 (patch) | |
tree | 4d5a4a93b135aef048628d2a80de82074849b97d /clang/lib/Analysis/ConstructionContext.cpp | |
parent | d2e77472d1a3c5637c0056eaf2466e3512dc08ec (diff) | |
download | bcm5719-llvm-317291e34031d61f0ac6a91647df3ac23d82f2a0.tar.gz bcm5719-llvm-317291e34031d61f0ac6a91647df3ac23d82f2a0.zip |
[CFG] [analyzer] Add C++17-specific variable and return construction contexts.
In C++17 copy elision is mandatory for variable and return value constructors
(as long as it doesn't involve type conversion) which results in AST that does
not contain elidable constructors in their usual places. In order to provide
construction contexts in this scenario we need to cover more AST patterns.
This patch makes the CFG prepared for these scenarios by:
- Fork VariableConstructionContext and ReturnedValueConstructionContext into
two different sub-classes (each) one of which indicates the C++17 case and
contains a reference to an extra CXXBindTemporaryExpr.
- Allow CFGCXXRecordTypedCall element to accept VariableConstructionContext and
ReturnedValueConstructionContext as its context.
Differential Revision: https://reviews.llvm.org/D44597
llvm-svn: 328248
Diffstat (limited to 'clang/lib/Analysis/ConstructionContext.cpp')
-rw-r--r-- | clang/lib/Analysis/ConstructionContext.cpp | 40 |
1 files changed, 36 insertions, 4 deletions
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()); |