summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/CFG.cpp27
-rw-r--r--clang/lib/Analysis/ConstructionContext.cpp40
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());
OpenPOWER on IntegriCloud