Permit explicit specialization of member functions of class templates

that are declarations (rather than definitions). Also, be sure to set
the access specifiers properly when instantiating the declarations of
member function templates.

llvm-svn: 83911
This commit is contained in:
Douglas Gregor 2009-10-12 22:27:17 +00:00
parent e724ae92a8
commit ca027af608
3 changed files with 40 additions and 4 deletions

View File

@ -2810,7 +2810,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// function templates or member functions of class templates, per
// C++ [temp.expl.spec]p2.
if (!IsFunctionDefinition && !isFriend &&
NewFD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
!isFunctionTemplateSpecialization && !isExplicitSpecialization) {
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
@ -2979,9 +2979,17 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
return NewFD->setInvalidDecl();
if (FunctionTemplateDecl *OldTemplateDecl
= dyn_cast<FunctionTemplateDecl>(OldDecl))
= dyn_cast<FunctionTemplateDecl>(OldDecl)) {
NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
else {
FunctionTemplateDecl *NewTemplateDecl
= NewFD->getDescribedFunctionTemplate();
assert(NewTemplateDecl && "Template/non-template mismatch");
if (CXXMethodDecl *Method
= dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
Method->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
}
} else {
if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
NewFD->setAccess(OldDecl->getAccess());
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));

View File

@ -431,7 +431,9 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// Link the instantiated function template declaration to the function
// template from which it was instantiated.
FunctionTemplateDecl *InstTemplate = InstMethod->getDescribedFunctionTemplate();
FunctionTemplateDecl *InstTemplate
= InstMethod->getDescribedFunctionTemplate();
InstTemplate->setAccess(D->getAccess());
assert(InstTemplate && "VisitCXXMethodDecl didn't create a template!");
InstTemplate->setInstantiatedFromMemberTemplate(D);
Owner->addDecl(InstTemplate);

View File

@ -0,0 +1,26 @@
// RUN: clang-cc -fsyntax-only %s
template<class T> struct A {
void f(T);
template<class X1> void g1(T, X1);
template<class X2> void g2(T, X2);
void h(T) { }
};
// specialization
template<> void A<int>::f(int);
// out of class member template definition
template<class T> template<class X1> void A<T>::g1(T, X1) { }
// member template specialization
template<> template<class X1> void A<int>::g1(int, X1);
// member template specialization
template<> template<>
void A<int>::g1(int, char); // X1 deduced as char
template<> template<>
void A<int>::g2<char>(int, char); // X2 specified as char
// member specialization even if defined in class definition
template<> void A<int>::h(int) { }