diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ffd70a897193..78ebbd74bb65 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -305,6 +305,44 @@ private: //===--------------------------------------------------------------------===// // Scope manipulation + /// ParseScope - Introduces a new scope for parsing. The kind of + /// scope is determined by ScopeFlags. Objects of this type should + /// be created on the stack to coincide with the position where the + /// parser enters the new scope, and this object's constructor will + /// create that new scope. Similarly, once the object is destroyed + /// the parser will exit the scope. + class ParseScope { + Parser *Self; + ParseScope(const ParseScope&); // do not implement + ParseScope& operator=(const ParseScope&); // do not implement + + public: + // ParseScope - Construct a new object to manage a scope in the + // parser Self where the new Scope is created with the flags + // ScopeFlags, but only when ManageScope is true (the default). If + // ManageScope is false, this object does nothing. + ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true) + : Self(Self) { + if (ManageScope) + Self->EnterScope(ScopeFlags); + else + this->Self = 0; + } + + // Exit - Exit the scope associated with this object now, rather + // than waiting until the object is destroyed. + void Exit() { + if (Self) { + Self->ExitScope(); + Self = 0; + } + } + + ~ParseScope() { + Exit(); + } + }; + /// EnterScope - Start a new scope. void EnterScope(unsigned ScopeFlags); diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 2f5014ba5040..824847af63b0 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -65,7 +65,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { /// (non-nested) C++ class. Now go over the stack of lexed methods that were /// collected during its parsing and parse them all. void Parser::ParseLexedMethodDefs() { - while (!getCurTopClassStack().empty()) { + for (; !getCurTopClassStack().empty(); getCurTopClassStack().pop()) { LexedMethod &LM = getCurTopClassStack().top(); assert(!LM.Toks.empty() && "Empty body!"); @@ -81,15 +81,13 @@ void Parser::ParseLexedMethodDefs() { // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. - EnterScope(Scope::FnScope|Scope::DeclScope); + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); Actions.ActOnStartOfFunctionDef(CurScope, LM.D); if (Tok.is(tok::colon)) ParseConstructorInitializer(LM.D); ParseFunctionStatementBody(LM.D, Tok.getLocation(), Tok.getLocation()); - - getCurTopClassStack().pop(); } } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index e7f4fc92eada..572ca613e018 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1728,7 +1728,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - EnterScope(Scope::FnScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FnScope|Scope::DeclScope); bool IsVariadic = false; while (1) { @@ -1818,7 +1818,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, } // Leave prototype scope. - ExitScope(); + PrototypeScope.Exit(); // If we have the closing ')', eat it. MatchRHSPunctuation(tok::r_paren, LParenLoc); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index c3b94bc6289f..edcbfad6f371 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -67,7 +67,7 @@ Parser::DeclTy *Parser::ParseNamespace(unsigned Context) { SourceLocation LBrace = ConsumeBrace(); // Enter a scope for the namespace. - EnterScope(Scope::DeclScope); + ParseScope NamespaceScope(this, Scope::DeclScope); DeclTy *NamespcDecl = Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace); @@ -76,7 +76,7 @@ Parser::DeclTy *Parser::ParseNamespace(unsigned Context) { ParseExternalDeclaration(); // Leave the namespace scope. - ExitScope(); + NamespaceScope.Exit(); SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace); @@ -590,7 +590,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } // Enter a scope for the class. - EnterScope(Scope::CXXClassScope|Scope::DeclScope); + ParseScope ClassScope(this, Scope::CXXClassScope|Scope::DeclScope); Actions.ActOnStartCXXClassDef(CurScope, TagDecl, LBraceLoc); @@ -659,7 +659,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } // Leave the class scope. - ExitScope(); + ClassScope.Exit(); Actions.ActOnFinishCXXClassDef(TagDecl); } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 4cf7c1e4f726..9babd10ed076 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1159,8 +1159,8 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() { // argument decls, decls within the compound expression, etc. This also // allows determining whether a variable reference inside the block is // within or outside of the block. - EnterScope(Scope::BlockScope|Scope::FnScope|Scope::BreakScope| - Scope::ContinueScope|Scope::DeclScope); + ParseScope BlockScope(this, Scope::BlockScope|Scope::FnScope|Scope::BreakScope| + Scope::ContinueScope|Scope::DeclScope); // Inform sema that we are starting a block. Actions.ActOnBlockStart(CaretLoc, CurScope); @@ -1179,7 +1179,6 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() { // If there was an error parsing the arguments, they may have tried to use // ^(x+y) which requires an argument list. Just skip the whole block // literal. - ExitScope(); return true; } } else { @@ -1200,7 +1199,6 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() { Actions.ActOnBlockError(CaretLoc, CurScope); } } - ExitScope(); return Result.result(); } diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index c6bc386d6b23..8f6e777ba78d 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1214,11 +1214,11 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { } // Enter a scope to hold everything within the compound stmt. Compound // statements can always hold declarations. - EnterScope(Scope::DeclScope); + ParseScope BodyScope(this, Scope::DeclScope); OwningStmtResult SynchBody(Actions, ParseCompoundStatementBody()); - ExitScope(); + BodyScope.Exit(); if (SynchBody.isInvalid()) SynchBody = Actions.ActOnNullStmt(Tok.getLocation()); return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.release(), @@ -1246,9 +1246,9 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { } OwningStmtResult CatchStmts(Actions); OwningStmtResult FinallyStmt(Actions); - EnterScope(Scope::DeclScope); + ParseScope TryScope(this, Scope::DeclScope); OwningStmtResult TryBody(Actions, ParseCompoundStatementBody()); - ExitScope(); + TryScope.Exit(); if (TryBody.isInvalid()) TryBody = Actions.ActOnNullStmt(Tok.getLocation()); @@ -1267,7 +1267,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ConsumeToken(); // consume catch if (Tok.is(tok::l_paren)) { ConsumeParen(); - EnterScope(Scope::DeclScope); + ParseScope CatchScope(this, Scope::DeclScope); if (Tok.isNot(tok::ellipsis)) { DeclSpec DS; ParseDeclarationSpecifiers(DS); @@ -1297,7 +1297,6 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc, FirstPart.release(), CatchBody.release(), CatchStmts.release()); - ExitScope(); } else { Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after) << "@catch clause"; @@ -1307,8 +1306,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { } else { assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?"); ConsumeToken(); // consume finally - EnterScope(Scope::DeclScope); - + ParseScope FinallyScope(this, Scope::DeclScope); OwningStmtResult FinallyBody(Actions, true); if (Tok.is(tok::l_brace)) @@ -1320,7 +1318,6 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, FinallyBody.release()); catch_or_finally_seen = true; - ExitScope(); break; } } @@ -1355,7 +1352,7 @@ Parser::DeclTy *Parser::ParseObjCMethodDefinition() { SourceLocation BraceLoc = Tok.getLocation(); // Enter a scope for the method body. - EnterScope(Scope::FnScope|Scope::DeclScope); + ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); // Tell the actions module that we have entered a method definition with the // specified Declarator for the method. @@ -1368,7 +1365,7 @@ Parser::DeclTy *Parser::ParseObjCMethodDefinition() { FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, 0, 0, false); // Leave the function body scope. - ExitScope(); + BodyScope.Exit(); // TODO: Pass argument information. Actions.ActOnFinishFunctionBody(MDecl, FnBody.release()); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f244e4ba98ca..8b5277bc3653 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -333,12 +333,10 @@ Parser::StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { // Enter a scope to hold everything within the compound stmt. Compound // statements can always hold declarations. - EnterScope(Scope::DeclScope); + ParseScope CompoundScope(this, Scope::DeclScope); // Parse the statements in the body. OwningStmtResult Body(Actions, ParseCompoundStatementBody(isStmtExpr)); - - ExitScope(); return Body.result(); } @@ -446,8 +444,7 @@ Parser::StmtResult Parser::ParseIfStatement() { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // - if (C99orCXX) - EnterScope(Scope::DeclScope | Scope::ControlScope); + ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. OwningExprResult CondExp(Actions); @@ -461,8 +458,6 @@ Parser::StmtResult Parser::ParseIfStatement() { if (CondExp.isInvalid()) { SkipUntil(tok::semi); - if (C99orCXX) - ExitScope(); return true; } @@ -484,15 +479,15 @@ Parser::StmtResult Parser::ParseIfStatement() { // would have to notify ParseStatement not to create a new scope. It's // simpler to let it create a new scope. // - bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace); - if (NeedsInnerScope) EnterScope(Scope::DeclScope); + ParseScope InnerScope(this, Scope::DeclScope, + C99orCXX && Tok.isNot(tok::l_brace)); // Read the 'then' stmt. SourceLocation ThenStmtLoc = Tok.getLocation(); OwningStmtResult ThenStmt(Actions, ParseStatement()); // Pop the 'if' scope if needed. - if (NeedsInnerScope) ExitScope(); + InnerScope.Exit(); // If it has an else, parse it. SourceLocation ElseLoc; @@ -511,18 +506,17 @@ Parser::StmtResult Parser::ParseIfStatement() { // The substatement in a selection-statement (each substatement, in the else // form of the if statement) implicitly defines a local scope. // - NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace); - if (NeedsInnerScope) EnterScope(Scope::DeclScope); + ParseScope InnerScope(this, Scope::DeclScope, + C99orCXX && Tok.isNot(tok::l_brace)); ElseStmtLoc = Tok.getLocation(); ElseStmt = ParseStatement(); // Pop the 'else' scope if needed. - if (NeedsInnerScope) ExitScope(); + InnerScope.Exit(); } - if (C99orCXX) - ExitScope(); + IfScope.Exit(); // If the then or else stmt is invalid and the other is valid (and present), // make turn the invalid one into a null stmt to avoid dropping the other @@ -572,10 +566,10 @@ Parser::StmtResult Parser::ParseSwitchStatement() { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // - if (C99orCXX) - EnterScope(Scope::BreakScope | Scope::DeclScope | Scope::ControlScope); - else - EnterScope(Scope::BreakScope); + unsigned ScopeFlags + = C99orCXX? Scope::BreakScope | Scope::DeclScope | Scope::ControlScope + : Scope::BreakScope; + ParseScope SwitchScope(this, ScopeFlags); // Parse the condition. OwningExprResult Cond(Actions); @@ -587,10 +581,8 @@ Parser::StmtResult Parser::ParseSwitchStatement() { Cond = ParseSimpleParenExpression(); } - if (Cond.isInvalid()) { - ExitScope(); + if (Cond.isInvalid()) return true; - } OwningStmtResult Switch(Actions, Actions.ActOnStartOfSwitchStmt(Cond.release())); @@ -606,21 +598,21 @@ Parser::StmtResult Parser::ParseSwitchStatement() { // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace); - if (NeedsInnerScope) EnterScope(Scope::DeclScope); + ParseScope InnerScope(this, Scope::DeclScope, + C99orCXX && Tok.isNot(tok::l_brace)); // Read the body statement. OwningStmtResult Body(Actions, ParseStatement()); // Pop the body scope if needed. - if (NeedsInnerScope) ExitScope(); + InnerScope.Exit(); if (Body.isInvalid()) { Body = Actions.ActOnNullStmt(Tok.getLocation()); // FIXME: Remove the case statement list from the Switch statement. } - - ExitScope(); + + SwitchScope.Exit(); return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.release(), Body.release()); @@ -655,11 +647,13 @@ Parser::StmtResult Parser::ParseWhileStatement() { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // + unsigned ScopeFlags; if (C99orCXX) - EnterScope(Scope::BreakScope | Scope::ContinueScope | - Scope::DeclScope | Scope::ControlScope); + ScopeFlags = Scope::BreakScope | Scope::ContinueScope | + Scope::DeclScope | Scope::ControlScope; else - EnterScope(Scope::BreakScope | Scope::ContinueScope); + ScopeFlags = Scope::BreakScope | Scope::ContinueScope; + ParseScope WhileScope(this, ScopeFlags); // Parse the condition. OwningExprResult Cond(Actions); @@ -682,16 +676,15 @@ Parser::StmtResult Parser::ParseWhileStatement() { // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace); - if (NeedsInnerScope) EnterScope(Scope::DeclScope); + ParseScope InnerScope(this, Scope::DeclScope, + C99orCXX && Tok.isNot(tok::l_brace)); // Read the body statement. OwningStmtResult Body(Actions, ParseStatement()); // Pop the body scope if needed. - if (NeedsInnerScope) ExitScope(); - - ExitScope(); + InnerScope.Exit(); + WhileScope.Exit(); if (Cond.isInvalid() || Body.isInvalid()) return true; @@ -708,10 +701,13 @@ Parser::StmtResult Parser::ParseDoStatement() { // C99 6.8.5p5 - In C99, the do statement is a block. This is not // the case for C90. Start the loop scope. + unsigned ScopeFlags; if (getLang().C99) - EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope); + ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope; else - EnterScope(Scope::BreakScope | Scope::ContinueScope); + ScopeFlags = Scope::BreakScope | Scope::ContinueScope; + + ParseScope DoScope(this, ScopeFlags); // 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 @@ -721,18 +717,17 @@ Parser::StmtResult Parser::ParseDoStatement() { // The substatement in an iteration-statement implicitly defines a local scope // which is entered and exited each time through the loop. // - bool NeedsInnerScope = - (getLang().C99 || getLang().CPlusPlus) && Tok.isNot(tok::l_brace); - if (NeedsInnerScope) EnterScope(Scope::DeclScope); + ParseScope InnerScope(this, Scope::DeclScope, + (getLang().C99 || getLang().CPlusPlus) && + Tok.isNot(tok::l_brace)); // Read the body statement. OwningStmtResult Body(Actions, ParseStatement()); // Pop the body scope if needed. - if (NeedsInnerScope) ExitScope(); + InnerScope.Exit(); if (Tok.isNot(tok::kw_while)) { - ExitScope(); if (!Body.isInvalid()) { Diag(Tok, diag::err_expected_while); Diag(DoLoc, diag::note_matching) << "do"; @@ -743,7 +738,6 @@ Parser::StmtResult Parser::ParseDoStatement() { SourceLocation WhileLoc = ConsumeToken(); if (Tok.isNot(tok::l_paren)) { - ExitScope(); Diag(Tok, diag::err_expected_lparen_after) << "do/while"; SkipUntil(tok::semi, false, true); return true; @@ -751,8 +745,7 @@ Parser::StmtResult Parser::ParseDoStatement() { // Parse the condition. OwningExprResult Cond(Actions, ParseSimpleParenExpression()); - - ExitScope(); + DoScope.Exit(); if (Cond.isInvalid() || Body.isInvalid()) return true; @@ -799,11 +792,14 @@ Parser::StmtResult Parser::ParseForStatement() { // Names declared in the for-init-statement are in the same declarative-region // as those declared in the condition. // + unsigned ScopeFlags; if (C99orCXX) - EnterScope(Scope::BreakScope | Scope::ContinueScope | - Scope::DeclScope | Scope::ControlScope); + ScopeFlags = Scope::BreakScope | Scope::ContinueScope | + Scope::DeclScope | Scope::ControlScope; else - EnterScope(Scope::BreakScope | Scope::ContinueScope); + ScopeFlags = Scope::BreakScope | Scope::ContinueScope; + + ParseScope ForScope(this, ScopeFlags); SourceLocation LParenLoc = ConsumeParen(); OwningExprResult Value(Actions); @@ -891,17 +887,17 @@ Parser::StmtResult Parser::ParseForStatement() { // See comments in ParseIfStatement for why we create a scope for // for-init-statement/condition and a new scope for substatement in C++. // - bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace); - if (NeedsInnerScope) EnterScope(Scope::DeclScope); + ParseScope InnerScope(this, Scope::DeclScope, + C99orCXX && Tok.isNot(tok::l_brace)); // Read the body statement. OwningStmtResult Body(Actions, ParseStatement()); // Pop the body scope if needed. - if (NeedsInnerScope) ExitScope(); + InnerScope.Exit(); // Leave the for-scope. - ExitScope(); + ForScope.Exit(); if (Body.isInvalid()) return true; @@ -1214,8 +1210,5 @@ Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl, if (FnBody.isInvalid()) FnBody = Actions.ActOnCompoundStmt(L, R, 0, 0, false); - // Leave the function body scope. - ExitScope(); - return Actions.ActOnFinishFunctionBody(Decl, FnBody.release()); } diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index c1120d5ce43e..d21dc4aa6d6f 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -41,7 +41,7 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { SourceLocation TemplateLoc = ConsumeToken(); // Enter template-parameter scope. - EnterScope(Scope::TemplateParamScope); + ParseScope TemplateParmScope(this, Scope::TemplateParamScope); // Try to parse the template parameters, and the declaration if // successful. @@ -49,9 +49,6 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { if(ParseTemplateParameters(0)) TemplateDecl = ParseDeclarationOrFunctionDefinition(); - // Leave template-parameter scope. - ExitScope(); - return TemplateDecl; } diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index d040efd7acd2..3d72b60b8673 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -287,7 +287,7 @@ bool Parser::ParseTopLevelDecl(DeclTy*& Result) { /// external-declaration /// translation-unit external-declaration void Parser::ParseTranslationUnit() { - Initialize(); // pushes a scope. + Initialize(); DeclTy *Res; while (!ParseTopLevelDecl(Res)) @@ -526,7 +526,7 @@ Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) { } // Enter a scope for the function body. - EnterScope(Scope::FnScope|Scope::DeclScope); + ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. @@ -549,7 +549,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - EnterScope(Scope::FnScope|Scope::DeclScope); + ParseScope PrototypeScope(this, Scope::FnScope|Scope::DeclScope); // Read all the argument declarations. while (isDeclarationSpecifier()) { @@ -653,9 +653,6 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { } } - // Leave prototype scope. - ExitScope(); - // The actions module must verify that all arguments were declared. }