diff options
author | Devin Coughlin <dcoughlin@apple.com> | 2015-11-25 22:35:37 +0000 |
---|---|---|
committer | Devin Coughlin <dcoughlin@apple.com> | 2015-11-25 22:35:37 +0000 |
commit | b6029b7ef449305ac58845e99306b9faa2d240e7 (patch) | |
tree | 67e08d10c5972645ec054be7a514e7bb61696359 /clang/lib/Analysis/CFG.cpp | |
parent | a774d719a0f9362df894ce8a4090aba79925a1ae (diff) | |
download | bcm5719-llvm-b6029b7ef449305ac58845e99306b9faa2d240e7.tar.gz bcm5719-llvm-b6029b7ef449305ac58845e99306b9faa2d240e7.zip |
[analyzer] Include block capture copy expressions in the CFG.
This prevents spurious dead store warnings when a C++ lambda is casted to a block.
I've also added several tests documenting our still-incomplete support for lambda-to-block
casts.
rdar://problem/22236293
llvm-svn: 254107
Diffstat (limited to 'clang/lib/Analysis/CFG.cpp')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index fba9a41f232..cff15cb3fd8 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -460,6 +460,7 @@ private: CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); CFGBlock *VisitLabelStmt(LabelStmt *L); + CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc); CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc); CFGBlock *VisitLogicalOperator(BinaryOperator *B); std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B, @@ -1453,7 +1454,7 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { return VisitBinaryOperator(cast<BinaryOperator>(S), asc); case Stmt::BlockExprClass: - return VisitNoRecurse(cast<Expr>(S), asc); + return VisitBlockExpr(cast<BlockExpr>(S), asc); case Stmt::BreakStmtClass: return VisitBreakStmt(cast<BreakStmt>(S)); @@ -2333,6 +2334,18 @@ CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { return LabelBlock; } +CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { + CFGBlock *LastBlock = VisitNoRecurse(E, asc); + for (const BlockDecl::Capture &CI : E->getBlockDecl()->captures()) { + if (Expr *CopyExpr = CI.getCopyExpr()) { + CFGBlock *Tmp = Visit(CopyExpr); + if (Tmp) + LastBlock = Tmp; + } + } + return LastBlock; +} + CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { CFGBlock *LastBlock = VisitNoRecurse(E, asc); for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), |