erichkeane created this revision. erichkeane added reviewers: clang-language-wg, alexander-shaposhnikov. Herald added a project: All. erichkeane requested review of this revision.
As reported in GH61959, the patch for https://reviews.llvm.org/D146178 regressed some comparisons of non-out-of-line function constraints. This patch fixes it by making sure we skip the list of template arguments from a partial specialization (where they don't really matter!). There was 1 other workaround that was made for checking deduced arguments that this removes part of. Fixes: #61959 https://reviews.llvm.org/D147722 Files: clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/SemaTemplate/concepts.cpp Index: clang/test/SemaTemplate/concepts.cpp =================================================================== --- clang/test/SemaTemplate/concepts.cpp +++ clang/test/SemaTemplate/concepts.cpp @@ -825,3 +825,34 @@ template<C<int> U> friend constexpr auto decltype(L<int>)::operator()() const; }; } // namespace TemplateInsideNonTemplateClass + +namespace GH61959 { +template <typename T0> +concept C = (sizeof(T0) >= 4); + +template<typename...> +struct Orig { }; + +template<typename T> +struct Orig<T> { + template<typename> requires C<T> + void f() { } + + template<typename> requires true + void f() { } +}; + +template <typename...> struct Mod {}; + +template <typename T1, typename T2> +struct Mod<T1, T2> { + template <typename> requires C<T1> + constexpr static int f() { return 1; } + + template <typename> requires C<T2> + constexpr static int f() { return 2; } +}; + +static_assert(Mod<int, char>::f<double>() == 1); +static_assert(Mod<char, int>::f<double>() == 2); +} Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -310,6 +310,16 @@ if (const auto *VarTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(CurDecl)) { R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization); + } else if (const auto *PartialClassTemplSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(CurDecl)) { + // We don't want the arguments from the Partial Specialization, since + // anything instantiating here cannot access the arguments from the + // specialized template anyway, so any substitution we would do with these + // partially specialized arguments would 'wrong' and confuse constraint + // instantiation. We only do this in the case of a constraint check, since + // code elsewhere actually uses these and replaces them later with what + // they mean. + R = Response::UseNextDecl(PartialClassTemplSpec); } else if (const auto *ClassTemplSpec = dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) { R = HandleClassTemplateSpec(ClassTemplSpec, Result, Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2851,11 +2851,6 @@ VarTemplatePartialSpecializationDecl *Spec) { return !Spec->isClassScopeExplicitSpecialization(); } -template <> -bool DeducedArgsNeedReplacement<ClassTemplatePartialSpecializationDecl>( - ClassTemplatePartialSpecializationDecl *Spec) { - return !Spec->isClassScopeExplicitSpecialization(); -} template <typename TemplateDeclT> static Sema::TemplateDeductionResult
Index: clang/test/SemaTemplate/concepts.cpp =================================================================== --- clang/test/SemaTemplate/concepts.cpp +++ clang/test/SemaTemplate/concepts.cpp @@ -825,3 +825,34 @@ template<C<int> U> friend constexpr auto decltype(L<int>)::operator()() const; }; } // namespace TemplateInsideNonTemplateClass + +namespace GH61959 { +template <typename T0> +concept C = (sizeof(T0) >= 4); + +template<typename...> +struct Orig { }; + +template<typename T> +struct Orig<T> { + template<typename> requires C<T> + void f() { } + + template<typename> requires true + void f() { } +}; + +template <typename...> struct Mod {}; + +template <typename T1, typename T2> +struct Mod<T1, T2> { + template <typename> requires C<T1> + constexpr static int f() { return 1; } + + template <typename> requires C<T2> + constexpr static int f() { return 2; } +}; + +static_assert(Mod<int, char>::f<double>() == 1); +static_assert(Mod<char, int>::f<double>() == 2); +} Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -310,6 +310,16 @@ if (const auto *VarTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(CurDecl)) { R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization); + } else if (const auto *PartialClassTemplSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(CurDecl)) { + // We don't want the arguments from the Partial Specialization, since + // anything instantiating here cannot access the arguments from the + // specialized template anyway, so any substitution we would do with these + // partially specialized arguments would 'wrong' and confuse constraint + // instantiation. We only do this in the case of a constraint check, since + // code elsewhere actually uses these and replaces them later with what + // they mean. + R = Response::UseNextDecl(PartialClassTemplSpec); } else if (const auto *ClassTemplSpec = dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) { R = HandleClassTemplateSpec(ClassTemplSpec, Result, Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2851,11 +2851,6 @@ VarTemplatePartialSpecializationDecl *Spec) { return !Spec->isClassScopeExplicitSpecialization(); } -template <> -bool DeducedArgsNeedReplacement<ClassTemplatePartialSpecializationDecl>( - ClassTemplatePartialSpecializationDecl *Spec) { - return !Spec->isClassScopeExplicitSpecialization(); -} template <typename TemplateDeclT> static Sema::TemplateDeductionResult
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits