diff options
author | Chris Lattner <sabre@nondot.org> | 2010-01-24 01:50:29 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-01-24 01:50:29 +0000 |
commit | 7e52de4b45286d057b367bb1f9283a1e32d79252 (patch) | |
tree | f4b19a3887ac0e6daada5daa22d8a8751386ef2e | |
parent | 31819f53836eabb6d2dfeca34487d9a960cb6491 (diff) |
fix PR6034, a crash on invalid where the switch stack would get
unbalanced.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94347 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Action.h | 5 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 10 | ||||
-rw-r--r-- | test/Sema/statements.c | 8 |
5 files changed, 33 insertions, 8 deletions
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index ff33f5039d..74076c8aef 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -808,6 +808,11 @@ public: return StmtEmpty(); } + /// ActOnSwitchBodyError - This is called if there is an error parsing the + /// body of the switch stmt instead of ActOnFinishSwitchStmt. + virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body) {} + virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { return StmtEmpty(); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 21e960aa81..88481e8b06 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -741,19 +741,19 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { // Read the body statement. OwningStmtResult Body(ParseStatement()); - // Pop the body scope if needed. + // Pop the scopes. InnerScope.Exit(); - - if (Body.isInvalid()) { - Body = Actions.ActOnNullStmt(Tok.getLocation()); - // FIXME: Remove the case statement list from the Switch statement. - } - SwitchScope.Exit(); - if (Cond.isInvalid() && !CondVar.get()) + if (Cond.isInvalid() && !CondVar.get()) { + Actions.ActOnSwitchBodyError(SwitchLoc, move(Switch), move(Body)); return StmtError(); + } + if (Body.isInvalid()) + // FIXME: Remove the case statement list from the Switch statement. + Body = Actions.ActOnNullStmt(Tok.getLocation()); + return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body)); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 06e9e3ae9e..ead9feb48e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1373,6 +1373,8 @@ public: SourceLocation ElseLoc, StmtArg ElseVal); virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, DeclPtrTy CondVar); + virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body); virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body); virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0c207fa6e8..4653c77c86 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -482,6 +482,16 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, return false; } +/// ActOnSwitchBodyError - This is called if there is an error parsing the +/// body of the switch stmt instead of ActOnFinishSwitchStmt. +void Sema::ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body) { + // Keep the switch stack balanced. + assert(getSwitchStack().back() == (SwitchStmt*)Switch.get() && + "switch stack missing push/pop!"); + getSwitchStack().pop_back(); +} + Action::OwningStmtResult Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { diff --git a/test/Sema/statements.c b/test/Sema/statements.c index 3cd2460e79..6da2daa01a 100644 --- a/test/Sema/statements.c +++ b/test/Sema/statements.c @@ -33,3 +33,11 @@ void *test10() { bar: return &&bar; // expected-warning {{returning address of label, which is local}} } + +// PR6034 +void test11(int bit) { + switch (bit) + switch (env->fpscr) // expected-error {{use of undeclared identifier 'env'}} + { + } +} |