aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-05-09 23:39:43 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-05-09 23:39:43 +0000
commit00bc645d154f8f30bfbfb2fe508caf087793157c (patch)
tree13eebea1acbdbd9993013e3299aa9eeebf64b24e /lib/Sema/SemaDecl.cpp
parent0951052064e1c29c6ac9b873764fa6bfc2685817 (diff)
-Implement proper name lookup for namespaces.
-identifierResolver exposes an iterator interface to get all decls through the scope chain. -The semantic staff (checking IdentifierNamespace and Doug's checking for shadowed tags were moved out of IdentifierResolver and back into Sema. IdentifierResolver just gives an iterator for all reachable decls of an identifier. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50923 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp72
1 files changed, 51 insertions, 21 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index afe877fb97..933a361812 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -59,13 +59,40 @@ void Sema::PopDeclContext() {
/// Add this decl to the scope shadowed decl chains.
void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
- IdResolver.AddDecl(D, S);
S->AddDecl(D);
+
+ // C++ [basic.scope]p4:
+ // -- exactly one declaration shall declare a class name or
+ // enumeration name that is not a typedef name and the other
+ // declarations shall all refer to the same object or
+ // enumerator, or all refer to functions and function templates;
+ // in this case the class name or enumeration name is hidden.
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ // We are pushing the name of a tag (enum or class).
+ IdentifierResolver::ctx_iterator
+ CIT = IdResolver.ctx_begin(TD->getIdentifier(), TD->getDeclContext());
+ if (CIT != IdResolver.ctx_end(TD->getIdentifier()) &&
+ IdResolver.isDeclInScope(*CIT, TD->getDeclContext(), S)) {
+ // There is already a declaration with the same name in the same
+ // scope. It must be found before we find the new declaration,
+ // so swap the order on the shadowed declaration chain.
+
+ IdResolver.AddShadowedDecl(TD, *CIT);
+ return;
+ }
+ }
+
+ IdResolver.AddDecl(D);
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!");
+
+ // We only want to remove the decls from the identifier decl chains for local
+ // scopes, when inside a function/method.
+ if (S->getFnParent() == 0)
+ return;
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
@@ -115,8 +142,10 @@ Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI,
// Scan up the scope chain looking for a decl that matches this identifier
// that is in the appropriate namespace. This search should not take long, as
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
- NamedDecl *ND = IdResolver.Lookup(II, NS);
- if (ND) return ND;
+ for (IdentifierResolver::iterator
+ I = IdResolver.begin(II, CurContext), E = IdResolver.end(II); I != E; ++I)
+ if ((*I)->getIdentifierNamespace() & NS)
+ return *I;
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
@@ -184,11 +213,7 @@ ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
// TUScope is the translation-unit scope to insert this function into.
- TUScope->AddDecl(New);
-
- // Add this decl to the end of the identifier info.
- IdResolver.AddGlobalDecl(New);
-
+ PushOnScopeChains(New, TUScope);
return New;
}
@@ -797,12 +822,12 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
D.getAttributes());
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- if (PrevDecl && S->isDeclScope(PrevDecl)) {
+ if (PrevDecl && IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
if (NewTD == 0) return 0;
}
New = NewTD;
- if (S->getParent() == 0) {
+ if (S->getFnParent() == 0) {
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
@@ -873,7 +898,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
// Merge the decl with the existing one if appropriate. Since C functions
// are in a flat namespace, make sure we consider decls in outer scopes.
- if (PrevDecl) {
+ if (PrevDecl &&
+ (!getLangOptions().CPlusPlus ||
+ IdResolver.isDeclInScope(PrevDecl, CurContext, S)) ) {
bool Redeclaration = false;
NewFD = MergeFunctionDecl(NewFD, PrevDecl, Redeclaration);
if (NewFD == 0) return 0;
@@ -914,7 +941,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
}
- if (S->getParent() == 0) {
+ if (S->getFnParent() == 0) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
@@ -942,7 +969,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
}
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- if (PrevDecl && S->isDeclScope(PrevDecl)) {
+ if (PrevDecl && IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
NewVD = MergeVarDecl(NewVD, PrevDecl);
if (NewVD == 0) return 0;
}
@@ -1221,12 +1248,14 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
// See if this is a redefinition.
Decl *PrevDcl = LookupDecl(D.getIdentifier(), Decl::IDNS_Ordinary,
GlobalScope);
- if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(PrevDcl)) {
- const FunctionDecl *Definition;
- if (FD->getBody(Definition)) {
- Diag(D.getIdentifierLoc(), diag::err_redefinition,
- D.getIdentifier()->getName());
- Diag(Definition->getLocation(), diag::err_previous_definition);
+ if (PrevDcl && IdResolver.isDeclInScope(PrevDcl, CurContext)) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PrevDcl)) {
+ const FunctionDecl *Definition;
+ if (FD->getBody(Definition)) {
+ Diag(D.getIdentifierLoc(), diag::err_redefinition,
+ D.getIdentifier()->getName());
+ Diag(Definition->getLocation(), diag::err_previous_definition);
+ }
}
}
Decl *decl = static_cast<Decl*>(ActOnDeclarator(GlobalScope, D, 0));
@@ -1375,7 +1404,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
- if (TK == TK_Reference || S->isDeclScope(PrevDecl)) {
+ if (TK == TK_Reference ||
+ IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
// Make sure that this wasn't declared as an enum and now used as a struct
// or something similar.
if (PrevDecl->getKind() != Kind) {
@@ -1733,7 +1763,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
// Verify that there isn't already something declared with this name in this
// scope.
if (Decl *PrevDecl = LookupDecl(Id, Decl::IDNS_Ordinary, S)) {
- if (S->isDeclScope(PrevDecl)) {
+ if (IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());
else