template-ids are looked up differently in friend declarations.
llvm-svn: 116529
This commit is contained in:
parent
57756eabc9
commit
f477659040
|
@ -6384,6 +6384,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
|
||||||
// declaration, if there is no prior declaration, the program is
|
// declaration, if there is no prior declaration, the program is
|
||||||
// ill-formed.
|
// ill-formed.
|
||||||
bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass();
|
bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass();
|
||||||
|
bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
|
||||||
|
|
||||||
// Find the appropriate context according to the above.
|
// Find the appropriate context according to the above.
|
||||||
DC = CurContext;
|
DC = CurContext;
|
||||||
|
@ -6404,7 +6405,11 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
|
||||||
if (isLocal || !Previous.empty())
|
if (isLocal || !Previous.empty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (DC->isFileContext()) break;
|
if (isTemplateId) {
|
||||||
|
if (isa<TranslationUnitDecl>(DC)) break;
|
||||||
|
} else {
|
||||||
|
if (DC->isFileContext()) break;
|
||||||
|
}
|
||||||
DC = DC->getParent();
|
DC = DC->getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only %s
|
// RUN: %clang_cc1 -fsyntax-only %s -verify
|
||||||
|
|
||||||
// C++'0x [namespace.memdef] p3:
|
// C++'0x [namespace.memdef] p3:
|
||||||
// Every name first declared in a namespace is a member of that namespace. If
|
// 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
|
// 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}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue