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

via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 11 01:20:38 PDT 2025


Author: Younan Zhang
Date: 2025-10-11T16:20:34+08:00
New Revision: 688cbe41ca7d40552d201758bbf8f26a7cd20b4b

URL: https://github.com/llvm/llvm-project/commit/688cbe41ca7d40552d201758bbf8f26a7cd20b4b
DIFF: https://github.com/llvm/llvm-project/commit/688cbe41ca7d40552d201758bbf8f26a7cd20b4b.diff

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

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.

Added: 
    

Modified: 
    clang/lib/Sema/SemaConcept.cpp
    clang/test/SemaTemplate/concepts.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index f4df63c1d2243..9cbd1bd772f6f 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,20 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
           ? Constraint.getPackSubstitutionIndex()
           : PackSubstitutionIndex;
 
-  Sema::InstantiatingTemplate _(S, ConceptId->getBeginLoc(),
-                                Sema::InstantiatingTemplate::ConstraintsCheck{},
-                                ConceptId->getNamedConcept(),
-                                MLTAL.getInnermost(),
-                                Constraint.getSourceRange());
+  Sema::InstantiatingTemplate InstTemplate(
+      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());
+  if (InstTemplate.isInvalid())
+    return ExprError();
 
   unsigned Size = Satisfaction.Details.size();
 

diff  --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 1dbb9897f941f..3fbe7c0ac650f 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 {


        


More information about the cfe-commits mailing list