https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/143096
CWG2369 revealed another case where we were SFINAE'ing out the invalid result of substitution, but the expression now makes into evaluation. We switch to the concept specialization's context before we check it. This ensures that we're able to realize the invalid expression earlier, so we can avoid evaluating invalid expression, which is a hard error. >From 020160fde7a3cc13b104a5f5577a8037cf412c66 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Fri, 6 Jun 2025 17:09:08 +0800 Subject: [PATCH] [Clang] Fail the constraint substitution early after CWG2369 CWG2369 revealed another case where we were SFINAE'ing out the invalid result of substitution, but the expression now makes into evaluation. We switch to the concept specialization's context before we check it. This ensures that we're able to realize the invalid expression earlier, so we can avoid evaluating invalid expression, which is a hard error. --- clang/lib/Sema/SemaTemplate.cpp | 2 ++ clang/test/SemaTemplate/concepts.cpp | 31 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1d8fea1d72008..ccc532e1fd3de 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4749,6 +4749,8 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, EnterExpressionEvaluationContext EECtx{ *this, ExpressionEvaluationContext::Unevaluated, CSD}; + ContextRAII CurContext(*this, CSD->getDeclContext(), + /*NewThisContext=*/false); if (!AreArgsDependent && CheckConstraintSatisfaction( NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()), diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 3e50a8bce24af..abfc14de9bc75 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1200,3 +1200,34 @@ bool test_val_types() { } } + +namespace CWG2369_Regression { + +enum class KindEnum { + Unknown = 0, + Foo = 1, +}; + +template <typename T> +concept KnownKind = T::kind() != KindEnum::Unknown; + +template <KnownKind T> struct KnownType; + +struct Type { + KindEnum kind() const; + + static Type f(Type t); + + template <KnownKind T> static KnownType<T> f(T t); + + static void g() { + Type t; + f(t); + } +}; + +template <KnownKind T> struct KnownType { + static constexpr KindEnum kind() { return KindEnum::Foo; } +}; + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits