Skip to content

Conversation

zyn0217
Copy link
Contributor

@zyn0217 zyn0217 commented Oct 11, 2025

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.

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.
@zyn0217 zyn0217 requested a review from cor3ntin October 11, 2025 04:23
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Oct 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 11, 2025

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/162969.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaConcept.cpp (+17-8)
  • (modified) clang/test/SemaTemplate/concepts.cpp (+12)
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 {

@zyn0217 zyn0217 merged commit 688cbe4 into llvm:main Oct 11, 2025
10 checks passed
@zyn0217 zyn0217 deleted the post-parameter-mapping branch October 11, 2025 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants