summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/ConstructionContext.cpp
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-07-31 20:45:53 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-07-31 20:45:53 +0000
commita657a32cc8fe05cd6fdb1578834a719c169493ae (patch)
tree1ce53125b4393b867acb0f5adbfa80e4b21ee364 /clang/lib/Analysis/ConstructionContext.cpp
parent118c47b6d19acfaed0405773ff00ccd690dfd179 (diff)
downloadbcm5719-llvm-a657a32cc8fe05cd6fdb1578834a719c169493ae.tar.gz
bcm5719-llvm-a657a32cc8fe05cd6fdb1578834a719c169493ae.zip
[CFG] [analyzer] Implement function argument construction contexts.
In r330377 and r338425 we have already identified what constitutes function argument constructors and added stubs in order to prevent confusing them with other temporary object constructors. Now we implement a ConstructionContext sub-class to carry all the necessary information about the construction site, namely call expression and argument index. On the analyzer side, the patch interacts with the recently implemented pre-C++17 copy elision support in an interesting manner. If on the CFG side we didn't find a construction context for the elidable constructor, we build the CFG as if the elidable constructor is not elided, and the non-elided constructor within it is a simple temporary. But the same problem may occur in the analyzer: if the elidable constructor has a construction context but the analyzer doesn't implement such context yet, the analyzer should also try to skip copy elision and still inline the non-elided temporary constructor. This was implemented by adding a "roll back" mechanism: when elision fails, roll back the changes and proceed as if it's a simple temporary. The approach is wonky, but i'm fine with that as long as it's merely a defensive mechanism that should eventually go away once all construction contexts become supported. Differential Revision: https://reviews.llvm.org/D48681. llvm-svn: 338436
Diffstat (limited to 'clang/lib/Analysis/ConstructionContext.cpp')
-rw-r--r--clang/lib/Analysis/ConstructionContext.cpp22
1 files changed, 15 insertions, 7 deletions
diff --git a/clang/lib/Analysis/ConstructionContext.cpp b/clang/lib/Analysis/ConstructionContext.cpp
index 3ffb0a6b35c..9d255a0bcfa 100644
--- a/clang/lib/Analysis/ConstructionContext.cpp
+++ b/clang/lib/Analysis/ConstructionContext.cpp
@@ -21,10 +21,11 @@ using namespace clang;
const ConstructionContextLayer *
ConstructionContextLayer::create(BumpVectorContext &C, TriggerTy Trigger,
+ unsigned Index,
const ConstructionContextLayer *Parent) {
ConstructionContextLayer *CC =
C.getAllocator().Allocate<ConstructionContextLayer>();
- return new (CC) ConstructionContextLayer(Trigger, Parent);
+ return new (CC) ConstructionContextLayer(Trigger, Index, Parent);
}
bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
@@ -111,11 +112,14 @@ const ConstructionContext *ConstructionContext::createFromLayers(
}
assert(ParentLayer->isLast());
- // This is a constructor into a function argument. Not implemented yet.
+ // This is a constructor into a function argument.
if (isa<CallExpr>(ParentLayer->getTriggerStmt()) ||
isa<CXXConstructExpr>(ParentLayer->getTriggerStmt()) ||
- isa<ObjCMessageExpr>(ParentLayer->getTriggerStmt()))
- return nullptr;
+ isa<ObjCMessageExpr>(ParentLayer->getTriggerStmt())) {
+ return create<ArgumentConstructionContext>(
+ C, cast<Expr>(ParentLayer->getTriggerStmt()),
+ ParentLayer->getIndex(), BTE);
+ }
// This is C++17 copy-elided construction into return statement.
if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
assert(!RS->getRetValue()->getType().getCanonicalType()
@@ -175,11 +179,15 @@ const ConstructionContext *ConstructionContext::createFromLayers(
assert(TopLayer->isLast());
return create<SimpleReturnedValueConstructionContext>(C, RS);
}
- // This is a constructor into a function argument. Not implemented yet.
+ // This is a constructor into a function argument.
if (isa<CallExpr>(TopLayer->getTriggerStmt()) ||
isa<CXXConstructExpr>(TopLayer->getTriggerStmt()) ||
- isa<ObjCMessageExpr>(TopLayer->getTriggerStmt()))
- return nullptr;
+ isa<ObjCMessageExpr>(TopLayer->getTriggerStmt())) {
+ assert(TopLayer->isLast());
+ return create<ArgumentConstructionContext>(
+ C, cast<Expr>(TopLayer->getTriggerStmt()), TopLayer->getIndex(),
+ /*BTE=*/nullptr);
+ }
llvm_unreachable("Unexpected construction context with statement!");
} else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
assert(TopLayer->isLast());
OpenPOWER on IntegriCloud