]> granicus.if.org Git - clang/commitdiff
Fix handling of redeclaration lookup for using declarations, where the prior
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 11 Apr 2014 01:03:38 +0000 (01:03 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 11 Apr 2014 01:03:38 +0000 (01:03 +0000)
declaration is not visible. Previously we didn't find hidden friend names in
this redeclaration lookup, because we forgot to treat it as a redeclaration
lookup. Conversely, we did find some local extern names, but those don't
actually conflict with a namespace-scope using declaration, because the only
conflicts we can get are scope conflicts, not conflicts due to the entities
being members of the same namespace.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206011 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaLookup.cpp
test/SemaCXX/using-decl-1.cpp

index 850db26e9afa02efdc682547856029bef2f1ac55..fbc3fd7eb8169c0297a3b657b32adbfaa0c1b911 100644 (file)
@@ -7379,6 +7379,13 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
       NamedDecl *D = F.next();
       if (!isDeclInScope(D, CurContext, S))
         F.erase();
+      // If we found a local extern declaration that's not ordinarily visible,
+      // and this declaration is being added to a non-block scope, ignore it.
+      // We're only checking for scope conflicts here, not also for violations
+      // of the linkage rules.
+      else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
+               !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
+        F.erase();
     }
     F.done();
   } else {
index 39a1ceaa57ecc2a6c01b586bf0e48accd1bac2b7..172a07906da014fdf4d38c6b32ad72cefdcc29d4 100644 (file)
@@ -244,10 +244,11 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
       IDNS = Decl::IDNS_Tag;
     }
     break;
+
   case Sema::LookupLabel:
     IDNS = Decl::IDNS_Label;
     break;
-      
+
   case Sema::LookupMemberName:
     IDNS = Decl::IDNS_Member;
     if (CPlusPlus)
@@ -263,8 +264,10 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
     break;
 
   case Sema::LookupUsingDeclName:
-    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
-         | Decl::IDNS_Member | Decl::IDNS_Using;
+    assert(Redeclaration && "should only be used for redecl lookup");
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member |
+           Decl::IDNS_Using | Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend |
+           Decl::IDNS_LocalExtern;
     break;
 
   case Sema::LookupObjCProtocolName:
index 24d92f175c302d271df2a19869f4f1e69fdc17d3..21aa107e219d8b1b12026f85ef302bd66b2522c4 100644 (file)
@@ -160,3 +160,37 @@ namespace M { }
 }
 using N::M::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_nested_specifier::N::M'; did you mean 'N::FFF'?}}
 }
+
+namespace UsingDeclVsHiddenName {
+  namespace A {
+    enum HiddenTag1 {}; // expected-note {{previous use is here}}
+    enum HiddenTag2 {}; // expected-note {{target}}
+    int HiddenFn1; // expected-note {{target}}
+    int HiddenFn2; // expected-note {{target}}
+    int HiddenLocalExtern1;
+    int HiddenLocalExtern2;
+  }
+
+  namespace B {
+    using A::HiddenTag1;
+    using A::HiddenFn1; // expected-note {{using declaration}}
+    using A::HiddenLocalExtern1;
+
+    struct S {
+      friend struct HiddenTag1; // expected-error {{tag type that does not match previous}}
+      friend struct HiddenTag2; // expected-note {{conflicting declaration}}
+      friend void HiddenFn1(); // expected-error {{cannot befriend target of using declaration}}
+      friend void HiddenFn2(); // expected-note {{conflicting declaration}}
+      void f() {
+        // OK, these are not in the scope of namespace B, even though they're
+        // members of the namespace.
+        void HiddenLocalExtern1();
+        void HiddenLocalExtern2();
+      }
+    };
+
+    using A::HiddenTag2; // expected-error {{conflicts with declaration already in scope}}
+    using A::HiddenFn2; // expected-error {{conflicts with declaration already in scope}}
+    using A::HiddenLocalExtern2;
+  }
+}