aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-08-26 06:24:45 +0000
committerChris Lattner <sabre@nondot.org>2007-08-26 06:24:45 +0000
commit31e057270232c1c37602579cb6461c2704175672 (patch)
tree9961557d2fe9c65e156942a73334a37b66d9fc30
parenta7c98959345da4cbfa4988b1806e111c40d4f335 (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.cpp3
-rw-r--r--Parse/ParseStmt.cpp25
-rw-r--r--Parse/Parser.cpp9
-rw-r--r--Sema/SemaDecl.cpp23
-rw-r--r--include/clang/Parse/Scope.h33
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);