that are declarations (rather than definitions). Also, be sure to set
the access specifiers properly when instantiating the declarations of
member function templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83911
91177308-0d34-0410-b5e6-
96231b3b80d8
// 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();
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));
// 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);
--- /dev/null
+// 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) { }