Skip to content

Commit 3604567

Browse files
committed
Deal with parameters used, but not referenced by an atomic constraint
These parameters should not affect subsumption. This force us to maintain two occurence list for each atomic constraint.
1 parent 7ecf194 commit 3604567

File tree

5 files changed

+79
-26
lines changed

5 files changed

+79
-26
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12776,6 +12776,18 @@ class Sema final : public SemaBase {
1277612776
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
1277712777
unsigned Depth, llvm::SmallBitVector &Used);
1277812778

12779+
/// Mark which template parameters are named in a given expression.
12780+
///
12781+
/// Unlike MarkUsedTemplateParameters, this excludes parameter that
12782+
/// are used but not directly named by an expression - ie it excludes
12783+
/// any template parameter that denotes the type of a referenced NTTP.
12784+
///
12785+
/// \param Used a bit vector whose elements will be set to \c true
12786+
/// to indicate when the corresponding template parameter will be
12787+
/// deduced.
12788+
void MarkUsedTemplateParametersForSubsumptionParameterMapping(
12789+
const Expr *E, unsigned Depth, llvm::SmallBitVector &Used);
12790+
1277912791
/// Mark which template parameters can be deduced from a given
1278012792
/// template argument list.
1278112793
///

clang/include/clang/Sema/SemaConcept.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,15 @@ struct NormalizedConstraint {
6161
unsigned Kind : 5;
6262
unsigned Placeholder : 1;
6363
unsigned PackSubstitutionIndex : 26;
64-
// Indexes and Args are part of the common initial sequences
65-
// of constraints that do have a mapping.
64+
// Indexes, IndexesForSubsumption, and Args are part of the common initial
65+
// sequences of constraints that do have a mapping.
66+
67+
// Indexes of the parameters used in a constraint expression.
6668
OccurenceList Indexes;
69+
// Indexes of the parameters named directly in a constraint expression.
70+
// FIXME: we should try to reduce the size of this struct?
71+
OccurenceList IndexesForSubsumption;
72+
6773
TemplateArgumentLoc *Args;
6874
TemplateParameterList *ParamList;
6975
ExprOrConcept ConstraintExpr;
@@ -77,6 +83,7 @@ struct NormalizedConstraint {
7783
unsigned FoldOperator : 1;
7884
unsigned Placeholder : 26;
7985
OccurenceList Indexes;
86+
OccurenceList IndexesForSubsumption;
8087
TemplateArgumentLoc *Args;
8188
TemplateParameterList *ParamList;
8289
const Expr *Pattern;
@@ -119,6 +126,7 @@ struct NormalizedConstraint {
119126
/*Placeholder=*/0,
120127
PackIndex.toInternalRepresentation(),
121128
/*Indexes=*/{},
129+
/*IndexesForSubsumption=*/{},
122130
/*Args=*/nullptr,
123131
/*ParamList=*/nullptr,
124132
ConstraintExpr,
@@ -131,6 +139,7 @@ struct NormalizedConstraint {
131139
llvm::to_underlying(OpKind),
132140
/*Placeholder=*/0,
133141
/*Indexes=*/{},
142+
/*IndexesForSubsumption=*/{},
134143
/*Args=*/nullptr,
135144
/*ParamList=*/nullptr,
136145
Pattern,
@@ -145,6 +154,7 @@ struct NormalizedConstraint {
145154
: ConceptId{{llvm::to_underlying(ConstraintKind::ConceptId),
146155
/*Placeholder=*/0, PackIndex.toInternalRepresentation(),
147156
/*Indexes=*/{},
157+
/*IndexesForSubsumption=*/{},
148158
/*Args=*/nullptr, /*ParamList=*/nullptr, ConceptId,
149159
ConstraintDecl},
150160
SubConstraint,
@@ -166,6 +176,11 @@ struct NormalizedConstraint {
166176
return Atomic.Indexes;
167177
}
168178

179+
const OccurenceList &mappingOccurenceListForSubsumption() const {
180+
assert(hasParameterMapping() && "This constraint has no parameter mapping");
181+
return Atomic.IndexesForSubsumption;
182+
}
183+
169184
llvm::MutableArrayRef<TemplateArgumentLoc> getParameterMapping() const {
170185
return {Atomic.Args, Atomic.Indexes.count()};
171186
}
@@ -175,11 +190,16 @@ struct NormalizedConstraint {
175190
}
176191

177192
void updateParameterMapping(OccurenceList Indexes,
193+
OccurenceList IndexesForSubsumption,
178194
llvm::MutableArrayRef<TemplateArgumentLoc> Args,
179195
TemplateParameterList *ParamList) {
180196
assert(getKind() != ConstraintKind::Compound);
181197
assert(Indexes.count() == Args.size());
182-
Atomic.Indexes = Indexes;
198+
assert(IndexesForSubsumption.size() == Indexes.size());
199+
assert((Indexes & IndexesForSubsumption) == Indexes);
200+
201+
Atomic.IndexesForSubsumption = std::move(IndexesForSubsumption);
202+
Atomic.Indexes = std::move(Indexes);
183203
Atomic.Args = Args.data();
184204
Atomic.ParamList = ParamList;
185205
}
@@ -198,10 +218,17 @@ struct NormalizedConstraint {
198218
llvm::ArrayRef<TemplateArgumentLoc> OtherParameterMapping =
199219
Other.getParameterMapping();
200220

221+
const OccurenceList &Indexes = mappingOccurenceListForSubsumption();
222+
const OccurenceList &OtherIndexes =
223+
Other.mappingOccurenceListForSubsumption();
224+
201225
if (ParameterMapping.size() != OtherParameterMapping.size())
202226
return false;
203-
204227
for (unsigned I = 0, S = ParameterMapping.size(); I < S; ++I) {
228+
if (Indexes[I] != OtherIndexes[I])
229+
return false;
230+
if (!Indexes[I])
231+
continue;
205232
llvm::FoldingSetNodeID IDA, IDB;
206233
C.getCanonicalTemplateArgument(ParameterMapping[I].getArgument())
207234
.Profile(IDA, C);
@@ -296,6 +323,7 @@ class NormalizedConstraintWithParamMapping : public NormalizedConstraint {
296323
using NormalizedConstraint::hasMatchingParameterMapping;
297324
using NormalizedConstraint::hasParameterMapping;
298325
using NormalizedConstraint::mappingOccurenceList;
326+
using NormalizedConstraint::mappingOccurenceListForSubsumption;
299327
using NormalizedConstraint::updateParameterMapping;
300328

301329
const NamedDecl *getConstraintDecl() const { return Atomic.ConstraintDecl; }

clang/lib/Sema/SemaConcept.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,25 +1919,28 @@ void SubstituteParameterMappings::buildParameterMapping(
19191919
cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
19201920

19211921
llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1922+
llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
19221923

19231924
if (N.getKind() == NormalizedConstraint::ConstraintKind::Atomic) {
19241925
SemaRef.MarkUsedTemplateParameters(
19251926
static_cast<AtomicConstraint &>(N).getConstraintExpr(),
19261927
/*OnlyDeduced=*/false,
19271928
/*Depth=*/0, OccurringIndices);
1929+
1930+
SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
1931+
static_cast<AtomicConstraint &>(N).getConstraintExpr(),
1932+
/*Depth=*/0, OccurringIndicesForSubsumption);
1933+
19281934
} else if (N.getKind() ==
19291935
NormalizedConstraint::ConstraintKind::FoldExpanded) {
19301936
SemaRef.MarkUsedTemplateParameters(
19311937
static_cast<FoldExpandedConstraint &>(N).getPattern(),
19321938
/*OnlyDeduced=*/false,
19331939
/*Depth=*/0, OccurringIndices);
1934-
} else if (N.getKind() == NormalizedConstraint::ConstraintKind::ConceptId) {
1935-
auto *Args = static_cast<ConceptIdConstraint &>(N)
1936-
.getConceptId()
1937-
->getTemplateArgsAsWritten();
1938-
if (Args)
1939-
SemaRef.MarkUsedTemplateParameters(Args->arguments(),
1940-
/*Depth=*/0, OccurringIndices);
1940+
1941+
SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
1942+
static_cast<FoldExpandedConstraint &>(N).getPattern(),
1943+
/*Depth=*/0, OccurringIndicesForSubsumption);
19411944
}
19421945
TemplateArgumentLoc *TempArgs =
19431946
new (SemaRef.Context) TemplateArgumentLoc[OccurringIndices.count()];
@@ -1962,7 +1965,7 @@ void SubstituteParameterMappings::buildParameterMapping(
19621965
/*RAngleLoc=*/SourceLocation(),
19631966
/*RequiresClause=*/nullptr);
19641967
N.updateParameterMapping(
1965-
OccurringIndices,
1968+
std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
19661969
MutableArrayRef<TemplateArgumentLoc>{TempArgs, OccurringIndices.count()},
19671970
UsedList);
19681971
}
@@ -2023,7 +2026,8 @@ bool SubstituteParameterMappings::substitute(
20232026

20242027
MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
20252028
CTAI.SugaredConverted.size());
2026-
N.updateParameterMapping(N.mappingOccurenceList(), Mapping,
2029+
N.updateParameterMapping(N.mappingOccurenceList(),
2030+
N.mappingOccurenceListForSubsumption(), Mapping,
20272031
N.getUsedTemplateParamList());
20282032
return false;
20292033
}
@@ -2481,10 +2485,13 @@ auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
24812485
ID.AddBoolean(Ori->hasParameterMapping());
24822486
if (Ori->hasParameterMapping()) {
24832487
const auto &Mapping = Ori->getParameterMapping();
2484-
for (const TemplateArgumentLoc &TAL : Mapping) {
2485-
SemaRef.getASTContext()
2486-
.getCanonicalTemplateArgument(TAL.getArgument())
2487-
.Profile(ID, SemaRef.getASTContext());
2488+
const NormalizedConstraint::OccurenceList &Indexes =
2489+
Ori->mappingOccurenceListForSubsumption();
2490+
for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2491+
if (Indexes[Idx])
2492+
SemaRef.getASTContext()
2493+
.getCanonicalTemplateArgument(TAL.getArgument())
2494+
.Profile(ID, SemaRef.getASTContext());
24882495
}
24892496
}
24902497
auto It = Elems.find(ID);

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6702,10 +6702,11 @@ namespace {
67026702
struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
67036703
llvm::SmallBitVector &Used;
67046704
unsigned Depth;
6705+
bool VisitDeclRefTypes = true;
67056706

6706-
MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used,
6707-
unsigned Depth)
6708-
: Used(Used), Depth(Depth) { }
6707+
MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used, unsigned Depth,
6708+
bool VisitDeclRefTypes = true)
6709+
: Used(Used), Depth(Depth), VisitDeclRefTypes(VisitDeclRefTypes) {}
67096710

67106711
bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
67116712
if (T->getDepth() == Depth)
@@ -6726,7 +6727,8 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
67266727
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
67276728
if (NTTP->getDepth() == Depth)
67286729
Used[NTTP->getIndex()] = true;
6729-
DynamicRecursiveASTVisitor::TraverseType(E->getType());
6730+
if (VisitDeclRefTypes)
6731+
DynamicRecursiveASTVisitor::TraverseType(E->getType());
67306732
return true;
67316733
}
67326734

@@ -7176,6 +7178,13 @@ Sema::MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
71767178
::MarkUsedTemplateParameters(Context, E, OnlyDeduced, Depth, Used);
71777179
}
71787180

7181+
void Sema::MarkUsedTemplateParametersForSubsumptionParameterMapping(
7182+
const Expr *E, unsigned Depth, llvm::SmallBitVector &Used) {
7183+
MarkUsedTemplateParameterVisitor(Used, Depth, /*VisitDeclRefTypes=*/false)
7184+
.TraverseStmt(const_cast<Expr *>(E));
7185+
return;
7186+
}
7187+
71797188
void
71807189
Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
71817190
bool OnlyDeduced, unsigned Depth,

clang/test/SemaTemplate/instantiate-template-argument.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,17 @@ constexpr int foo() requires C2<int, W> { return 1; } // #cand1
1313
// sizeof(U) >= 4 [U = W (decltype(int{}))]
1414

1515
template<char X>
16-
// expected-note@+1{{candidate function}}
1716
constexpr int foo() requires C1<1, X> && true { return 2; } // #cand2
1817
// sizeof(U) >= 4 [U = X (decltype(1))]
1918

2019
static_assert(foo<'a'>() == 2);
21-
// expected-error@-1 {{call to 'foo' is ambiguous}}
22-
// expected-note@#cand1 {{candidate function}}
23-
// expected-note@#cand2 {{candidate function}}
20+
2421

2522
template<char Z>
2623
constexpr int foo() requires C2<long long, Z> && true { return 3; } // #cand3
2724
// sizeof(U) >= 4 [U = Z (decltype(long long{}))]
2825

2926
static_assert(foo<'a'>() == 3);
3027
// expected-error@-1{{call to 'foo' is ambiguous}}
31-
// expected-note@#cand1 {{candidate function}}
28+
// expected-note@#cand2 {{candidate function}}
3229
// expected-note@#cand3 {{candidate function}}

0 commit comments

Comments
 (0)