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 *Spec) { - return !Spec->isClassScopeExplicitSpecialization(); -} template static Sema::TemplateDeductionResult 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(CurDecl)) { R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization); + } else if (const auto *PartialClassTemplSpec = + dyn_cast(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(CurDecl)) { R = HandleClassTemplateSpec(ClassTemplSpec, Result, Index: clang/test/SemaTemplate/concepts.cpp =================================================================== --- clang/test/SemaTemplate/concepts.cpp +++ clang/test/SemaTemplate/concepts.cpp @@ -825,3 +825,34 @@ template U> friend constexpr auto decltype(L)::operator()() const; }; } // namespace TemplateInsideNonTemplateClass + +namespace GH61959 { +template +concept C = (sizeof(T0) >= 4); + +template +struct Orig { }; + +template +struct Orig { + template requires C + void f() { } + + template requires true + void f() { } +}; + +template struct Mod {}; + +template +struct Mod { + template requires C + constexpr static int f() { return 1; } + + template requires C + constexpr static int f() { return 2; } +}; + +static_assert(Mod::f() == 1); +static_assert(Mod::f() == 2); +}