summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp75
-rw-r--r--test/SemaTemplate/alias-templates.cpp10
-rw-r--r--test/SemaTemplate/deduction.cpp2
3 files changed, 55 insertions, 32 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 160c9f0907..ba4a5b7bc0 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2280,16 +2280,18 @@ namespace {
};
}
-bool Sema::InstantiateClassTemplateSpecialization(
- SourceLocation PointOfInstantiation,
+/// Get the instantiation pattern to use to instantiate the definition of a
+/// given ClassTemplateSpecializationDecl (either the pattern of the primary
+/// template or of a partial specialization).
+static CXXRecordDecl *
+getPatternForClassTemplateSpecialization(
+ Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool Complain) {
- // Perform the actual instantiation on the canonical declaration.
- ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
- ClassTemplateSpec->getCanonicalDecl());
- if (ClassTemplateSpec->isInvalidDecl())
- return true;
-
+ Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
+ if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
+ return nullptr;
+
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
CXXRecordDecl *Pattern = nullptr;
@@ -2309,15 +2311,13 @@ bool Sema::InstantiateClassTemplateSpecialization(
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
TemplateDeductionInfo Info(FailedCandidates.getLocation());
- if (TemplateDeductionResult Result
- = DeduceTemplateArguments(Partial,
- ClassTemplateSpec->getTemplateArgs(),
- Info)) {
+ if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
+ Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate().set(
DeclAccessPair::make(Template, AS_public), Partial,
- MakeDeductionFailureInfo(Context, Result, Info));
+ MakeDeductionFailureInfo(S.Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());
@@ -2347,9 +2347,8 @@ bool Sema::InstantiateClassTemplateSpecialization(
for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
PEnd = Matched.end();
P != PEnd; ++P) {
- if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
- PointOfInstantiation)
- == P->Partial)
+ if (S.getMoreSpecializedPartialSpecialization(
+ P->Partial, Best->Partial, PointOfInstantiation) == P->Partial)
Best = P;
}
@@ -2360,9 +2359,9 @@ bool Sema::InstantiateClassTemplateSpecialization(
PEnd = Matched.end();
P != PEnd; ++P) {
if (P != Best &&
- getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
- PointOfInstantiation)
- != Best->Partial) {
+ S.getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+ PointOfInstantiation) !=
+ Best->Partial) {
Ambiguous = true;
break;
}
@@ -2370,20 +2369,20 @@ bool Sema::InstantiateClassTemplateSpecialization(
if (Ambiguous) {
// Partial ordering did not produce a clear winner. Complain.
+ Inst.Clear();
ClassTemplateSpec->setInvalidDecl();
- Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+ S.Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
<< ClassTemplateSpec;
// Print the matching partial specializations.
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
PEnd = Matched.end();
P != PEnd; ++P)
- Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
- << getTemplateArgumentBindingsText(
- P->Partial->getTemplateParameters(),
- *P->Args);
+ S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+ << S.getTemplateArgumentBindingsText(
+ P->Partial->getTemplateParameters(), *P->Args);
- return true;
+ return nullptr;
}
}
@@ -2416,13 +2415,27 @@ bool Sema::InstantiateClassTemplateSpecialization(
Pattern = OrigTemplate->getTemplatedDecl();
}
- bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec,
- Pattern,
- getTemplateInstantiationArgs(ClassTemplateSpec),
- TSK,
- Complain);
+ return Pattern;
+}
- return Result;
+bool Sema::InstantiateClassTemplateSpecialization(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK, bool Complain) {
+ // Perform the actual instantiation on the canonical declaration.
+ ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
+ ClassTemplateSpec->getCanonicalDecl());
+ if (ClassTemplateSpec->isInvalidDecl())
+ return true;
+
+ CXXRecordDecl *Pattern = getPatternForClassTemplateSpecialization(
+ *this, PointOfInstantiation, ClassTemplateSpec, TSK, Complain);
+ if (!Pattern)
+ return true;
+
+ return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, Pattern,
+ getTemplateInstantiationArgs(ClassTemplateSpec), TSK,
+ Complain);
}
/// \brief Instantiates the definitions of all of the member
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp
index bcdc84e19f..d70e868178 100644
--- a/test/SemaTemplate/alias-templates.cpp
+++ b/test/SemaTemplate/alias-templates.cpp
@@ -244,3 +244,13 @@ namespace redecl {
template<typename = void> using A = int;
A<> a; // ok
}
+
+namespace PR31514 {
+ template<typename T, typename> using EnableTupleSize = T;
+
+ template<typename T> struct tuple_size { static const int value = 0; };
+ template<typename T> struct tuple_size<EnableTupleSize<const T, decltype(tuple_size<T>::value)>> {};
+ template<typename T> struct tuple_size<EnableTupleSize<volatile T, decltype(tuple_size<T>::value)>> {};
+
+ tuple_size<const int> t;
+}
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
index 2275a8b3b7..c25bf68b06 100644
--- a/test/SemaTemplate/deduction.cpp
+++ b/test/SemaTemplate/deduction.cpp
@@ -342,7 +342,7 @@ namespace deduction_substitution_failure {
template<typename T, typename U> struct A {};
template<typename T> struct A<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}
- A<int, int> ai; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}}
+ A<int, int> ai; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}} expected-note {{in instantiation of template class 'deduction_substitution_failure::A<int, int>'}}
template<typename T, typename U> int B; // expected-warning 0-1 {{extension}}
template<typename T> int B<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}