#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
// 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) {
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();
// 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();
// 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();
}
// Start the switch scope.
- EnterScope(Scope::BreakScope);
+ EnterScope(Scope::BreakScope|Scope::DeclScope);
// Parse the condition.
ExprResult Cond = ParseSimpleParenExpression();
// 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();
}
// Start the loop scope.
- EnterScope(Scope::BreakScope | Scope::ContinueScope);
+ EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
// Parse the condition.
ExprResult Cond = ParseSimpleParenExpression();
// 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();
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();
return true;
}
- EnterScope(Scope::BreakScope | Scope::ContinueScope);
+ EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
SourceLocation LParenLoc = ConsumeParen();
ExprResult Value;
// 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();
// 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.
{
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.
}
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);
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);
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);
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();
// 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);
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)) {
/// 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
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);