diff options
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 13 | ||||
-rw-r--r-- | clang/test/Analysis/misc-ps.m | 13 |
2 files changed, 21 insertions, 5 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index a0ec5febbef..0957875fd26 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -928,11 +928,13 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { /// VisitChildren - Visit the children of a Stmt. CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) { - CFGBlock *B = Block; - for (Stmt::child_range I = Terminator->children(); I; ++I) { - if (*I) B = Visit(*I); - } - return B; + CFGBlock *lastBlock = Block; + for (Stmt::child_range I = Terminator->children(); I; ++I) + if (Stmt *child = *I) + if (CFGBlock *b = Visit(child)) + lastBlock = b; + + return lastBlock; } CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, @@ -1819,6 +1821,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { if (badCFG) return 0; LoopSuccessor = Block; + Block = 0; } else LoopSuccessor = Succ; diff --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m index 45b44b7412c..4daf899a8dc 100644 --- a/clang/test/Analysis/misc-ps.m +++ b/clang/test/Analysis/misc-ps.m @@ -1233,3 +1233,16 @@ void pr8648() { // crash with assignment y = ({ (union pr8648_union) { .pr8648_union_field = 0LL }; }).pr8648_union_field; } + +// PR 9269 - don't assert when building the following CFG. The for statement +// contains a condition with multiple basic blocks, and the value of the +// statement expression is then indexed as part of a bigger condition expression. +// This example exposed a bug in child traversal in the CFGBuilder. +void pr9269() { + struct s { char *bar[10]; } baz[2] = { 0 }; + unsigned i = 0; + for (i = 0; + (* ({ while(0); ({ &baz[0]; }); })).bar[0] != 0; + ++i) {} +} + |