aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-10-14 22:22:28 +0000
committerJohn McCall <rjmccall@apple.com>2010-10-14 22:22:28 +0000
commit8a407370c37229f2b69fe643850959b98899c28a (patch)
treedfa261b5cad2e4b07daaf081e44899c2fdf47893
parent95f4292cc526c629fead321c7fcfd4fe0f3bc66e (diff)
template-ids are looked up differently in friend declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116529 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclCXX.cpp7
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp27
2 files changed, 32 insertions, 2 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a63f057ae0..ee0b172ee6 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/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<CXXRecordDecl>(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<TranslationUnitDecl>(DC)) break;
+ } else {
+ if (DC->isFileContext()) break;
+ }
DC = DC->getParent();
}
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
index ddcbe785a7..069ca0a925 100644
--- 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
@@ -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 <class T> void f(T);
+ namespace ns {
+ class A {
+ friend void f<int>(int);
+ static void foo(); // expected-note 2 {{declared private here}}
+ };
+
+ // Note that this happens without instantiation.
+ template <class T> void f(T) {
+ A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}}
+ }
+ }
+
+ template <class T> void f(T) {
+ ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}}
+ }
+
+ template void f<int>(int);
+ template void f<long>(long); //expected-note {{instantiation}}
+}