From f4776590402a62ff1517aa07f2d1e7284b80a5bc Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 14 Oct 2010 22:22:28 +0000 Subject: [PATCH] template-ids are looked up differently in friend declarations. llvm-svn: 116529 --- clang/lib/Sema/SemaDeclCXX.cpp | 7 ++++- .../namespace.def/namespace.memdef/p3.cpp | 27 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a63f057ae0a8..ee0b172ee61b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6384,6 +6384,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, // declaration, if there is no prior declaration, the program is // ill-formed. bool isLocal = cast(CurContext)->isLocalClass(); + bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; // Find the appropriate context according to the above. DC = CurContext; @@ -6404,7 +6405,11 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, if (isLocal || !Previous.empty()) break; - if (DC->isFileContext()) break; + if (isTemplateId) { + if (isa(DC)) break; + } else { + if (DC->isFileContext()) break; + } DC = DC->getParent(); } diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp index ddcbe785a739..069ca0a92588 100644 --- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only %s +// RUN: %clang_cc1 -fsyntax-only %s -verify // C++'0x [namespace.memdef] p3: // Every name first declared in a namespace is a member of that namespace. If @@ -66,3 +66,28 @@ namespace N3 { } // FIXME: Woefully inadequate for testing + +// Friends declared as template-ids aren't subject to the restriction +// on innermost namespaces. +// rdar://problem/8552377 +namespace test5 { + template void f(T); + namespace ns { + class A { + friend void f(int); + static void foo(); // expected-note 2 {{declared private here}} + }; + + // Note that this happens without instantiation. + template void f(T) { + A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} + } + } + + template void f(T) { + ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} + } + + template void f(int); + template void f(long); //expected-note {{instantiation}} +}