aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-04-18 19:30:02 +0000
committerChris Lattner <sabre@nondot.org>2009-04-18 19:30:02 +0000
commite32f74c7af4064a08aaf21fc181de72138450197 (patch)
tree5828484d9e58da499e4a5ca3e23536c14029de66 /lib/Sema/SemaDecl.cpp
parentca93195baf1076ee6232a722f5ea5e580fc67a4f (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.cpp52
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();