diff options
author | Chris Lattner <sabre@nondot.org> | 2007-08-26 06:24:45 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-08-26 06:24:45 +0000 |
commit | 31e057270232c1c37602579cb6461c2704175672 (patch) | |
tree | 9961557d2fe9c65e156942a73334a37b66d9fc30 | |
parent | a7c98959345da4cbfa4988b1806e111c40d4f335 (diff) |
Break the assumption that any sort of scope (e.g. a loop scope) can
hold declarations. Instead, introduce a new "DeclScope" scope type that
holds them explicitly. For now, all scopes have this bit, but in the
future we can use them to fix some issues Neil noticed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41431 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Parse/ParseDecl.cpp | 3 | ||||
-rw-r--r-- | Parse/ParseStmt.cpp | 25 | ||||
-rw-r--r-- | Parse/Parser.cpp | 9 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 23 | ||||
-rw-r--r-- | include/clang/Parse/Scope.h | 33 |
5 files changed, 65 insertions, 28 deletions
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp index d1dde24241..6a617128ad 100644 --- a/Parse/ParseDecl.cpp +++ b/Parse/ParseDecl.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Scope.h" #include "llvm/ADT/SmallSet.h" using namespace clang; @@ -1268,7 +1269,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // Enter function-declaration scope, limiting any declarators for struct // tags to the function prototype scope. // FIXME: is this needed? - EnterScope(0); + EnterScope(Scope::DeclScope); IsVariadic = false; while (1) { diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp index e0d527ebf6..832eef213e 100644 --- a/Parse/ParseStmt.cpp +++ b/Parse/ParseStmt.cpp @@ -372,8 +372,9 @@ Parser::StmtResult Parser::ParseDefaultStatement() { Parser::StmtResult Parser::ParseCompoundStatement() { assert(Tok.getKind() == tok::l_brace && "Not a compount stmt!"); - // Enter a scope to hold everything within the compound stmt. - EnterScope(0); + // Enter a scope to hold everything within the compound stmt. Compound + // statements can always hold declarations. + EnterScope(Scope::DeclScope); // Parse the statements in the body. StmtResult Body = ParseCompoundStatementBody(); @@ -437,7 +438,7 @@ Parser::StmtResult Parser::ParseIfStatement() { // 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. bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace; - if (NeedsInnerScope) EnterScope(0); + if (NeedsInnerScope) EnterScope(Scope::DeclScope); // Read the if condition. StmtResult CondStmt = ParseStatement(); @@ -460,7 +461,7 @@ Parser::StmtResult Parser::ParseIfStatement() { // this if the body isn't a compound statement to avoid push/pop in common // cases. NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace; - if (NeedsInnerScope) EnterScope(0); + if (NeedsInnerScope) EnterScope(Scope::DeclScope); ElseStmt = ParseStatement(); @@ -489,7 +490,7 @@ Parser::StmtResult Parser::ParseSwitchStatement() { } // Start the switch scope. - EnterScope(Scope::BreakScope); + EnterScope(Scope::BreakScope|Scope::DeclScope); // Parse the condition. ExprResult Cond = ParseSimpleParenExpression(); @@ -505,7 +506,7 @@ Parser::StmtResult Parser::ParseSwitchStatement() { // 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. bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace; - if (NeedsInnerScope) EnterScope(0); + if (NeedsInnerScope) EnterScope(Scope::DeclScope); // Read the body statement. StmtResult Body = ParseStatement(); @@ -538,7 +539,7 @@ Parser::StmtResult Parser::ParseWhileStatement() { } // Start the loop scope. - EnterScope(Scope::BreakScope | Scope::ContinueScope); + EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope); // Parse the condition. ExprResult Cond = ParseSimpleParenExpression(); @@ -547,7 +548,7 @@ Parser::StmtResult Parser::ParseWhileStatement() { // 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. bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace; - if (NeedsInnerScope) EnterScope(0); + if (NeedsInnerScope) EnterScope(Scope::DeclScope); // Read the body statement. StmtResult Body = ParseStatement(); @@ -571,13 +572,13 @@ Parser::StmtResult Parser::ParseDoStatement() { SourceLocation DoLoc = ConsumeToken(); // eat the 'do'. // Start the loop scope. - EnterScope(Scope::BreakScope | Scope::ContinueScope); + EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope); // 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. bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace; - if (NeedsInnerScope) EnterScope(0); + if (NeedsInnerScope) EnterScope(Scope::DeclScope); // Read the body statement. StmtResult Body = ParseStatement(); @@ -625,7 +626,7 @@ Parser::StmtResult Parser::ParseForStatement() { return true; } - EnterScope(Scope::BreakScope | Scope::ContinueScope); + EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope); SourceLocation LParenLoc = ConsumeParen(); ExprResult Value; @@ -701,7 +702,7 @@ Parser::StmtResult Parser::ParseForStatement() { // 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. bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace; - if (NeedsInnerScope) EnterScope(0); + if (NeedsInnerScope) EnterScope(Scope::DeclScope); // Read the body statement. StmtResult Body = ParseStatement(); diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp index d9d79613d2..d034dc26bc 100644 --- a/Parse/Parser.cpp +++ b/Parse/Parser.cpp @@ -221,11 +221,10 @@ void Parser::Initialize() { // Prime the lexer look-ahead. ConsumeToken(); - // Create the global scope, install it as the current scope. + // Create the translation unit scope. Install it as the current scope. assert(CurScope == 0 && "A scope is already active?"); - EnterScope(0); - - + EnterScope(Scope::DeclScope); + // Install builtin types. // TODO: Move this someplace more useful. { @@ -435,7 +434,7 @@ Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) { ParseKNRParamDeclarations(D); // Enter a scope for the function body. - EnterScope(Scope::FnScope); + EnterScope(Scope::FnScope|Scope::DeclScope); // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index faf016b944..543d2af454 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -78,6 +78,9 @@ Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const { } void Sema::PopScope(SourceLocation Loc, Scope *S) { + if (S->decl_empty()) return; + assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!"); + for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); I != E; ++I) { Decl *D = static_cast<Decl*>(*I); @@ -159,6 +162,8 @@ Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) { FunctionDecl::Extern, false, 0); // Find translation-unit scope to insert this function into. + if (Scope *FnS = S->getFnParent()) + S = FnS->getParent(); // Skip all scopes in a function at once. while (S->getParent()) S = S->getParent(); S->AddDecl(New); @@ -286,6 +291,11 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, return 0; } + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0) + S = S->getParent(); + // See if this is a redefinition of a variable in the same scope. Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary, D.getIdentifierLoc(), S); @@ -616,6 +626,8 @@ Decl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, D.SetIdentifier(&II, Loc); // Find translation-unit scope to insert this function into. + if (Scope *FnS = S->getFnParent()) + S = FnS->getParent(); // Skip all scopes in a function at once. while (S->getParent()) S = S->getParent(); @@ -724,6 +736,12 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK, // If this has an identifier, add it to the scope stack. if (Name) { + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0) + S = S->getParent(); + + // Add it to the decl chain. New->setNext(Name->getFETokenInfo<Decl>()); Name->setFETokenInfo(New); S->AddDecl(New); @@ -896,6 +914,11 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl, cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst)); Expr *Val = static_cast<Expr*>(val); + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0) + S = S->getParent(); + // Verify that there isn't already something declared with this name in this // scope. if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, IdLoc, S)) { diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h index b7a47c55ed..a31eb35abd 100644 --- a/include/clang/Parse/Scope.h +++ b/include/clang/Parse/Scope.h @@ -38,7 +38,11 @@ public: /// ContinueScope - This is a while,do,for, which can have continue /// stmt embedded into it. - ContinueScope = 0x04 + ContinueScope = 0x04, + + /// DeclScope - This is a scope that can contain a declaration. Some scopes + /// just contain loop constructs but don't contain decls. + DeclScope = 0x08 }; private: /// The parent scope for this scope. This is null for the translation-unit @@ -75,27 +79,36 @@ public: Scope(Scope *Parent, unsigned ScopeFlags) { Init(Parent, ScopeFlags); } - + + /// getFlags - Return the flags for this scope. + /// + unsigned getFlags() const { return Flags; } + /// getParent - Return the scope that this is nested in. /// - Scope *getParent() const { return AnyParent; } + const Scope *getParent() const { return AnyParent; } + Scope *getParent() { return AnyParent; } + + /// getFnParent - Return the closest scope that is a function body. + /// + const Scope *getFnParent() const { return FnParent; } + Scope *getFnParent() { return FnParent; } /// getContinueParent - Return the closest scope that a continue statement /// would be affected by. - Scope *getContinueParent() const { - return ContinueParent; - } + const Scope *getContinueParent() const { return ContinueParent; } + Scope *getContinueParent() { return ContinueParent; } /// getBreakParent - Return the closest scope that a break statement /// would be affected by. - Scope *getBreakParent() const { - return BreakParent; - } - + const Scope *getBreakParent() const { return BreakParent; } + Scope *getBreakParent() { return BreakParent; } + typedef DeclSetTy::iterator decl_iterator; decl_iterator decl_begin() const { return DeclsInScope.begin(); } decl_iterator decl_end() const { return DeclsInScope.end(); } + bool decl_empty() const { return DeclsInScope.empty(); } void AddDecl(Action::DeclTy *D) { DeclsInScope.insert(D); |