diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2013-10-21 09:34:44 +0000 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2013-10-21 09:34:44 +0000 |
commit | 6652921d5aba1e5c158212d288d2b7d6e53386c8 (patch) | |
tree | fb23cb362c0e8c0fb7df46afa05ff11d9510a5e3 /clang/lib/Parse/ParseStmt.cpp | |
parent | b773785a593592020a449dfcfe65bd4e4f93fe71 (diff) | |
download | bcm5719-llvm-6652921d5aba1e5c158212d288d2b7d6e53386c8.tar.gz bcm5719-llvm-6652921d5aba1e5c158212d288d2b7d6e53386c8.zip |
Fix to PR8880 (clang dies processing a for loop).
Due to statement expressions supported as GCC extension, it is possible
to put 'break' or 'continue' into a loop/switch statement but outside its
body, for example:
for ( ; ({ if (first) { first = 0; continue; } 0; }); )
Such usage must be diagnosed as an error, GCC rejects it. To recognize
this and similar patterns the flags BreakScope and ContinueScope are
temporarily turned off while parsing condition expression.
Differential Revision: http://llvm-reviews.chandlerc.com/D1762
llvm-svn: 193073
Diffstat (limited to 'clang/lib/Parse/ParseStmt.cpp')
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f57ff97ceb5..395fb394dc4 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1135,6 +1135,9 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { ScopeFlags |= Scope::DeclScope | Scope::ControlScope; ParseScope SwitchScope(this, ScopeFlags); + // Temporarily disable 'break' while parsing condition. + SwitchScope.ClearFlags(Scope::BreakScope); + // Parse the condition. ExprResult Cond; Decl *CondVar = 0; @@ -1157,6 +1160,9 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { return Switch; } + // Enable 'break' in the body of switch statement. + SwitchScope.SetFlags(Scope::BreakScope); + // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1227,6 +1233,9 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { ScopeFlags = Scope::BreakScope | Scope::ContinueScope; ParseScope WhileScope(this, ScopeFlags); + // Disable 'break' and 'continue' while parsing condition. + WhileScope.ClearFlags(Scope::BreakScope | Scope::ContinueScope); + // Parse the condition. ExprResult Cond; Decl *CondVar = 0; @@ -1235,6 +1244,9 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); + // Allow 'break' and 'continue' in the body of the statement. + WhileScope.SetFlags(Scope::BreakScope | Scope::ContinueScope); + // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1314,6 +1326,9 @@ StmtResult Parser::ParseDoStatement() { return StmtError(); } + // Do not allow 'break' and 'continue' in 'while' condition expression. + DoScope.ClearFlags(Scope::BreakScope | Scope::ContinueScope); + // Parse the parenthesized expression. BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -1391,6 +1406,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); + // Until loop body starts, statements 'break' and 'continue' cannot + // be used. + ForScope.ClearFlags(Scope::BreakScope | Scope::ContinueScope); + ExprResult Value; bool ForEach = false, ForRange = false; @@ -1566,6 +1585,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { T.getCloseLocation()); } + // When parsing body of 'for' statement, 'break' and 'continue' may be used. + ForScope.SetFlags(Scope::BreakScope | Scope::ContinueScope); + // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. |