summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/ConstructionContext.cpp
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-03-22 21:37:39 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-03-22 21:37:39 +0000
commit317291e34031d61f0ac6a91647df3ac23d82f2a0 (patch)
tree4d5a4a93b135aef048628d2a80de82074849b97d /clang/lib/Analysis/ConstructionContext.cpp
parentd2e77472d1a3c5637c0056eaf2466e3512dc08ec (diff)
downloadbcm5719-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.cpp40
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());
OpenPOWER on IntegriCloud