Use a scoped object to manage entry/exit from a parser scope rather than explicitly calling EnterScope/ExitScope

llvm-svn: 60830
This commit is contained in:
Douglas Gregor 2008-12-10 06:34:36 +00:00
parent 4637c3c698
commit 7307d6ca96
9 changed files with 108 additions and 90 deletions

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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());

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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.
}