hintonda updated this revision to Diff 47999.
hintonda added a comment.
- Renamed variables to make code self-documenting
http://reviews.llvm.org/D17215
Files:
lib/Sema/SemaTemplate.cpp
test/SemaCXX/pr14211-crash-on-invalid.cpp
Index: test/SemaCXX/pr14211-crash-on-invalid.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/pr14211-crash-on-invalid.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// Don't crash (PR14211).
+
+template<class T>
+struct X {
+ void bar(T t) {}
+ void foo(T t, int i) {}
+ template<class U>
+ void foo(T t, U i) {}
+};
+
+template class X<double>; // expected-note {{previous explicit instantiation
is here}}
+template void X<double>::foo(double t, int i); // expected-error {{duplicate
explicit instantiation of 'foo'}}
+template void X<double>::foo<int>(double t, int i);
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7825,20 +7825,24 @@
// A member function [...] of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
- UnresolvedSet<8> Matches;
+ UnresolvedSet<8> TemplateMatches;
+ FunctionDecl *NonTemplateMatch = nullptr;
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
if (!HasExplicitTemplateArgs) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
QualType Adjusted = adjustCCAndNoReturn(R, Method->getType());
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
- Matches.clear();
-
- Matches.addDecl(Method, P.getAccess());
- if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
- break;
+ if (Method->getPrimaryTemplate()){
+ TemplateMatches.clear();
+
+ TemplateMatches.addDecl(Method, P.getAccess());
+ if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
+ break;
+ } else
+ NonTemplateMatch = Method;
}
}
}
@@ -7862,22 +7866,25 @@
continue;
}
- Matches.addDecl(Specialization, P.getAccess());
+ TemplateMatches.addDecl(Specialization, P.getAccess());
}
+ FunctionDecl *Specialization = NonTemplateMatch;
// Find the most specialized function template specialization.
- UnresolvedSetIterator Result = getMostSpecialized(
- Matches.begin(), Matches.end(), FailedCandidates,
- D.getIdentifierLoc(),
- PDiag(diag::err_explicit_instantiation_not_known) << Name,
- PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
- PDiag(diag::note_explicit_instantiation_candidate));
-
- if (Result == Matches.end())
- return true;
+ if (!Specialization) {
+ UnresolvedSetIterator Result = getMostSpecialized(
+ TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates,
+ D.getIdentifierLoc(),
+ PDiag(diag::err_explicit_instantiation_not_known) << Name,
+ PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+ PDiag(diag::note_explicit_instantiation_candidate));
+
+ if (Result == TemplateMatches.end())
+ return true;
- // Ignore access control bits, we don't need them for redeclaration checking.
- FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+ // Ignore access control bits, we don't need them for redeclaration
checking.
+ Specialization = cast<FunctionDecl>(*Result);
+ }
// C++11 [except.spec]p4
// In an explicit instantiation an exception-specification may be specified,
Index: test/SemaCXX/pr14211-crash-on-invalid.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/pr14211-crash-on-invalid.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// Don't crash (PR14211).
+
+template<class T>
+struct X {
+ void bar(T t) {}
+ void foo(T t, int i) {}
+ template<class U>
+ void foo(T t, U i) {}
+};
+
+template class X<double>; // expected-note {{previous explicit instantiation is here}}
+template void X<double>::foo(double t, int i); // expected-error {{duplicate explicit instantiation of 'foo'}}
+template void X<double>::foo<int>(double t, int i);
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7825,20 +7825,24 @@
// A member function [...] of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
- UnresolvedSet<8> Matches;
+ UnresolvedSet<8> TemplateMatches;
+ FunctionDecl *NonTemplateMatch = nullptr;
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
if (!HasExplicitTemplateArgs) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
QualType Adjusted = adjustCCAndNoReturn(R, Method->getType());
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
- Matches.clear();
-
- Matches.addDecl(Method, P.getAccess());
- if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
- break;
+ if (Method->getPrimaryTemplate()){
+ TemplateMatches.clear();
+
+ TemplateMatches.addDecl(Method, P.getAccess());
+ if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
+ break;
+ } else
+ NonTemplateMatch = Method;
}
}
}
@@ -7862,22 +7866,25 @@
continue;
}
- Matches.addDecl(Specialization, P.getAccess());
+ TemplateMatches.addDecl(Specialization, P.getAccess());
}
+ FunctionDecl *Specialization = NonTemplateMatch;
// Find the most specialized function template specialization.
- UnresolvedSetIterator Result = getMostSpecialized(
- Matches.begin(), Matches.end(), FailedCandidates,
- D.getIdentifierLoc(),
- PDiag(diag::err_explicit_instantiation_not_known) << Name,
- PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
- PDiag(diag::note_explicit_instantiation_candidate));
-
- if (Result == Matches.end())
- return true;
+ if (!Specialization) {
+ UnresolvedSetIterator Result = getMostSpecialized(
+ TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates,
+ D.getIdentifierLoc(),
+ PDiag(diag::err_explicit_instantiation_not_known) << Name,
+ PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+ PDiag(diag::note_explicit_instantiation_candidate));
+
+ if (Result == TemplateMatches.end())
+ return true;
- // Ignore access control bits, we don't need them for redeclaration checking.
- FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+ // Ignore access control bits, we don't need them for redeclaration checking.
+ Specialization = cast<FunctionDecl>(*Result);
+ }
// C++11 [except.spec]p4
// In an explicit instantiation an exception-specification may be specified,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits