diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-07-31 19:39:37 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-07-31 19:39:37 +0000 |
commit | bd880fe1c1235f48d5e537af563362ddc4f8af53 (patch) | |
tree | 7a3306948c07a228645b403ec6e1c43deb6d6a39 /clang/lib/Analysis/CFG.cpp | |
parent | 959fe03933e5f841f77219d526f88055c081d9a0 (diff) | |
download | bcm5719-llvm-bd880fe1c1235f48d5e537af563362ddc4f8af53.tar.gz bcm5719-llvm-bd880fe1c1235f48d5e537af563362ddc4f8af53.zip |
[CFG] [analyzer] Add stubs for constructor and message argument constructors.
CFG now correctly identifies construction context for temporaries constructed
for the purpose of passing into a function as an argument.
Such context is still not fully implemented because the information it provides
is not rich enough: it doens't contain information about argument index.
It will be addresssed later.
This patch is an extension of r330377 to C++ construct-expressions and
Objective-C message expressions which aren't call-expressions but require
similar handling. C++ new-expressions with placement arguments still remain to
be handled.
Differential Revision: https://reviews.llvm.org/D49826
llvm-svn: 338425
Diffstat (limited to 'clang/lib/Analysis/CFG.cpp')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 0e529bb0c52..9e4fbd68899 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -569,6 +569,7 @@ private: CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); + CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc); CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); CFGBlock *VisitReturnStmt(ReturnStmt *R); CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S); @@ -683,6 +684,27 @@ private: void findConstructionContexts(const ConstructionContextLayer *Layer, Stmt *Child); + // Scan all arguments of a call expression for a construction context. + // These sorts of call expressions don't have a common superclass, + // hence strict duck-typing. + template <typename CallLikeExpr, + typename = typename std::enable_if< + std::is_same<CallLikeExpr, CallExpr>::value || + std::is_same<CallLikeExpr, CXXConstructExpr>::value || + std::is_same<CallLikeExpr, ObjCMessageExpr>::value>> + void findConstructionContextsForArguments(CallLikeExpr *E) { + // A stub for the code that'll eventually be used for finding construction + // contexts for constructors of C++ object-type arguments passed into + // call-like expression E. + // FIXME: Once actually implemented, this construction context layer should + // include the index of the argument as well. + for (auto Arg : E->arguments()) + if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue()) + findConstructionContexts( + ConstructionContextLayer::create(cfg->getBumpVectorContext(), E), + Arg); + } + // Unset the construction context after consuming it. This is done immediately // after adding the CFGConstructor or CFGCXXRecordTypedCall element, so // there's no need to do this manually in every Visit... function. @@ -2101,6 +2123,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::ObjCForCollectionStmtClass: return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); + case Stmt::ObjCMessageExprClass: + return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc); + case Stmt::OpaqueValueExprClass: return Block; @@ -2383,12 +2408,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { if (!boundType.isNull()) calleeType = boundType; } - // FIXME: Once actually implemented, this construction context layer should - // include the number of the argument as well. - for (auto Arg: C->arguments()) { - findConstructionContexts( - ConstructionContextLayer::create(cfg->getBumpVectorContext(), C), Arg); - } + findConstructionContextsForArguments(C); // If this is a call to a no-return function, this stops the block here. bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); @@ -3580,6 +3600,16 @@ CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { return VisitStmt(S, AddStmtChoice::AlwaysAdd); } +CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME, + AddStmtChoice asc) { + findConstructionContextsForArguments(ME); + + autoCreateBlock(); + appendStmt(Block, ME); + + return VisitChildren(ME); +} + CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { // If we were in the middle of a block we stop processing that block. if (badCFG) @@ -4244,6 +4274,11 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc) { + // If the constructor takes objects as arguments by value, we need to properly + // construct these objects. Construction contexts we find here aren't for the + // constructor C, they're for its arguments only. + findConstructionContextsForArguments(C); + autoCreateBlock(); appendConstructor(Block, C); |