forked from OSchip/llvm-project
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:
parent
e724ae92a8
commit
ca027af608
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) { }
|
Loading…
Reference in New Issue