Introduce support for finding class and enum names via ordinary name lookup in C++
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49621 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 79898e4..037802c 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -15,6 +15,7 @@
#include "IdentifierResolver.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Decl.h"
+#include "clang/Parse/Scope.h"
#include <list>
#include <vector>
@@ -113,6 +114,25 @@
} else
IDI = toIdDeclInfo(Ptr);
+ // 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 (isa<TagDecl>(D)) {
+ // We are pushing the name of a tag (enum or class).
+ IdDeclInfo::ShadowedIter TopIter = IDI->shadowed_end() - 1;
+ if (S->isDeclScope(*TopIter)) {
+ // 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 stack.
+ NamedDecl *Temp = *TopIter;
+ *TopIter = D;
+ D = Temp;
+ }
+ }
+
IDI->PushShadowed(D);
}
@@ -159,16 +179,15 @@
/// Lookup - Find the non-shadowed decl that belongs to a particular
/// Decl::IdentifierNamespace.
-NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NSI) {
+NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NS) {
assert(II && "null param passed");
- Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
void *Ptr = II->getFETokenInfo<void>();
if (!Ptr) return NULL;
if (isDeclPtr(Ptr)) {
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
- return (D->getIdentifierNamespace() == NS) ? D : NULL;
+ return (D->getIdentifierNamespace() & NS) ? D : NULL;
}
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
@@ -178,7 +197,7 @@
for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
SI != IDI->shadowed_begin(); --SI) {
NamedDecl *D = *(SI-1);
- if (D->getIdentifierNamespace() == NS)
+ if (D->getIdentifierNamespace() & NS)
return D;
}
diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h
index bdaab69..abe568d 100644
--- a/lib/Sema/IdentifierResolver.h
+++ b/lib/Sema/IdentifierResolver.h
@@ -38,8 +38,8 @@
/// The decl must already be part of the decl chain.
void RemoveDecl(NamedDecl *D);
- /// Lookup - Find the non-shadowed decl that belongs to a particular
- /// Decl::IdentifierNamespace.
+ /// Lookup - Find the non-shadowed decl that belongs to one or more
+ /// of the specified Decl::IdentifierNamespaces.
NamedDecl *Lookup(const IdentifierInfo *II, unsigned NSI);
private:
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c47a027..328741e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -35,7 +35,9 @@
Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) {
Decl *IIDecl = LookupDecl(&II, Decl::IDNS_Ordinary, S, false);
- if (IIDecl && (isa<TypedefDecl>(IIDecl) || isa<ObjCInterfaceDecl>(IIDecl)))
+ if (IIDecl && (isa<TypedefDecl>(IIDecl) ||
+ isa<ObjCInterfaceDecl>(IIDecl) ||
+ isa<TagDecl>(IIDecl)))
return IIDecl;
return 0;
}
@@ -102,7 +104,9 @@
Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI,
Scope *S, bool enableLazyBuiltinCreation) {
if (II == 0) return 0;
- Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
+ unsigned NS = NSI;
+ if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
+ NS |= Decl::IDNS_Tag;
// 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
@@ -113,7 +117,7 @@
// 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
// now, injecting it into translation unit scope, and return it.
- if (NS == Decl::IDNS_Ordinary) {
+ if (NS & Decl::IDNS_Ordinary) {
if (enableLazyBuiltinCreation) {
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID())
@@ -746,7 +750,13 @@
Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S);
ScopedDecl *New;
bool InvalidDecl = false;
-
+
+ // In C++, the previous declaration we find might be a tag type
+ // (class or enum). In this case, the new declaration will hide the
+ // tag type.
+ if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
+ PrevDecl = 0;
+
QualType R = GetTypeForDeclarator(D, S);
assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 223cb56..33797c4 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -105,7 +105,7 @@
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
// TypeQuals handled by caller.
- Result = Context.getTagDeclType(cast<TagDecl>(D));
+ Result = Context.getTypeDeclType(cast<TypeDecl>(D));
break;
}
case DeclSpec::TST_typedef: {
@@ -114,6 +114,7 @@
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
+
// FIXME: Adding a TST_objcInterface clause doesn't seem ideal, so
// we have this "hack" for now...
if (ObjCInterfaceDecl *ObjCIntDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
@@ -140,7 +141,7 @@
}
}
// TypeQuals handled by caller.
- Result = Context.getTypedefType(cast<TypedefDecl>(D));
+ Result = Context.getTypeDeclType(dyn_cast<TypeDecl>(D));
break;
}
case DeclSpec::TST_typeofType: