[cfe-commits] r102198 - in /cfe/trunk: include/clang/AST/DeclBase.h include/clang/AST/DeclContextInternals.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTImporter.cpp lib/AST/DeclBase.cpp lib/Sema/SemaCodeComplete.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaLookup.cpp test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp test/CXX/class.access/class.friend/p1.cpp test/CXX/temp/temp.decls/temp.friend/p1.cpp test/SemaCXX/constructor-initializer.cpp test/SemaCXX/typedef-redecl.cpp

John McCall rjmccall at apple.com
Fri Apr 23 11:46:30 PDT 2010


Author: rjmccall
Date: Fri Apr 23 13:46:30 2010
New Revision: 102198

URL: http://llvm.org/viewvc/llvm-project?rev=102198&view=rev
Log:
Recommit my change to how C++ does elaborated type lookups, now with
two bugfixes which fix selfhost and (hopefully) the nightly tests.


Added:
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp
      - copied, changed from r102173, cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/DeclContextInternals.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
    cfe/trunk/test/SemaCXX/constructor-initializer.cpp
    cfe/trunk/test/SemaCXX/typedef-redecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Apr 23 13:46:30 2010
@@ -76,24 +76,63 @@
 #include "clang/AST/DeclNodes.def"
   };
 
-  /// IdentifierNamespace - According to C99 6.2.3, there are four
-  /// namespaces, labels, tags, members and ordinary
-  /// identifiers. These are meant as bitmasks, so that searches in
-  /// C++ can look into the "tag" namespace during ordinary lookup. We
-  /// use additional namespaces for Objective-C entities.  We also put
-  /// C++ friend declarations (of previously-undeclared entities) in
-  /// shadow namespaces, and 'using' declarations (as opposed to their
-  /// implicit shadow declarations) can be found in their own
-  /// namespace.
+  /// IdentifierNamespace - The different namespaces in which
+  /// declarations may appear.  According to C99 6.2.3, there are
+  /// four namespaces, labels, tags, members and ordinary
+  /// identifiers.  C++ describes lookup completely differently:
+  /// certain lookups merely "ignore" certain kinds of declarations,
+  /// usually based on whether the declaration is of a type, etc.
+  /// 
+  /// These are meant as bitmasks, so that searches in
+  /// C++ can look into the "tag" namespace during ordinary lookup.
+  ///
+  /// Decl currently provides 16 bits of IDNS bits.
   enum IdentifierNamespace {
-    IDNS_Label = 0x1,
-    IDNS_Tag = 0x2,
-    IDNS_Member = 0x4,
-    IDNS_Ordinary = 0x8,
-    IDNS_ObjCProtocol = 0x10,
-    IDNS_OrdinaryFriend = 0x80,
-    IDNS_TagFriend = 0x100,
-    IDNS_Using = 0x200
+    /// Labels, declared with 'x:' and referenced with 'goto x'.
+    IDNS_Label               = 0x0001,
+
+    /// Tags, declared with 'struct foo;' and referenced with
+    /// 'struct foo'.  All tags are also types.  This is what
+    /// elaborated-type-specifiers look for in C.
+    IDNS_Tag                 = 0x0002,
+
+    /// Types, declared with 'struct foo', typedefs, etc.
+    /// This is what elaborated-type-specifiers look for in C++,
+    /// but note that it's ill-formed to find a non-tag.
+    IDNS_Type                = 0x0004,
+
+    /// Members, declared with object declarations within tag
+    /// definitions.  In C, these can only be found by "qualified"
+    /// lookup in member expressions.  In C++, they're found by
+    /// normal lookup.
+    IDNS_Member              = 0x0008,
+
+    /// Namespaces, declared with 'namespace foo {}'.
+    /// Lookup for nested-name-specifiers find these.
+    IDNS_Namespace           = 0x0010,
+
+    /// Ordinary names.  In C, everything that's not a label, tag,
+    /// or member ends up here.
+    IDNS_Ordinary            = 0x0020,
+
+    /// Objective C @protocol.
+    IDNS_ObjCProtocol        = 0x0040,
+
+    /// This declaration is a friend function.  A friend function
+    /// declaration is always in this namespace but may also be in
+    /// IDNS_Ordinary if it was previously declared.
+    IDNS_OrdinaryFriend      = 0x0080,
+
+    /// This declaration is a friend class.  A friend class
+    /// declaration is always in this namespace but may also be in
+    /// IDNS_Tag|IDNS_Type if it was previously declared.
+    IDNS_TagFriend           = 0x0100,
+
+    /// This declaration is a using declaration.  A using declaration
+    /// *introduces* a number of other declarations into the current
+    /// scope, and those declarations use the IDNS of their targets,
+    /// but the actual using declarations go in this namespace.
+    IDNS_Using               = 0x0200
   };
 
   /// ObjCDeclQualifier - Qualifier used on types in method declarations
