Recommit my change to how C++ does elaborated type lookups, now with
two bugfixes which fix selfhost and (hopefully) the nightly tests.

llvm-svn: 102198
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index e71f8c8..35bb697 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -415,6 +415,9 @@
 
     return false;
   }
+
+  if (Filter == &ResultBuilder::IsNestedNameSpecifier)
+    AsNestedNameSpecifier = true;
   
   // ... then it must be interesting!
   return true;
@@ -504,7 +507,7 @@
     }
     for (; I != IEnd; ++I) {
       // A tag declaration does not hide a non-tag declaration.
-      if (I->first->getIdentifierNamespace() == Decl::IDNS_Tag &&
+      if (I->first->hasTagIdentifierNamespace() &&
           (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
                    Decl::IDNS_ObjCProtocol)))
         continue;
@@ -629,7 +632,7 @@
 bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
   unsigned IDNS = Decl::IDNS_Ordinary;
   if (SemaRef.getLangOptions().CPlusPlus)
-    IDNS |= Decl::IDNS_Tag;
+    IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
   else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
     return true;
 
@@ -641,7 +644,7 @@
 bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
   unsigned IDNS = Decl::IDNS_Ordinary;
   if (SemaRef.getLangOptions().CPlusPlus)
-    IDNS |= Decl::IDNS_Tag;
+    IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
   
   return (ND->getIdentifierNamespace() & IDNS) && 
     !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND);
@@ -2094,10 +2097,16 @@
     return;
   }
   
-  ResultBuilder Results(*this, Filter);
-  Results.allowNestedNameSpecifiers();
+  ResultBuilder Results(*this);
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
+
+  // First pass: look for tags.
+  Results.setFilter(Filter);
   LookupVisibleDecls(S, LookupTagName, Consumer);
+
+  // Second pass: look for nested name specifiers.
+  Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+  LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
   
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c9001f1..cc57bdd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5000,7 +5000,8 @@
       SearchDC = SearchDC->getEnclosingNamespaceContext();
     }
 
-    // In C++, look for a shadow friend decl.
+    // In C++, we need to do a redeclaration lookup to properly
+    // diagnose some problems.
     if (getLangOptions().CPlusPlus) {
       Previous.setRedeclarationKind(ForRedeclaration);
       LookupQualifiedName(Previous, SearchDC);
@@ -5009,6 +5010,30 @@
 
   if (!Previous.empty()) {
     NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+
+    // It's okay to have a tag decl in the same scope as a typedef
+    // which hides a tag decl in the same scope.  Finding this
+    // insanity with a redeclaration lookup can only actually happen
+    // in C++.
+    //
+    // This is also okay for elaborated-type-specifiers, which is
+    // technically forbidden by the current standard but which is
+    // okay according to the likely resolution of an open issue;
+    // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
+    if (getLangOptions().CPlusPlus) {
+      if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) {
+        if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+          TagDecl *Tag = TT->getDecl();
+          if (Tag->getDeclName() == Name &&
+              Tag->getDeclContext()->Equals(TD->getDeclContext())) {
+            PrevDecl = Tag;
+            Previous.clear();
+            Previous.addDecl(Tag);
+          }
+        }
+      }
+    }
+
     if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
       // 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
@@ -5100,23 +5125,61 @@
       // If we get here, we're going to create a new Decl. If PrevDecl
       // is non-NULL, it's a definition of the tag declared by
       // PrevDecl. If it's NULL, we have a new definition.
+
+
+    // Otherwise, PrevDecl is not a tag, but was found with tag
+    // lookup.  This is only actually possible in C++, where a few
+    // things like templates still live in the tag namespace.
     } else {
-      // PrevDecl is a namespace, template, or anything else
-      // that lives in the IDNS_Tag identifier namespace.
-      if (TUK == TUK_Reference || TUK == TUK_Friend ||
-          isDeclInScope(PrevDecl, SearchDC, S)) {
-        // The tag name clashes with a namespace name, issue an error and
-        // recover by making this tag be anonymous.
+      assert(getLangOptions().CPlusPlus);
+
+      // Use a better diagnostic if an elaborated-type-specifier
+      // found the wrong kind of type on the first
+      // (non-redeclaration) lookup.
+      if ((TUK == TUK_Reference || TUK == TUK_Friend) &&
+          !Previous.isForRedeclaration()) {
+        unsigned Kind = 0;
+        if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
+        else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
+        Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
+        Diag(PrevDecl->getLocation(), diag::note_declared_at);
+        Invalid = true;
+
+      // Otherwise, only diagnose if the declaration is in scope.
+      } else if (!isDeclInScope(PrevDecl, SearchDC, S)) {
+        // do nothing
+
+      // Diagnose implicit declarations introduced by elaborated types.
+      } else if (TUK == TUK_Reference || TUK == TUK_Friend) {
+        unsigned Kind = 0;
+        if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
+        else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
+        Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
+        Invalid = true;
+
+      // Otherwise it's a declaration.  Call out a particularly common
+      // case here.
+      } else if (isa<TypedefDecl>(PrevDecl)) {
+        Diag(NameLoc, diag::err_tag_definition_of_typedef)
+          << Name
+          << cast<TypedefDecl>(PrevDecl)->getUnderlyingType();
+        Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
+        Invalid = true;
+
+      // Otherwise, diagnose.
+      } else {
+        // The tag name clashes with something else in the target scope,
+        // issue an error and recover by making this tag be anonymous.
         Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
         Diag(PrevDecl->getLocation(), diag::note_previous_definition);
         Name = 0;
-        Previous.clear();
         Invalid = true;
-      } else {
-        // The existing declaration isn't relevant to us; we're in a
-        // new scope, so clear out the previous declaration.
-        Previous.clear();
       }
+
+      // The existing declaration isn't relevant to us; we're in a
+      // new scope, so clear out the previous declaration.
+      Previous.clear();
     }
   }
 
