diff options
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 75 | ||||
-rw-r--r-- | test/SemaTemplate/alias-templates.cpp | 10 | ||||
-rw-r--r-- | test/SemaTemplate/deduction.cpp | 2 |
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}} |