diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-07-31 20:45:53 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-07-31 20:45:53 +0000 |
commit | a657a32cc8fe05cd6fdb1578834a719c169493ae (patch) | |
tree | 1ce53125b4393b867acb0f5adbfa80e4b21ee364 /clang/lib/Analysis/ConstructionContext.cpp | |
parent | 118c47b6d19acfaed0405773ff00ccd690dfd179 (diff) | |
download | bcm5719-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.cpp | 22 |
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()); |