]> granicus.if.org Git - clang/commitdiff
Fix name lookup for friend class templates to consider anything in a
authorDouglas Gregor <dgregor@apple.com>
Sat, 26 Sep 2009 07:05:09 +0000 (07:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 26 Sep 2009 07:05:09 +0000 (07:05 +0000)
scope *up to and including* the innermost namespace scope, rather than
just searching in the innermost namespace scope.

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

lib/Sema/SemaTemplate.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp [new file with mode: 0644]

index 72274525fd07221c54af6659632eb0eb0f9e65db..d037f3f3e38483f1579d60990d4a7ba674853a9e 100644 (file)
@@ -577,18 +577,6 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
       return true;
     }
 
-    Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName,
-                                   true);
-  } else if (TUK == TUK_Friend) {
-    // C++ [namespace.memdef]p3:
-    //   [...] When looking for a prior declaration of a class or a function 
-    //   declared as a friend, and when the name of the friend class or 
-    //   function is neither a qualified name nor a template-id, scopes outside
-    //   the innermost enclosing namespace scope are not considered.
-    SemanticContext = CurContext;
-    while (!SemanticContext->isFileContext())
-      SemanticContext = SemanticContext->getLookupParent();
-    
     Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName,
                                    true);
   } else {
@@ -601,7 +589,27 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
   if (Previous.begin() != Previous.end())
     PrevDecl = *Previous.begin();
 
-  if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
+  if (PrevDecl && TUK == TUK_Friend) {
+    // C++ [namespace.memdef]p3:
+    //   [...] When looking for a prior declaration of a class or a function 
+    //   declared as a friend, and when the name of the friend class or 
+    //   function is neither a qualified name nor a template-id, scopes outside
+    //   the innermost enclosing namespace scope are not considered.
+    DeclContext *OutermostContext = CurContext;
+    while (!OutermostContext->isFileContext())
+      OutermostContext = OutermostContext->getLookupParent();
+    
+    if (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
+        OutermostContext->Encloses(PrevDecl->getDeclContext())) {
+      SemanticContext = PrevDecl->getDeclContext();
+    } else {
+      // Declarations in outer scopes don't matter. However, the outermost
+      // context we computed is the semntic context for our new 
+      // declaration.
+      PrevDecl = 0;
+      SemanticContext = OutermostContext;
+    }
+  } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
     PrevDecl = 0;
 
   // If there is a previous declaration with the same name, check
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp
new file mode 100644 (file)
index 0000000..2ca7165
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T> struct X0 { };
+struct X1 { };
+
+struct Y {
+  template<typename T> union X0;
+  template<typename T> friend union X0;
+  
+  union X1;
+  friend union X1;
+};
+
+
+// FIXME: Woefully inadequate for testing