diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-01-07 19:37:16 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-01-07 19:37:16 +0000 |
commit | 9ce5270f0aadaaf03a0cf705787f42ce9eb1194c (patch) | |
tree | 7fba07e5e993b50a4486b7a0ba08e323b3891e7b | |
parent | 03414b98caba86771622c35b1fa70d13de0c14ba (diff) |
Fix crash in CFGBuilder on invalid code. We still need
to reject this code, but at least clang doesn't
crash anymore.
Crash reported in PR 8880.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123017 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/CFG.cpp | 43 | ||||
-rw-r--r-- | test/Sema/statements.c | 10 |
2 files changed, 33 insertions, 20 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 0db9598853..93d70999ea 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -200,12 +200,12 @@ int LocalScope::const_iterator::distance(LocalScope::const_iterator L) { /// build process. It consists of CFGBlock that specifies position in CFG graph /// and LocalScope::const_iterator that specifies position in LocalScope graph. struct BlockScopePosPair { - BlockScopePosPair() {} - BlockScopePosPair(CFGBlock* B, LocalScope::const_iterator S) - : Block(B), ScopePos(S) {} + BlockScopePosPair() : block(0) {} + BlockScopePosPair(CFGBlock* b, LocalScope::const_iterator scopePos) + : block(b), scopePosition(scopePos) {} - CFGBlock* Block; - LocalScope::const_iterator ScopePos; + CFGBlock *block; + LocalScope::const_iterator scopePosition; }; /// CFGBuilder - This class implements CFG construction from an AST. @@ -481,7 +481,7 @@ CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), E = BackpatchBlocks.end(); I != E; ++I ) { - CFGBlock* B = I->Block; + CFGBlock* B = I->block; GotoStmt* G = cast<GotoStmt>(B->getTerminator()); LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); @@ -490,8 +490,9 @@ CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, if (LI == LabelMap.end()) continue; JumpTarget JT = LI->second; - prependAutomaticObjDtorsWithTerminator(B, I->ScopePos, JT.ScopePos); - addSuccessor(B, JT.Block); + prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, + JT.scopePosition); + addSuccessor(B, JT.block); } // Add successors to the Indirect Goto Dispatch block (if we have one). @@ -506,7 +507,7 @@ CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, // at an incomplete AST. Handle this by not registering a successor. if (LI == LabelMap.end()) continue; - addSuccessor(B, LI->second.Block); + addSuccessor(B, LI->second.block); } // Create an empty entry block that has no predecessors. @@ -1045,9 +1046,9 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { // If there is no target for the break, then we are looking at an incomplete // AST. This means that the CFG cannot be constructed. - if (BreakJumpTarget.Block) { - addAutomaticObjDtors(ScopePos, BreakJumpTarget.ScopePos, B); - addSuccessor(Block, BreakJumpTarget.Block); + if (BreakJumpTarget.block) { + addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); + addSuccessor(Block, BreakJumpTarget.block); } else badCFG = true; @@ -1494,8 +1495,8 @@ CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); else { JumpTarget JT = I->second; - addAutomaticObjDtors(ScopePos, JT.ScopePos, G); - addSuccessor(Block, JT.Block); + addAutomaticObjDtors(ScopePos, JT.scopePosition, G); + addSuccessor(Block, JT.block); } return Block; @@ -1549,6 +1550,8 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { if (Stmt* C = F->getCond()) { Block = ExitConditionBlock; EntryConditionBlock = addStmt(C); + if (badCFG) + return 0; assert(Block == EntryConditionBlock || (Block == 0 && EntryConditionBlock == Succ)); @@ -1616,7 +1619,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { // The starting block for the loop increment is the block that should // represent the 'loop target' for looping back to the start of the loop. - ContinueJumpTarget.Block->setLoopTarget(F); + ContinueJumpTarget.block->setLoopTarget(F); // If body is not a compound statement create implicit scope // and add destructors. @@ -1628,7 +1631,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { CFGBlock* BodyBlock = addStmt(F->getBody()); if (!BodyBlock) - BodyBlock = ContinueJumpTarget.Block;//can happen for "for (...;...;...);" + BodyBlock = ContinueJumpTarget.block;//can happen for "for (...;...;...);" else if (badCFG) return 0; @@ -1894,7 +1897,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { CFGBlock* BodyBlock = addStmt(W->getBody()); if (!BodyBlock) - BodyBlock = ContinueJumpTarget.Block; // can happen for "while(...) ;" + BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" else if (Block) { if (badCFG) return 0; @@ -2078,9 +2081,9 @@ CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { // If there is no target for the continue, then we are looking at an // incomplete AST. This means the CFG cannot be constructed. - if (ContinueJumpTarget.Block) { - addAutomaticObjDtors(ScopePos, ContinueJumpTarget.ScopePos, C); - addSuccessor(Block, ContinueJumpTarget.Block); + if (ContinueJumpTarget.block) { + addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); + addSuccessor(Block, ContinueJumpTarget.block); } else badCFG = true; diff --git a/test/Sema/statements.c b/test/Sema/statements.c index 61eafe6ff0..963b98fe56 100644 --- a/test/Sema/statements.c +++ b/test/Sema/statements.c @@ -90,3 +90,13 @@ void foo(enum x X) { } } +// PR 8880 +// FIXME: Clang should reject this, since GCC does. Previously this +// was causing a crash in the CFG builder. +int test_pr8880() { + int first = 1; + for ( ; ({ if (first) { first = 0; continue; } 0; }); ) + return 0; + return 1; +} + |