@@ -311,6 +350,13 @@
   }
   static unsigned getIdentifierNamespaceForKind(Kind DK);
 
+  bool hasTagIdentifierNamespace() const {
+    return isTagIdentifierNamespace(getIdentifierNamespace());
+  }
+  static bool isTagIdentifierNamespace(unsigned NS) {
+    // TagDecls have Tag and Type set and may also have TagFriend.
+    return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type);
+  }
 
   /// getLexicalDeclContext - The declaration context where this Decl was
   /// lexically declared (LexicalDC). May be different from
@@ -453,14 +499,14 @@
     assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
                      IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
            "namespace includes neither ordinary nor tag");
-    assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary |
+    assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
                        IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
            "namespace includes other than ordinary or tag");
 
     IdentifierNamespace = 0;
     if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
       IdentifierNamespace |= IDNS_TagFriend;
-      if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag;
+      if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
     }
 
     if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {

Modified: cfe/trunk/include/clang/AST/DeclContextInternals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclContextInternals.h?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclContextInternals.h (original)
+++ cfe/trunk/include/clang/AST/DeclContextInternals.h Fri Apr 23 13:46:30 2010
@@ -230,7 +230,7 @@
     // Tag declarations always go at the end of the list so that an
     // iterator which points at the first tag will start a span of
     // decls that only contains tags.
-    if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
+    if (D->hasTagIdentifierNamespace())
       Vec.push_back(reinterpret_cast<uintptr_t>(D));
 
     // Resolved using declarations go at the front of the list so that
@@ -251,7 +251,7 @@
     // tag declarations.  But we can be clever about tag declarations
     // because there can only ever be one in a scope.
     } else if (reinterpret_cast<NamedDecl *>(Vec.back())
-                 ->getIdentifierNamespace() == Decl::IDNS_Tag) {
+                 ->hasTagIdentifierNamespace()) {
       uintptr_t TagD = Vec.back();
       Vec.back() = reinterpret_cast<uintptr_t>(D);
       Vec.push_back(TagD);

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Apr 23 13:46:30 2010
@@ -1583,6 +1583,11 @@
   "redefinition of %0 as different kind of symbol">;
 def err_redefinition_different_typedef : Error<
   "typedef redefinition with different types (%0 vs %1)">;
+def err_tag_reference_non_tag : Error<
+  "elaborated type refers to %select{a non-tag type|a typedef|a template}0">;
+def err_tag_reference_conflict : Error<
+  "implicit declaration introduced by elaborated type conflicts with "
+  "%select{a declaration|a typedef|a template}0 of the same name">;
 def err_tag_definition_of_typedef : Error<
   "definition of type %0 conflicts with typedef of the same name">;
 def err_conflicting_types : Error<"conflicting types for %0">;

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Apr 23 13:46:30 2010
@@ -1438,7 +1438,7 @@
     for (DeclContext::lookup_result Lookup = DC->lookup(Name);
          Lookup.first != Lookup.second; 
          ++Lookup.first) {
-      if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+      if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Namespace))
         continue;
       
       if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) {
@@ -1451,7 +1451,7 @@
     }
     
     if (!ConflictingDecls.empty()) {
-      Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
+      Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace,
                                          ConflictingDecls.data(), 
                                          ConflictingDecls.size());
     }

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Apr 23 13:46:30 2010
@@ -231,23 +231,28 @@
     case CXXConstructor:
     case CXXDestructor:
     case CXXConversion:
