Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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()) {
Expand Down
18 changes: 18 additions & 0 deletions clang/test/SemaTemplate/concepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down