From 828f631af1b5520d43fa038c0d9390717642ac39 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 21 Feb 2011 22:11:26 +0000 Subject: [PATCH] Fix a CFGBuilder bug exposed on convoluted control-flow in the Linux kernel. llvm-svn: 126149 --- clang/lib/Analysis/CFG.cpp | 13 ++++++++----- 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 a0ec5febbeff..0957875fd268 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 45b44b7412c9..4daf899a8dc0 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) {} +} +