arphaman created this revision. This patch fixes an an assertion that previously occurred for the following sample:
template <typename InputT, typename OutputT> struct SourceSelectionRequirement { template<typename T> OutputT evaluateSelectionRequirement(InputT &&Value) { } }; template <typename InputT, typename OutputT> OutputT SourceSelectionRequirement<InputT, OutputT>::evaluateSelectionRequirement<void>(InputT &&Value) { return Value; } Clang asserted when it was trying to deduce the function template specialisation for `evaluateSelectionRequirement`, because it was trying to do deduction with the template specialisation `<void>` and `template <typename InputT, typename OutputT>` which have different template depth. I initially fixed the issue by setting the right depth, during the deduction, but wasn't happy with the results (we produced two errors, the second one complained about failed deduction). Thus I changed my approach to the one that's presented in this patch - we can detect if the template parameters are fabricated and then avoid the deduction. This approach avoids the second error while fixing the assertion. It also fixed a redundant error `FIXME` in `SemaTemplate/explicit-specialization-member.cpp` (Basically removed a redundant deduction error). Thanks for taking a look Repository: rL LLVM https://reviews.llvm.org/D37341 Files: lib/Sema/SemaDecl.cpp test/SemaTemplate/deduction-crash.cpp test/SemaTemplate/explicit-specialization-member.cpp Index: test/SemaTemplate/explicit-specialization-member.cpp =================================================================== --- test/SemaTemplate/explicit-specialization-member.cpp +++ test/SemaTemplate/explicit-specialization-member.cpp @@ -38,24 +38,20 @@ template<typename T> template<int N> - void Baz<T>::bar() { // expected-note {{couldn't infer template argument 'N'}} + void Baz<T>::bar() { } - // FIXME: We shouldn't try to match this against a prior declaration if - // template parameter matching failed. template<typename T> - void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}} \ - // expected-error {{no function template matches}} + void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}} } } namespace PR19340 { template<typename T> struct Helper { - template<int N> static void func(const T *m) {} // expected-note {{failed template argument deduction}} + template<int N> static void func(const T *m) {} }; -template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} \ - // expected-error {{no function template matches}} +template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} } namespace SpecLoc { Index: test/SemaTemplate/deduction-crash.cpp =================================================================== --- test/SemaTemplate/deduction-crash.cpp +++ test/SemaTemplate/deduction-crash.cpp @@ -144,3 +144,20 @@ template<typename T, typename U = void> int n<T *>; // expected-error +{{}} expected-note {{}} int k = n<void *>; } + +namespace deduceFunctionSpecializationForInvalidOutOfLineFunction { + +template <typename InputT, typename OutputT> +struct SourceSelectionRequirement { + template<typename T> + OutputT evaluateSelectionRequirement(InputT &&Value) { + } +}; + +template <typename InputT, typename OutputT> +OutputT SourceSelectionRequirement<InputT, OutputT>:: +evaluateSelectionRequirement<void>(InputT &&Value) { // expected-error {{cannot specialize a member of an unspecialized template}} + return Value; +} + +} Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -8195,6 +8195,7 @@ FunctionTemplateDecl *FunctionTemplate = nullptr; bool isMemberSpecialization = false; bool isFunctionTemplateSpecialization = false; + bool HasFabricatedTemplateSpecializationTemplateParams = false; bool isDependentClassScopeExplicitSpecialization = false; bool HasExplicitTemplateArgs = false; @@ -8303,6 +8304,8 @@ } else { // This is a function template specialization. isFunctionTemplateSpecialization = true; + if (Invalid && TemplateParams->getLAngleLoc().isInvalid()) + HasFabricatedTemplateSpecializationTemplateParams = true; // For source fidelity, store all the template param lists. if (TemplateParamLists.size() > 0) NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists); @@ -8874,7 +8877,8 @@ diag::ext_function_specialization_in_class : diag::err_function_specialization_in_class) << NewFD->getDeclName(); - } else if (CheckFunctionTemplateSpecialization(NewFD, + } else if (!HasFabricatedTemplateSpecializationTemplateParams && + CheckFunctionTemplateSpecialization(NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), Previous))
Index: test/SemaTemplate/explicit-specialization-member.cpp =================================================================== --- test/SemaTemplate/explicit-specialization-member.cpp +++ test/SemaTemplate/explicit-specialization-member.cpp @@ -38,24 +38,20 @@ template<typename T> template<int N> - void Baz<T>::bar() { // expected-note {{couldn't infer template argument 'N'}} + void Baz<T>::bar() { } - // FIXME: We shouldn't try to match this against a prior declaration if - // template parameter matching failed. template<typename T> - void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}} \ - // expected-error {{no function template matches}} + void Baz<T>::bar<0>() { // expected-error {{cannot specialize a member of an unspecialized template}} } } namespace PR19340 { template<typename T> struct Helper { - template<int N> static void func(const T *m) {} // expected-note {{failed template argument deduction}} + template<int N> static void func(const T *m) {} }; -template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} \ - // expected-error {{no function template matches}} +template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} } namespace SpecLoc { Index: test/SemaTemplate/deduction-crash.cpp =================================================================== --- test/SemaTemplate/deduction-crash.cpp +++ test/SemaTemplate/deduction-crash.cpp @@ -144,3 +144,20 @@ template<typename T, typename U = void> int n<T *>; // expected-error +{{}} expected-note {{}} int k = n<void *>; } + +namespace deduceFunctionSpecializationForInvalidOutOfLineFunction { + +template <typename InputT, typename OutputT> +struct SourceSelectionRequirement { + template<typename T> + OutputT evaluateSelectionRequirement(InputT &&Value) { + } +}; + +template <typename InputT, typename OutputT> +OutputT SourceSelectionRequirement<InputT, OutputT>:: +evaluateSelectionRequirement<void>(InputT &&Value) { // expected-error {{cannot specialize a member of an unspecialized template}} + return Value; +} + +} Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -8195,6 +8195,7 @@ FunctionTemplateDecl *FunctionTemplate = nullptr; bool isMemberSpecialization = false; bool isFunctionTemplateSpecialization = false; + bool HasFabricatedTemplateSpecializationTemplateParams = false; bool isDependentClassScopeExplicitSpecialization = false; bool HasExplicitTemplateArgs = false; @@ -8303,6 +8304,8 @@ } else { // This is a function template specialization. isFunctionTemplateSpecialization = true; + if (Invalid && TemplateParams->getLAngleLoc().isInvalid()) + HasFabricatedTemplateSpecializationTemplateParams = true; // For source fidelity, store all the template param lists. if (TemplateParamLists.size() > 0) NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists); @@ -8874,7 +8877,8 @@ diag::ext_function_specialization_in_class : diag::err_function_specialization_in_class) << NewFD->getDeclName(); - } else if (CheckFunctionTemplateSpecialization(NewFD, + } else if (!HasFabricatedTemplateSpecializationTemplateParams && + CheckFunctionTemplateSpecialization(NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), Previous))
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits