diff options
author | Chris Lattner <sabre@nondot.org> | 2009-04-18 19:30:02 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-04-18 19:30:02 +0000 |
commit | e32f74c7af4064a08aaf21fc181de72138450197 (patch) | |
tree | 5828484d9e58da499e4a5ca3e23536c14029de66 /lib/Sema/SemaDecl.cpp | |
parent | ca93195baf1076ee6232a722f5ea5e580fc67a4f (diff) |
fix error recovery in the case of a jump to a label with no definition
to create a well formed AST instead of a dangling pointer. This resolves
several fixme's.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69459 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 3ea7f05eb3..772db3b247 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3067,10 +3067,6 @@ void JumpScopeChecker::VerifyJumps() { Stmt *Jump = Jumps.pop_back_val(); if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { - // FIXME: invalid code makes dangling AST, see test6 in scope-check.c. - // FIXME: This is a hack. - if (!LabelAndGotoScopes.count(GS->getLabel())) return; - assert(LabelAndGotoScopes.count(GS->getLabel()) && "Label not visited?"); CheckJump(GS, LabelAndGotoScopes[GS->getLabel()], diag::err_goto_into_protected_scope); @@ -3155,31 +3151,37 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) { // Check goto/label use. for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) { + LabelStmt *L = I->second; + // Verify that we have no forward references left. If so, there was a goto // or address of a label taken, but no definition of it. Label fwd // definitions are indicated with a null substmt. - if (I->second->getSubStmt() == 0) { - LabelStmt *L = I->second; - // Emit error. - Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName(); - - // At this point, we have gotos that use the bogus label. Stitch it into - // the function body so that they aren't leaked and that the AST is well - // formed. - if (Body) { -#if 0 - // FIXME: Why do this? Having a 'push_back' in CompoundStmt is ugly, - // and the AST is malformed anyway. We should just blow away 'L'. - L->setSubStmt(new (Context) NullStmt(L->getIdentLoc())); - cast<CompoundStmt>(Body)->push_back(L); -#else - L->Destroy(Context); -#endif - } else { - // The whole function wasn't parsed correctly, just delete this. - L->Destroy(Context); - } + if (L->getSubStmt() != 0) + continue; + + // Emit error. + Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName(); + + // At this point, we have gotos that use the bogus label. Stitch it into + // the function body so that they aren't leaked and that the AST is well + // formed. + if (Body == 0) { + // The whole function wasn't parsed correctly, just delete this. + L->Destroy(Context); + continue; } + + // Otherwise, the body is valid: we want to stitch the label decl into the + // function somewhere so that it is properly owned and so that the goto + // has a valid target. Do this by creating a new compound stmt with the + // label in it. + + // Give the label a sub-statement. + L->setSubStmt(new (Context) NullStmt(L->getIdentLoc())); + + std::vector<Stmt*> Elements(Body->body_begin(), Body->body_end()); + Elements.push_back(L); + Body->setStmts(Context, &Elements[0], Elements.size()); } LabelMap.clear(); |