Skip to content
Merged
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
9 changes: 8 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -12065,6 +12065,13 @@ class Sema final : public SemaBase {
bool UpdateArgsWithConversions = true,
bool *ConstraintsNotSatisfied = nullptr);

bool CheckTemplateArgumentList(
TemplateDecl *Template, TemplateParameterList *Params,
SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true,
bool *ConstraintsNotSatisfied = nullptr);

bool CheckTemplateTypeArgument(
TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
Expand Down Expand Up @@ -13402,7 +13409,7 @@ class Sema final : public SemaBase {
TemplateArgumentListInfo &Outputs);

bool SubstTemplateArgumentsInParameterMapping(
ArrayRef<TemplateArgumentLoc> Args,
ArrayRef<TemplateArgumentLoc> Args, SourceLocation BaseLoc,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateArgumentListInfo &Out);

Expand Down
23 changes: 13 additions & 10 deletions clang/include/clang/Sema/SemaConcept.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct NormalizedConstraint {
unsigned PackSubstitutionIndex : 26;
llvm::SmallBitVector Indexes;
TemplateArgumentLoc *Args;
TemplateParameterList *ParamList;
ExprOrConcept ConstraintExpr;
const NamedDecl *ConstraintDecl;
};
Expand All @@ -81,6 +82,7 @@ struct NormalizedConstraint {
unsigned Placeholder : 26;
OccurenceList Indexes;
TemplateArgumentLoc *Args;
TemplateParameterList *ParamList;
const Expr *Pattern;
NormalizedConstraint *Constraint;
};
Expand Down Expand Up @@ -118,6 +120,7 @@ struct NormalizedConstraint {
PackIndex.toInternalRepresentation(),
/*Indexes=*/{},
/*Args=*/nullptr,
/*ParamList=*/nullptr,
ConstraintExpr,
ConstraintDecl} {}

Expand All @@ -128,6 +131,7 @@ struct NormalizedConstraint {
/*Placeholder=*/0,
/*Indexes=*/{},
/*Args=*/nullptr,
/*ParamList=*/nullptr,
Pattern,
Constraint} {}

Expand All @@ -138,7 +142,8 @@ struct NormalizedConstraint {
: ConceptId{{llvm::to_underlying(ConstraintKind::ConceptId),
/*Placeholder=*/0, PackIndex.toInternalRepresentation(),
/*Indexes=*/{},
/*Args=*/nullptr, ConceptId, ConstraintDecl},
/*Args=*/nullptr, /*ParamList=*/nullptr, ConceptId,
ConstraintDecl},
SubConstraint} {}

NormalizedConstraint(NormalizedConstraint *LHS, CompoundConstraintKind CCK,
Expand All @@ -160,15 +165,18 @@ struct NormalizedConstraint {
return {Atomic.Args, Atomic.Indexes.count()};
}

void InitParameterMapping(TemplateParameterList *TemplateParams, const Expr *,
const ASTTemplateArgumentListInfo *ArgsAsWritten);
TemplateParameterList *getUsedTemplateParamList() const {
return Atomic.ParamList;
}

void updateParameterMapping(OccurenceList Indexes,
llvm::MutableArrayRef<TemplateArgumentLoc> Args) {
llvm::MutableArrayRef<TemplateArgumentLoc> Args,
TemplateParameterList *ParamList) {
assert(getKind() != ConstraintKind::Compound);
assert(Indexes.count() == Args.size());
Atomic.Indexes = Indexes;
Atomic.Args = Args.data();
Atomic.ParamList = ParamList;
}

bool hasMatchingParameterMapping(ASTContext &C,
Expand Down Expand Up @@ -283,6 +291,7 @@ class NormalizedConstraintWithParamMapping : public NormalizedConstraint {
using NormalizedConstraint::hasParameterMapping;
using NormalizedConstraint::mappingOccurenceList;
using NormalizedConstraint::updateParameterMapping;
using NormalizedConstraint::getUsedTemplateParamList;

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

Expand All @@ -307,12 +316,6 @@ class AtomicConstraint : public NormalizedConstraintWithParamMapping {
const Expr *getConstraintExpr() const {
return cast<const Expr *>(Atomic.ConstraintExpr);
}

void InitParameterMapping(const ASTTemplateArgumentListInfo *ArgsAsWritten) {
NormalizedConstraint::InitParameterMapping(
cast<TemplateDecl>(Atomic.ConstraintDecl)->getTemplateParameters(),
getConstraintExpr(), ArgsAsWritten);
}
};

class FoldExpandedConstraint : public NormalizedConstraint {
Expand Down
107 changes: 76 additions & 31 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,24 +377,36 @@ SubstitutionInTemplateArguments(
? Constraint.getPackSubstitutionIndex()
: PackSubstitutionIndex);
if (S.SubstTemplateArgumentsInParameterMapping(
Constraint.getParameterMapping(), MLTAL, SubstArgs) ||
Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
SubstArgs) ||
Trap.hasErrorOccurred())
return std::nullopt;
Sema::CheckTemplateArgumentInfo CTAI;
auto *TD = const_cast<TemplateDecl *>(
cast<TemplateDecl>(Constraint.getConstraintDecl()));
if (S.CheckTemplateArgumentList(TD, Constraint.getUsedTemplateParamList(),
TD->getLocation(), SubstArgs,
/*DefaultArguments=*/{},
/*PartialTemplateArgs=*/false, CTAI))
return std::nullopt;
NormalizedConstraint::OccurenceList Used =
Constraint.mappingOccurenceList();
SubstitutedOuterMost =
llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
for (unsigned I = 0, MappedIndex = 0; I < SubstArgs.size(); I++)
if (I < Used.size() && Used[I]) {
for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
TemplateArgument Arg;
if (Used[I])
// SubstitutedOuterMost[I].dump();
// SubstArgs[MappedIndex].getArgument().dump();
TemplateArgument Arg = S.Context.getCanonicalTemplateArgument(
SubstArgs[MappedIndex++].getArgument());
if (I < SubstitutedOuterMost.size())
SubstitutedOuterMost[I] = Arg;
else
SubstitutedOuterMost.push_back(Arg);
}
// Arg = S.Context.getCanonicalTemplateArgument(
// SubstArgs[MappedIndex++].getArgument());
Arg = S.Context.getCanonicalTemplateArgument(
CTAI.SugaredConverted[MappedIndex++]);
if (I < SubstitutedOuterMost.size())
SubstitutedOuterMost[I] = Arg;
else
SubstitutedOuterMost.push_back(Arg);
}
MLTAL.replaceOutermostTemplateArguments(
const_cast<NamedDecl *>(Constraint.getConstraintDecl()),
SubstitutedOuterMost);
Expand Down Expand Up @@ -681,7 +693,7 @@ static bool calculateConstraintSatisfaction(
Ok = calculateConstraintSatisfaction(S, Constraint.getRHS(), Template,
TemplateNameLoc, MLTAL, Satisfaction,
PackSubstitutionIndex);
if(Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors)
if (Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors)
Satisfaction.Details.erase(Satisfaction.Details.begin() + EffectiveDetailEndIndex,
Satisfaction.Details.end());
return Ok;
Expand Down Expand Up @@ -1574,26 +1586,37 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
/*OnlyDeduced=*/false,
/*Depth=*/0, OccurringIndices);
} else if (N.getKind() == NormalizedConstraint::ConstraintKind::ConceptId) {
auto Args = static_cast<ConceptIdConstraint &>(N)
.getConceptId()
->getTemplateArgsAsWritten();
auto *Args = static_cast<ConceptIdConstraint &>(N)
.getConceptId()
->getTemplateArgsAsWritten();
if (Args)
S.MarkUsedTemplateParameters(Args->arguments(),
/*Depth=*/0, OccurringIndices);
}
TemplateArgumentLoc *TempArgs =
new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
llvm::SmallVector<NamedDecl *> UsedParams;
for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
? ArgsAsWritten->arguments()[I].getLocation()
: SourceLocation();
if (OccurringIndices[I])
new (&(TempArgs)[J++]) TemplateArgumentLoc(
S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I], Loc));
if (OccurringIndices[I]) {
NamedDecl *Param = TemplateParams->begin()[I];
new (&(TempArgs)[J])
TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(Param, Loc));
UsedParams.push_back(Param);
J++;
}
}
auto *UsedList = TemplateParameterList::Create(
S.Context, TemplateParams->getTemplateLoc(),
TemplateParams->getLAngleLoc(), UsedParams,
/*RAngleLoc=*/SourceLocation(),
/*RequiresClause=*/nullptr);
N.updateParameterMapping(OccurringIndices,
MutableArrayRef<TemplateArgumentLoc>{
TempArgs, OccurringIndices.count()});
TempArgs, OccurringIndices.count()},
UsedList);
}
SourceLocation InstLocBegin =
ArgsAsWritten->arguments().empty()
Expand All @@ -1610,15 +1633,39 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
{InstLocBegin, InstLocEnd});
if (Inst.isInvalid())
return true;
if (S.SubstTemplateArgumentsInParameterMapping(N.getParameterMapping(), MLTAL,
SubstArgs))
// TransformTemplateArguments is unable to preserve the source location of a
// pack. The SourceLocation is necessary for the instantiation location.
// FIXME: The BaseLoc will be used as the location of the pack expansion,
// which is wrong.
if (S.SubstTemplateArgumentsInParameterMapping(
N.getParameterMapping(), N.getBeginLoc(), MLTAL, SubstArgs))
return true;
Sema::CheckTemplateArgumentInfo CTAI;
auto *TD =
const_cast<TemplateDecl *>(cast<TemplateDecl>(N.getConstraintDecl()));
if (S.CheckTemplateArgumentList(TD, N.getUsedTemplateParamList(),
TD->getLocation(), SubstArgs,
/*DefaultArguments=*/{},
/*PartialTemplateArgs=*/false, CTAI))
return true;
TemplateArgumentLoc *TempArgs =
new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
llvm::copy(SubstArgs.arguments(), TempArgs);
N.updateParameterMapping(
N.mappingOccurenceList(),
MutableArrayRef<TemplateArgumentLoc>(TempArgs, SubstArgs.size()));
new (S.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
SourceLocation Loc;
// If this is an empty pack, we have no corresponding SubstArgs.
if (I < SubstArgs.size())
Loc = SubstArgs.arguments()[I].getLocation();
TempArgs[I] = S.getTrivialTemplateArgumentLoc(CTAI.SugaredConverted[I],
QualType(), Loc);
}
// llvm::copy(SubstArgs.arguments(), TempArgs);
// N.updateParameterMapping(
// N.mappingOccurenceList(),
// MutableArrayRef<TemplateArgumentLoc>(TempArgs, SubstArgs.size()));
N.updateParameterMapping(N.mappingOccurenceList(),
MutableArrayRef<TemplateArgumentLoc>(
TempArgs, CTAI.SugaredConverted.size()),
N.getUsedTemplateParamList());
return false;
}

