[clang] 136c406 - [Clang] Give empty template parameter mapping an empty MLTAL (#164051)

via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 20 03:32:17 PDT 2025


Author: Younan Zhang
Date: 2025-10-20T18:32:14+08:00
New Revision: 136c40667ebc43ffc13b32cb2227dd69a7d85b81

URL: https://github.com/llvm/llvm-project/commit/136c40667ebc43ffc13b32cb2227dd69a7d85b81
DIFF: https://github.com/llvm/llvm-project/commit/136c40667ebc43ffc13b32cb2227dd69a7d85b81.diff

LOG: [Clang] Give empty template parameter mapping an empty MLTAL (#164051)

There are cases where atomic constraints are independent of template
parameters, yet we still have a template parameter mapping.

We don't bother translating template arguments for them. Note that we
retain an empty parameter mapping rather than none at all, as the former
may improve cache hit rates (We don't profile MLTAL but profile the
empty template argument list instead.)

This is a regression on trunk, so there's no release note.

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 829bd87599ac9..f77fca2a69e00 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -570,6 +570,11 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
   if (!Constraint.hasParameterMapping())
     return std::move(MLTAL);
 
+  // The mapping is empty, meaning no template arguments are needed for
+  // evaluation.
+  if (Constraint.getParameterMapping().empty())
+    return MultiLevelTemplateArgumentList();
+
   TemplateDeductionInfo Info(Constraint.getBeginLoc());
   Sema::InstantiatingTemplate Inst(
       S, Constraint.getBeginLoc(),
@@ -2017,8 +2022,13 @@ void SubstituteParameterMappings::buildParameterMapping(
       SemaRef.MarkUsedTemplateParameters(Args->arguments(),
                                          /*Depth=*/0, OccurringIndices);
   }
+  unsigned Size = OccurringIndices.count();
+  // When the constraint is independent of any template parameters,
+  // we build an empty mapping so that we can distinguish these cases
+  // from cases where no mapping exists at all, e.g. when there are only atomic
+  // constraints.
   TemplateArgumentLoc *TempArgs =
-      new (SemaRef.Context) TemplateArgumentLoc[OccurringIndices.count()];
+      new (SemaRef.Context) TemplateArgumentLoc[Size];
   llvm::SmallVector<NamedDecl *> UsedParams;
   for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
     SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
@@ -2039,7 +2049,6 @@ void SubstituteParameterMappings::buildParameterMapping(
       TemplateParams->getLAngleLoc(), UsedParams,
       /*RAngleLoc=*/SourceLocation(),
       /*RequiresClause=*/nullptr);
-  unsigned Size = OccurringIndices.count();
   N.updateParameterMapping(
       std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
       MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
@@ -2050,6 +2059,10 @@ bool SubstituteParameterMappings::substitute(
   if (!N.hasParameterMapping())
     buildParameterMapping(N);
 
+  // If the parameter mapping is empty, there is nothing to substitute.
+  if (N.getParameterMapping().empty())
+    return false;
+
   SourceLocation InstLocBegin, InstLocEnd;
   llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
   if (Arguments.empty()) {

diff  --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index a54bc02226058..5b0f3d39d9648 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1441,6 +1441,24 @@ void main() { Feeder<int>{}.feed<Cat<int>>(); }
 
 }
 
+namespace case9 {
+
+template <typename>
+concept a = requires { requires true; };
+template <typename T>
+concept b = a<typename T::EntitySpec>;
+template <typename T>
+concept c = requires { b<T>; };
+template <typename T>
+  requires c<T>
+struct s;
+template <typename> constexpr bool f() { return true; }
+template <typename T> constexpr bool d = f<T>();
+struct s2;
+static_assert(d<s<s2>>);
+
+}
+
 }
 
 namespace GH162125 {


        


More information about the cfe-commits mailing list