-    case Typedef:
     case EnumConstant:
     case Var:
     case ImplicitParam:
     case ParmVar:
     case NonTypeTemplateParm:
     case ObjCMethod:
-    case ObjCInterface:
     case ObjCProperty:
-    case ObjCCompatibleAlias:
       return IDNS_Ordinary;
 
+    case ObjCCompatibleAlias:
+    case ObjCInterface:
+      return IDNS_Ordinary | IDNS_Type;
+
+    case Typedef:
+    case UnresolvedUsingTypename:
+    case TemplateTypeParm:
+      return IDNS_Ordinary | IDNS_Type;
+
     case UsingShadow:
       return 0; // we'll actually overwrite this later
 
     case UnresolvedUsingValue:
-    case UnresolvedUsingTypename:
       return IDNS_Ordinary | IDNS_Using;
 
     case Using:
@@ -264,15 +269,18 @@
     case Record:
     case CXXRecord:
     case Enum:
-    case TemplateTypeParm:
-      return IDNS_Tag;
+      return IDNS_Tag | IDNS_Type;
 
     case Namespace:
+    case NamespaceAlias:
+      return IDNS_Namespace;
+
     case FunctionTemplate:
+      return IDNS_Ordinary;
+
     case ClassTemplate:
     case TemplateTemplateParm:
-    case NamespaceAlias:
-      return IDNS_Tag | IDNS_Ordinary;
+      return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
 
     // Never have names.
     case Friend:

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Apr 23 13:46:30 2010
@@ -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());
 }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Apr 23 13:46:30 2010
@@ -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))

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Apr 23 13:46:30 2010
@@ -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;

Copied: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp (from r102173, cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp?p2=cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp&p1=cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp&r1=102173&r2=102198&rev=102198&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp Fri Apr 23 13:46:30 2010
@@ -49,4 +49,12 @@
       return a.foo;
     }
   }
+
+  // This should magically be okay;  see comment in SemaDecl.cpp.
+  // rdar://problem/7898108
+  typedef struct A A;
+  int test() {
+    struct A a;
+    return a.foo;
+  }
 }

Modified: cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Fri Apr 23 13:46:30 2010
@@ -280,3 +280,10 @@
   }
   template A::I g2<A::I>(A::I i);
 }
+
+// PR6885
+namespace test9 {
+  class B {
+    friend class test9;
+  };
+}

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp Fri Apr 23 13:46:30 2010
@@ -155,7 +155,7 @@
 }
 
 namespace test7 {
-  template <class T> class A { // expected-note {{previous definition is here}}
+  template <class T> class A { // expected-note {{declared here}}
     friend class B;
     int x; // expected-note {{declared private here}}
   };
@@ -174,7 +174,7 @@
 
   // This shouldn't crash.
   template <class T> class D {
-    friend class A; // expected-error {{redefinition of 'A' as different kind of symbol}}
+    friend class A; // expected-error {{elaborated type refers to a template}}
   };
   template class D<int>;
 }

Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Fri Apr 23 13:46:30 2010
@@ -182,3 +182,10 @@
 };
 
 }
+
+namespace test1 {
+  struct A {
+    enum Kind { Foo } Kind;
+    A() : Kind(Foo) {}
+  };
+}

Modified: cfe/trunk/test/SemaCXX/typedef-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typedef-redecl.cpp?rev=102198&r1=102197&r2=102198&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typedef-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/typedef-redecl.cpp Fri Apr 23 13:46:30 2010
@@ -13,7 +13,7 @@
 struct Y; // expected-note{{previous definition is here}}
 typedef int Y;  // expected-error{{typedef redefinition with different types ('int' vs 'Y')}}
 
-typedef int Y2; // expected-note{{previous definition is here}}
+typedef int Y2; // expected-note{{declared here}}
 struct Y2; // expected-error{{definition of type 'Y2' conflicts with typedef of the same name}}
 
 void f(); // expected-note{{previous definition is here}}





More information about the cfe-commits mailing list