Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit ce43b3d

Browse files
committed
When determining the target function of an explicit instantiation, make
sure that non-template functions don't end up in the candidate set. Fixes PR14211. Patch by Don Hinton! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304951 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 410ea62 commit ce43b3d

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

lib/Sema/SemaTemplate.cpp

+25-19
Original file line numberDiff line numberDiff line change
@@ -8957,7 +8957,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
89578957
// A member function [...] of a class template can be explicitly
89588958
// instantiated from the member definition associated with its class
89598959
// template.
8960-
UnresolvedSet<8> Matches;
8960+
UnresolvedSet<8> TemplateMatches;
8961+
FunctionDecl *NonTemplateMatch = nullptr;
89618962
AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
89628963
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
89638964
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
@@ -8968,11 +8969,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
89688969
QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
89698970
/*AdjustExceptionSpec*/true);
89708971
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
8971-
Matches.clear();
8972-
8973-
Matches.addDecl(Method, P.getAccess());
8974-
if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
8975-
break;
8972+
if (Method->getPrimaryTemplate()) {
8973+
TemplateMatches.addDecl(Method, P.getAccess());
8974+
} else {
8975+
// FIXME: Can this assert ever happen? Needs a test.
8976+
assert(!NonTemplateMatch && "Multiple NonTemplateMatches");
8977+
NonTemplateMatch = Method;
8978+
}
89768979
}
89778980
}
89788981
}
@@ -9011,22 +9014,25 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
90119014
continue;
90129015
}
90139016

9014-
Matches.addDecl(Specialization, P.getAccess());
9017+
TemplateMatches.addDecl(Specialization, P.getAccess());
90159018
}
90169019

9017-
// Find the most specialized function template specialization.
9018-
UnresolvedSetIterator Result = getMostSpecialized(
9019-
Matches.begin(), Matches.end(), FailedCandidates,
9020-
D.getIdentifierLoc(),
9021-
PDiag(diag::err_explicit_instantiation_not_known) << Name,
9022-
PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
9023-
PDiag(diag::note_explicit_instantiation_candidate));
9024-
9025-
if (Result == Matches.end())
9026-
return true;
9020+
FunctionDecl *Specialization = NonTemplateMatch;
9021+
if (!Specialization) {
9022+
// Find the most specialized function template specialization.
9023+
UnresolvedSetIterator Result = getMostSpecialized(
9024+
TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates,
9025+
D.getIdentifierLoc(),
9026+
PDiag(diag::err_explicit_instantiation_not_known) << Name,
9027+
PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
9028+
PDiag(diag::note_explicit_instantiation_candidate));
9029+
9030+
if (Result == TemplateMatches.end())
9031+
return true;
90279032

9028-
// Ignore access control bits, we don't need them for redeclaration checking.
9029-
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
9033+
// Ignore access control bits, we don't need them for redeclaration checking.
9034+
Specialization = cast<FunctionDecl>(*Result);
9035+
}
90309036

90319037
// C++11 [except.spec]p4
90329038
// In an explicit instantiation an exception-specification may be specified,

test/CXX/temp/temp.decls/temp.mem/p5.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,16 @@ void test_X0(X0 x0, const X0 &x0c) {
7777
x0.operator float *();
7878
x0c.operator const char*();
7979
}
80+
81+
namespace PR14211 {
82+
template <class U> struct X {
83+
void foo(U){}
84+
template <class T> void foo(T){}
85+
86+
template <class T> void bar(T){}
87+
void bar(U){}
88+
};
89+
90+
template void X<int>::foo(int);
91+
template void X<int>::bar(int);
92+
}

0 commit comments

Comments
 (0)