Skip to content

Commit 136c406

Browse files
authored
[Clang] Give empty template parameter mapping an empty MLTAL (llvm#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.
1 parent 9bfaf12 commit 136c406

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

clang/lib/Sema/SemaConcept.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,11 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
570570
if (!Constraint.hasParameterMapping())
571571
return std::move(MLTAL);
572572

573+
// The mapping is empty, meaning no template arguments are needed for
574+
// evaluation.
575+
if (Constraint.getParameterMapping().empty())
576+
return MultiLevelTemplateArgumentList();
577+
573578
TemplateDeductionInfo Info(Constraint.getBeginLoc());
574579
Sema::InstantiatingTemplate Inst(
575580
S, Constraint.getBeginLoc(),
@@ -2017,8 +2022,13 @@ void SubstituteParameterMappings::buildParameterMapping(
20172022
SemaRef.MarkUsedTemplateParameters(Args->arguments(),
20182023
/*Depth=*/0, OccurringIndices);
20192024
}
2025+
unsigned Size = OccurringIndices.count();
2026+
// When the constraint is independent of any template parameters,
2027+
// we build an empty mapping so that we can distinguish these cases
2028+
// from cases where no mapping exists at all, e.g. when there are only atomic
2029+
// constraints.
20202030
TemplateArgumentLoc *TempArgs =
2021-
new (SemaRef.Context) TemplateArgumentLoc[OccurringIndices.count()];
2031+
new (SemaRef.Context) TemplateArgumentLoc[Size];
20222032
llvm::SmallVector<NamedDecl *> UsedParams;
20232033
for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
20242034
SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
@@ -2039,7 +2049,6 @@ void SubstituteParameterMappings::buildParameterMapping(
20392049
TemplateParams->getLAngleLoc(), UsedParams,
20402050
/*RAngleLoc=*/SourceLocation(),
20412051
/*RequiresClause=*/nullptr);
2042-
unsigned Size = OccurringIndices.count();
20432052
N.updateParameterMapping(
20442053
std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
20452054
MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
@@ -2050,6 +2059,10 @@ bool SubstituteParameterMappings::substitute(
20502059
if (!N.hasParameterMapping())
20512060
buildParameterMapping(N);
20522061

2062+
// If the parameter mapping is empty, there is nothing to substitute.
2063+
if (N.getParameterMapping().empty())
2064+
return false;
2065+
20532066
SourceLocation InstLocBegin, InstLocEnd;
20542067
llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
20552068
if (Arguments.empty()) {

clang/test/SemaTemplate/concepts.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,24 @@ void main() { Feeder<int>{}.feed<Cat<int>>(); }
14411441

14421442
}
14431443

1444+
namespace case9 {
1445+
1446+
template <typename>
1447+
concept a = requires { requires true; };
1448+
template <typename T>
1449+
concept b = a<typename T::EntitySpec>;
1450+
template <typename T>
1451+
concept c = requires { b<T>; };
1452+
template <typename T>
1453+
requires c<T>
1454+
struct s;
1455+
template <typename> constexpr bool f() { return true; }
1456+
template <typename T> constexpr bool d = f<T>();
1457+
struct s2;
1458+
static_assert(d<s<s2>>);
1459+
1460+
}
1461+
14441462
}
14451463

14461464
namespace GH162125 {

0 commit comments

Comments
 (0)