@@ -5187,28 +5250,6 @@
       New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8));
   }
 
-  if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) {
-    // C++ [dcl.typedef]p3:
-    //   [...] Similarly, in a given scope, a class or enumeration
-    //   shall not be declared with the same name as a typedef-name
-    //   that is declared in that scope and refers to a type other
-    //   than the class or enumeration itself.
-    LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName,
-                        ForRedeclaration);
-    LookupName(Lookup, S);
-    TypedefDecl *PrevTypedef = Lookup.getAsSingle<TypedefDecl>();
-    NamedDecl *PrevTypedefNamed = PrevTypedef;
-    if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) &&
-        Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) !=
-          Context.getCanonicalType(Context.getTypeDeclType(New))) {
-      Diag(Loc, diag::err_tag_definition_of_typedef)
-        << Context.getTypeDeclType(New)
-        << PrevTypedef->getUnderlyingType();
-      Diag(PrevTypedef->getLocation(), diag::note_previous_definition);
-      Invalid = true;
-    }
-  }
-
   // If this is a specialization of a member class (of a class template),
   // check the specialization.
   if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 8de0c40..a7a1084 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -202,26 +202,6 @@
     !D->getDeclContext()->isRecord();
 }
 
-static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) {
-  // This lookup ignores everything that isn't a type.
-
-  // This is a fast check for the far most common case.
-  if (D->isInIdentifierNamespace(Decl::IDNS_Tag))
-    return true;
-
-  if (isa<UsingShadowDecl>(D))
-    D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
-  return isa<TypeDecl>(D);
-}
-
-static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) {
-  // We don't need to look through using decls here because
-  // using decls aren't allowed to name namespaces.
-
-  return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
-}
-
 /// Gets the default result filter for the given lookup.
 static inline
 LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
@@ -232,16 +212,12 @@
   case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
   case Sema::LookupUsingDeclName:
   case Sema::LookupObjCProtocolName:
+  case Sema::LookupNestedNameSpecifierName:
+  case Sema::LookupNamespaceName:
     return &IsAcceptableIDNS;
 
   case Sema::LookupOperatorName:
     return &IsAcceptableOperatorName;
-
-  case Sema::LookupNestedNameSpecifierName:
-    return &IsAcceptableNestedNameSpecifierName;
-
-  case Sema::LookupNamespaceName:
-    return &IsAcceptableNamespaceName;
   }
 
   llvm_unreachable("unkknown lookup kind");
@@ -260,15 +236,25 @@
   case Sema::LookupRedeclarationWithLinkage:
     IDNS = Decl::IDNS_Ordinary;
     if (CPlusPlus) {
-      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
+      IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
       if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
     }
     break;
 
   case Sema::LookupTagName:
-    IDNS = Decl::IDNS_Tag;
-    if (CPlusPlus && Redeclaration)
-      IDNS |= Decl::IDNS_TagFriend;
+    if (CPlusPlus) {
+      IDNS = Decl::IDNS_Type;
+
+      // When looking for a redeclaration of a tag name, we add:
+      // 1) TagFriend to find undeclared friend decls
+      // 2) Namespace because they can't "overload" with tag decls.
+      // 3) Tag because it includes class templates, which can't
+      //    "overload" with tag decls.
+      if (Redeclaration)
+        IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace;
+    } else {
+      IDNS = Decl::IDNS_Tag;
+    }
     break;
 
   case Sema::LookupMemberName:
@@ -278,8 +264,11 @@
     break;
 
   case Sema::LookupNestedNameSpecifierName:
+    IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace;
+    break;
+
   case Sema::LookupNamespaceName:
-    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
+    IDNS = Decl::IDNS_Namespace;
     break;
 
   case Sema::LookupUsingDeclName:
@@ -2134,7 +2123,7 @@
                                IEnd = Pos->second.end();
          I != IEnd; ++I) {
       // A tag declaration does not hide a non-tag declaration.
-      if ((*I)->getIdentifierNamespace() == Decl::IDNS_Tag &&
+      if ((*I)->hasTagIdentifierNamespace() &&
           (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
                    Decl::IDNS_ObjCProtocol)))
         continue;