diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-17 01:35:32 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-17 01:35:32 +0000 |
commit | 85b29a4c862bb9f41d9739e5dab6436fe6d44ff8 (patch) | |
tree | 2e1d242c198709694e146d89d4bf0a7ed793c084 /lib | |
parent | ce582fe2a7aad8b14b3636ad9cac0a3b8bbb219b (diff) |
Reject continue/break statements within members of local functions nested within
loop and switch statements, by teaching Scope that a function scope never has
a continue/break parent for the purposes of control flow. Remove the hack in
block and lambda expressions which worked around this by pretending that such
expressions were continue/break scopes.
Remove Scope::ControlParent, since it's unused.
In passing, teach default statements to recover properly from a missing ';', and
add a fixit for same to both default and case labels (the latter already
recovered correctly).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150776 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/Scope.cpp | 18 |
4 files changed, 25 insertions, 16 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 642fc2ac65..75510ad440 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2290,7 +2290,6 @@ ExprResult Parser::ParseBlockLiteralExpression() { // allows determining whether a variable reference inside the block is // within or outside of the block. ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope | - Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope); // Inform sema that we are starting a block. diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index d09dba2585..76cc392866 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -871,7 +871,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using // it. ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope | - Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope); Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope()); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 8af4da6a84..c256f7842d 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -596,7 +596,8 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, // Nicely diagnose the common error "switch (X) { case 4: }", which is // not valid. SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); - Diag(AfterColonLoc, diag::err_label_end_of_compound_statement); + Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) + << FixItHint::CreateInsertion(AfterColonLoc, " ;"); SubStmt = true; } @@ -638,16 +639,22 @@ StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) { ColonLoc = ExpectedLoc; } - // Diagnose the common error "switch (X) {... default: }", which is not valid. - if (Tok.is(tok::r_brace)) { + StmtResult SubStmt; + + if (Tok.isNot(tok::r_brace)) { + SubStmt = ParseStatement(); + } else { + // Diagnose the common error "switch (X) {... default: }", which is + // not valid. SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); - Diag(AfterColonLoc, diag::err_label_end_of_compound_statement); - return StmtError(); + Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) + << FixItHint::CreateInsertion(AfterColonLoc, " ;"); + SubStmt = true; } - StmtResult SubStmt(ParseStatement()); + // Broken sub-stmt shouldn't prevent forming the case statement properly. if (SubStmt.isInvalid()) - return StmtError(); + SubStmt = Actions.ActOnNullStmt(ColonLoc); return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt.get(), getCurScope()); diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp index 833a59fdce..c76f61af6c 100644 --- a/lib/Sema/Scope.cpp +++ b/lib/Sema/Scope.cpp @@ -19,23 +19,28 @@ using namespace clang; void Scope::Init(Scope *parent, unsigned flags) { AnyParent = parent; Flags = flags; - + + if (parent && !(flags & FnScope)) { + BreakParent = parent->BreakParent; + ContinueParent = parent->ContinueParent; + } else { + // Control scopes do not contain the contents of nested function scopes for + // control flow purposes. + BreakParent = ContinueParent = 0; + } + if (parent) { Depth = parent->Depth + 1; PrototypeDepth = parent->PrototypeDepth; PrototypeIndex = 0; FnParent = parent->FnParent; - BreakParent = parent->BreakParent; - ContinueParent = parent->ContinueParent; - ControlParent = parent->ControlParent; BlockParent = parent->BlockParent; TemplateParamParent = parent->TemplateParamParent; } else { Depth = 0; PrototypeDepth = 0; PrototypeIndex = 0; - FnParent = BreakParent = ContinueParent = BlockParent = 0; - ControlParent = 0; + FnParent = BlockParent = 0; TemplateParamParent = 0; } @@ -43,7 +48,6 @@ void Scope::Init(Scope *parent, unsigned flags) { if (flags & FnScope) FnParent = this; if (flags & BreakScope) BreakParent = this; if (flags & ContinueScope) ContinueParent = this; - if (flags & ControlScope) ControlParent = this; if (flags & BlockScope) BlockParent = this; if (flags & TemplateParamScope) TemplateParamParent = this; |