Expand All @@ -1627,12 +1674,10 @@ substituteParameterMappings(Sema &S, ConceptIdConstraint &N,
const MultiLevelTemplateArgumentList &MLTAL,
const ASTTemplateArgumentListInfo *ArgsAsWritten) {

{
if (N.getConstraintDecl()) {
substituteParameterMappings(
S, static_cast<NormalizedConstraintWithParamMapping &>(N), MLTAL,
ArgsAsWritten);
}
if (N.getConstraintDecl()) {
substituteParameterMappings(
S, static_cast<NormalizedConstraintWithParamMapping &>(N), MLTAL,
ArgsAsWritten);
}
return substituteParameterMappings(S, N.getNormalizedConstraint(), MLTAL,
ArgsAsWritten);
Expand Down
27 changes: 25 additions & 2 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5682,6 +5682,20 @@ bool Sema::CheckTemplateArgumentList(
TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs,
bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI,
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
return CheckTemplateArgumentList(
Template, GetTemplateParameterList(Template), TemplateLoc, TemplateArgs,
DefaultArgs, PartialTemplateArgs, CTAI, UpdateArgsWithConversions,
ConstraintsNotSatisfied);
}

/// Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(
TemplateDecl *Template, TemplateParameterList *Params,
SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions,
bool *ConstraintsNotSatisfied) {

if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = false;
Expand All @@ -5691,8 +5705,6 @@ bool Sema::CheckTemplateArgumentList(
// template.
TemplateArgumentListInfo NewArgs = TemplateArgs;

TemplateParameterList *Params = GetTemplateParameterList(Template);

SourceLocation RAngleLoc = NewArgs.getRAngleLoc();

// C++23 [temp.arg.general]p1:
Expand Down Expand Up @@ -5884,6 +5896,17 @@ bool Sema::CheckTemplateArgumentList(
return true;
}

// For constraint parameter mapping, we have already built a pack in
// TransformTemplateArguments
// if (inParameterMappingSubstitution()) {
// llvm::copy(SugaredArgumentPack, std::back_inserter(CTAI.SugaredConverted));
// SugaredArgumentPack.clear();
// llvm::copy(CanonicalArgumentPack, std::back_inserter(CTAI.CanonicalConverted));
// CanonicalArgumentPack.clear();
// ++Param;
// continue;
// }

CTAI.SugaredConverted.push_back(
TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack));
SugaredArgumentPack.clear();
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6634,6 +6634,7 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
if (NTTP->getDepth() == Depth)
Used[NTTP->getIndex()] = true;
DynamicRecursiveASTVisitor::TraverseType(E->getType());
return true;
}
};
Expand Down Expand Up @@ -6974,10 +6975,13 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
break;

case Type::UnaryTransform:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
cast<UnaryTransformType>(T)->getUnderlyingType(),
OnlyDeduced, Depth, Used);
if (!OnlyDeduced) {
auto *UTT = cast<UnaryTransformType>(T);
auto Next = UTT->getUnderlyingType();
if (Next.isNull())
Next = UTT->getBaseType();
MarkUsedTemplateParameters(Ctx, Next, OnlyDeduced, Depth, Used);
}
break;

case Type::PackExpansion:
Expand Down
Loading