From: Ted Kremenek Date: Mon, 21 Feb 2011 22:11:26 +0000 (+0000) Subject: Fix a CFGBuilder bug exposed on convoluted control-flow in the Linux kernel. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b12da9f89b7863e6fc995312355b94197b75657;p=clang Fix a CFGBuilder bug exposed on convoluted control-flow in the Linux kernel. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126149 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index a0ec5febbe..0957875fd2 100644 --- a/lib/Analysis/CFG.cpp +++ b/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/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 45b44b7412..4daf899a8d 100644 --- a/test/Analysis/misc-ps.m +++ b/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) {} +} +