https://github.com/zyn0217 updated 
https://github.com/llvm/llvm-project/pull/143096

>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 1/2] [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; }
+};
+
+}

>From 91c4b8bbbb92d463bafceb57ea7af114dc52cfb2 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7...@gmail.com>
Date: Fri, 6 Jun 2025 17:58:57 +0800
Subject: [PATCH 2/2] Add tests for gh115838

---
 clang/docs/ReleaseNotes.rst          |  1 +
 clang/test/SemaTemplate/concepts.cpp | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d6b994d36df8a..ae896e98fda7f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -828,6 +828,7 @@ Bug Fixes to C++ Support
 - Clang modules now allow a module and its user to differ on 
TrivialAutoVarInit*
 - Fixed an access checking bug when initializing non-aggregates in default 
arguments (#GH62444), (#GH83608)
 - Fixed a pack substitution bug in deducing class template partial 
specializations. (#GH53609)
+- Fixed an access checking bug when substituting into concepts (#GH115838)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/test/SemaTemplate/concepts.cpp 
b/clang/test/SemaTemplate/concepts.cpp
index abfc14de9bc75..a99df2390a551 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1231,3 +1231,26 @@ template <KnownKind T> struct KnownType {
 };
 
 }
+
+namespace GH115838 {
+
+template<typename T> concept has_x = requires(T t) {{ t.x };};
+
+class Publ { public:    int x = 0; };
+class Priv { private:   int x = 0; };
+class Prot { protected: int x = 0; };
+class Same { protected: int x = 0; };
+
+template<typename T> class D;
+template<typename T> requires ( has_x<T>) class D<T>: public T { public: 
static constexpr bool has = 1; };
+template<typename T> requires (!has_x<T>) class D<T>: public T { public: 
static constexpr bool has = 0; };
+
+// "Same" is identical to "Prot" but queried before used.
+static_assert(!has_x<Same>,  "Protected should be invisible.");
+static_assert(!D<Same>::has, "Protected should be invisible.");
+
+static_assert( D<Publ>::has, "Public should be visible.");
+static_assert(!D<Priv>::has, "Private should be invisible.");
+static_assert(!D<Prot>::has, "Protected should be invisible.");
+
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to