[cfe-commits] r102164 - in /cfe/trunk: include/clang/AST/DeclBase.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/typedef-redecl.cpp

John McCall rjmccall at apple.com
Thu Apr 22 19:41:41 PDT 2010


Author: rjmccall
Date: Thu Apr 22 21:41:41 2010
New Revision: 102164

URL: http://llvm.org/viewvc/llvm-project?rev=102164&view=rev
Log:
C++ doesn't really use "namespaces" for different kinds of names the same
way that C does.  Among other differences, elaborated type specifiers
are defined to skip "non-types", which, as you might imagine, does not
include typedefs.  Rework our use of IDNS masks to capture the semantics
of different kinds of declarations better, and remove most current lookup
filters.  Removing the last remaining filter is more complicated and will
happen in a separate patch.

Fixes PR 6885 as well some spectrum of unfiled bugs.


Added:
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.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/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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Apr 22 21:41:41 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
@@ -453,14 +492,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/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Apr 22 21:41:41 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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Apr 22 21:41:41 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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Apr 22 21:41:41 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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Apr 22 21:41:41 2010
@@ -415,6 +415,9 @@
 
     return false;
   }
+
+  if (Filter == &ResultBuilder::IsNestedNameSpecifier)
+    AsNestedNameSpecifier = true;
   
   // ... then it must be interesting!
   return true;
@@ -504,7 +507,8 @@
     }
     for (; I != IEnd; ++I) {
       // A tag declaration does not hide a non-tag declaration.
-      if (I->first->getIdentifierNamespace() == Decl::IDNS_Tag &&
+      if (I->first->getIdentifierNamespace()
+            == (Decl::IDNS_Tag | Decl::IDNS_Type) &&
           (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
                    Decl::IDNS_ObjCProtocol)))
         continue;
@@ -629,7 +633,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 +645,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 +2098,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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Apr 22 21:41:41 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,26 @@
 
   if (!Previous.empty()) {
     NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+
+    // It's okay to have a tag decl in the same scope as a typedef
+    // which shadows a tag decl in the same scope.  Finding this
+    // insanity with a redeclaration lookup can only actually happen
+    // in C++.
+    if (getLangOptions().CPlusPlus &&
+        TUK != TUK_Reference && TUK != TUK_Friend) {
+      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(SearchDC)) {
+            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 +5121,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 +5246,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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Apr 22 21:41:41 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,8 @@
                                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)->getIdentifierNamespace()
+            == (Decl::IDNS_Tag|Decl::IDNS_Type) &&
           (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
                    Decl::IDNS_ObjCProtocol)))
         continue;

Added: 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?rev=102164&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp Thu Apr 22 21:41:41 2010
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace test0 {
+  struct A {
+    static int foo;
+  };
+  
+  namespace i0 {
+    typedef int A; // expected-note {{declared here}}
+
+    int test() {
+      struct A a; // expected-error {{elaborated type refers to a typedef}}
+      return a.foo;
+    }
+  }
+
+  namespace i1 {
+    template <class> class A; // expected-note {{declared here}}
+
+    int test() {
+      struct A a; // expected-error {{elaborated type refers to a template}}
+      return a.foo;
+    }
+  }
+
+  namespace i2 {
+    int A;
+
+    int test() {
+      struct A a;
+      return a.foo;
+    }
+  }
+
+  namespace i3 {
+    void A();
+
+    int test() {
+      struct A a;
+      return a.foo;
+    }
+  }
+
+  namespace i4 {
+    template <class T> void 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=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Thu Apr 22 21:41:41 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=102164&r1=102163&r2=102164&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 Thu Apr 22 21:41:41 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/typedef-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typedef-redecl.cpp?rev=102164&r1=102163&r2=102164&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typedef-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/typedef-redecl.cpp Thu Apr 22 21:41:41 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