[clang] [Clang] Fix a bug when checking non-dependent constraints (PR #162969)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 10 21:47:16 PDT 2025


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

>From efc31fd3fb460934d5fafa0c56232b3f9da5293e Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sat, 11 Oct 2025 12:12:33 +0800
Subject: [PATCH 1/2] [Clang] Fix a bug when checking non-dependent constraints

We check the non-dependent constraints early with empty template arguments
when we build a nested requirement. Therefore we cannot assume a non-empty
MLTAL within the Checker.

No release note because this is a regression on trunk.
---
 clang/lib/Sema/SemaConcept.cpp       | 25 +++++++++++++++++--------
 clang/test/SemaTemplate/concepts.cpp | 12 ++++++++++++
 2 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index f4df63c1d2243..13e7960dafdcf 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -604,6 +604,10 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
     return std::nullopt;
   const NormalizedConstraint::OccurenceList &Used =
       Constraint.mappingOccurenceList();
+  // The empty MLTAL situation should only occur when evaluating non-dependent
+  // constraints.
+  if (!MLTAL.getNumSubstitutedLevels())
+    MLTAL.addOuterTemplateArguments(TD, {}, /*Final=*/false);
   SubstitutedOuterMost =
       llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
   unsigned Offset = 0;
@@ -623,9 +627,7 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
   if (Offset < SubstitutedOuterMost.size())
     SubstitutedOuterMost.erase(SubstitutedOuterMost.begin() + Offset);
 
-  MLTAL.replaceOutermostTemplateArguments(
-      const_cast<NamedDecl *>(Constraint.getConstraintDecl()),
-      SubstitutedOuterMost);
+  MLTAL.replaceOutermostTemplateArguments(TD, SubstitutedOuterMost);
   return std::move(MLTAL);
 }
 
@@ -956,11 +958,18 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
           ? Constraint.getPackSubstitutionIndex()
           : PackSubstitutionIndex;
 
-  Sema::InstantiatingTemplate _(S, ConceptId->getBeginLoc(),
-                                Sema::InstantiatingTemplate::ConstraintsCheck{},
-                                ConceptId->getNamedConcept(),
-                                MLTAL.getInnermost(),
-                                Constraint.getSourceRange());
+  Sema::InstantiatingTemplate _(
+      S, ConceptId->getBeginLoc(),
+      Sema::InstantiatingTemplate::ConstraintsCheck{},
+      ConceptId->getNamedConcept(),
+      // We may have empty template arguments when checking non-dependent
+      // nested constraint expressions.
+      // In such cases, non-SFINAE errors would have already been diagnosed
+      // during parameter mapping substitution, so the instantiating template
+      // arguments are less useful here.
+      MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
+                                      : ArrayRef<TemplateArgument>{},
+      Constraint.getSourceRange());
 
   unsigned Size = Satisfaction.Details.size();
 
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 768af09afe9e2..a046fc47d1d18 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1404,6 +1404,18 @@ static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
 
 }
 
+namespace case7 {
+
+template <class _Tp, class _Up>
+concept __same_as_impl = __is_same(_Tp, _Up);
+template <class _Tp, class _Up>
+concept same_as = __same_as_impl<_Tp, _Up>;
+template <typename>
+concept IsEntitySpec =
+  requires { requires same_as<void, void>; };
+
+}
+
 }
 
 namespace GH162125 {

>From b9d2c1a4c45d37985e0de31f46d8690def18eb3c Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sat, 11 Oct 2025 12:46:31 +0800
Subject: [PATCH 2/2] Add the missed isInvalid() check

---
 clang/lib/Sema/SemaConcept.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 13e7960dafdcf..9cbd1bd772f6f 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -958,7 +958,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
           ? Constraint.getPackSubstitutionIndex()
           : PackSubstitutionIndex;
 
-  Sema::InstantiatingTemplate _(
+  Sema::InstantiatingTemplate InstTemplate(
       S, ConceptId->getBeginLoc(),
       Sema::InstantiatingTemplate::ConstraintsCheck{},
       ConceptId->getNamedConcept(),
@@ -970,6 +970,8 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
       MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
                                       : ArrayRef<TemplateArgument>{},
       Constraint.getSourceRange());
+  if (InstTemplate.isInvalid())
+    return ExprError();
 
   unsigned Size = Satisfaction.Details.size();
 



More information about the cfe-commits mailing list