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: