Skip to content

[Clang][CTAD][NFC] Unify transformTemplateParameter() #100865

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 28, 2024
Merged
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
119 changes: 42 additions & 77 deletions clang/lib/Sema/SemaTemplateDeductionGuide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "clang/Sema/Overload.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down Expand Up @@ -241,11 +242,10 @@ NamedDecl *buildDeductionGuide(
}

// Transform a given template type parameter `TTP`.
TemplateTypeParmDecl *
transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC,
TemplateTypeParmDecl *TTP,
MultiLevelTemplateArgumentList &Args,
unsigned NewDepth, unsigned NewIndex) {
TemplateTypeParmDecl *transformTemplateTypeParam(
Sema &SemaRef, DeclContext *DC, TemplateTypeParmDecl *TTP,
MultiLevelTemplateArgumentList &Args, unsigned NewDepth, unsigned NewIndex,
bool EvaluateConstraint) {
// TemplateTypeParmDecl's index cannot be changed after creation, so
// substitute it directly.
auto *NewTTP = TemplateTypeParmDecl::Create(
Expand All @@ -257,7 +257,7 @@ transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC,
: std::nullopt);
if (const auto *TC = TTP->getTypeConstraint())
SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
/*EvaluateConstraint=*/true);
/*EvaluateConstraint=*/EvaluateConstraint);
if (TTP->hasDefaultArgument()) {
TemplateArgumentLoc InstantiatedDefaultArg;
if (!SemaRef.SubstTemplateArgument(
Expand All @@ -284,6 +284,22 @@ transformTemplateParam(Sema &SemaRef, DeclContext *DC,
return NewParam;
}

NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC,
NamedDecl *TemplateParam,
MultiLevelTemplateArgumentList &Args,
unsigned NewIndex, unsigned NewDepth,
bool EvaluateConstraint = true) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
return transformTemplateTypeParam(
SemaRef, DC, TTP, Args, NewDepth, NewIndex,
/*EvaluateConstraint=*/EvaluateConstraint);
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth);
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth);
llvm_unreachable("Unhandled template parameter types");
}

/// Transform to convert portions of a constructor declaration into the
/// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
struct ConvertConstructorToDeductionGuideTransform {
Expand Down Expand Up @@ -358,20 +374,21 @@ struct ConvertConstructorToDeductionGuideTransform {
Args.addOuterRetainedLevel();
if (NestedPattern)
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
NamedDecl *NewParam = transformTemplateParameter(Param, Args);
auto [Depth, Index] = getDepthAndIndex(Param);
NamedDecl *NewParam = transformTemplateParameter(
SemaRef, DC, Param, Args, Index + Depth1IndexAdjustment, Depth - 1);
if (!NewParam)
return nullptr;
// Constraints require that we substitute depth-1 arguments
// to match depths when substituted for evaluation later
Depth1Args.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam));

if (NestedPattern) {
TemplateDeclInstantiator Instantiator(SemaRef, DC,
OuterInstantiationArgs);
Instantiator.setEvaluateConstraints(false);
SemaRef.runWithSufficientStackSpace(NewParam->getLocation(), [&] {
NewParam = cast<NamedDecl>(Instantiator.Visit(NewParam));
});
auto [Depth, Index] = getDepthAndIndex(NewParam);
NewParam = transformTemplateParameter(
SemaRef, DC, NewParam, OuterInstantiationArgs, Index,
Depth - OuterInstantiationArgs.getNumSubstitutedLevels(),
/*EvaluateConstraint=*/false);
}

assert(NewParam->getTemplateDepth() == 0 &&
Expand Down Expand Up @@ -479,25 +496,6 @@ struct ConvertConstructorToDeductionGuideTransform {
}

private:
/// Transform a constructor template parameter into a deduction guide template
/// parameter, rebuilding any internal references to earlier parameters and
/// renumbering as we go.
NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam,
MultiLevelTemplateArgumentList &Args) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
return transformTemplateTypeParam(
SemaRef, DC, TTP, Args, TTP->getDepth() - 1,
Depth1IndexAdjustment + TTP->getIndex());
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
return transformTemplateParam(SemaRef, DC, TTP, Args,
Depth1IndexAdjustment + TTP->getIndex(),
TTP->getDepth() - 1);
auto *NTTP = cast<NonTypeTemplateParmDecl>(TemplateParam);
return transformTemplateParam(SemaRef, DC, NTTP, Args,
Depth1IndexAdjustment + NTTP->getIndex(),
NTTP->getDepth() - 1);
}

QualType transformFunctionProtoType(
TypeLocBuilder &TLB, FunctionProtoTypeLoc TL,
SmallVectorImpl<ParmVarDecl *> &Params,
Expand Down Expand Up @@ -634,26 +632,6 @@ struct ConvertConstructorToDeductionGuideTransform {
}
};

unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
return TTP->getDepth();
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
return TTP->getDepth();
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
return NTTP->getDepth();
llvm_unreachable("Unhandled template parameter types");
}

unsigned getTemplateParameterIndex(NamedDecl *TemplateParam) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
return TTP->getIndex();
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
return TTP->getIndex();
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
return NTTP->getIndex();
llvm_unreachable("Unhandled template parameter types");
}

// Find all template parameters that appear in the given DeducedArgs.
// Return the indices of the template parameters in the TemplateParams.
SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
Expand Down Expand Up @@ -689,8 +667,10 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(

void MarkAppeared(NamedDecl *ND) {
if (llvm::isa<NonTypeTemplateParmDecl, TemplateTypeParmDecl,
TemplateTemplateParmDecl>(ND))
Mark(getTemplateParameterDepth(ND), getTemplateParameterIndex(ND));
TemplateTemplateParmDecl>(ND)) {
auto [Depth, Index] = getDepthAndIndex(ND);
Mark(Depth, Index);
}
}
void Mark(unsigned Depth, unsigned Index) {
if (Index < TemplateParamList->size() &&
Expand Down Expand Up @@ -722,20 +702,6 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
return false;
}

NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC,
NamedDecl *TemplateParam,
MultiLevelTemplateArgumentList &Args,
unsigned NewIndex, unsigned NewDepth) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
return transformTemplateTypeParam(SemaRef, DC, TTP, Args, NewDepth,
NewIndex);
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth);
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth);
llvm_unreachable("Unhandled template parameter types");
}

// Build the associated constraints for the alias deduction guides.
// C++ [over.match.class.deduct]p3.3:
// The associated constraints ([temp.constr.decl]) are the conjunction of the
Expand Down Expand Up @@ -791,7 +757,7 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
NamedDecl *NewParam = transformTemplateParameter(
SemaRef, AliasTemplate->getDeclContext(), TP, Args,
/*NewIndex=*/AdjustedAliasTemplateArgs.size(),
getTemplateParameterDepth(TP) + AdjustDepth);
getDepthAndIndex(TP).first + AdjustDepth);

TemplateArgument NewTemplateArgument =
Context.getInjectedTemplateArg(NewParam);
Expand All @@ -814,10 +780,10 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
Args.setKind(TemplateSubstitutionKind::Rewrite);
Args.addOuterTemplateArguments(TemplateArgsForBuildingRC);
// Rebuild the template parameter with updated depth and index.
NamedDecl *NewParam = transformTemplateParameter(
SemaRef, F->getDeclContext(), TP, Args,
/*NewIndex=*/FirstUndeducedParamIdx,
getTemplateParameterDepth(TP) + AdjustDepth);
NamedDecl *NewParam =
transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,
/*NewIndex=*/FirstUndeducedParamIdx,
getDepthAndIndex(TP).first + AdjustDepth);
FirstUndeducedParamIdx += 1;
assert(TemplateArgsForBuildingRC[Index].isNull());
TemplateArgsForBuildingRC[Index] =
Expand Down Expand Up @@ -919,7 +885,7 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
NamedDecl *NewParam = transformTemplateParameter(
SemaRef, AliasTemplate->getDeclContext(), TP, Args,
/*NewIndex=*/TransformedTemplateArgs.size(),
getTemplateParameterDepth(TP) + AdjustDepth);
getDepthAndIndex(TP).first + AdjustDepth);

TemplateArgument NewTemplateArgument =
Context.getInjectedTemplateArg(NewParam);
Expand Down Expand Up @@ -1081,8 +1047,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
Args.addOuterTemplateArguments(TransformedDeducedAliasArgs);
NamedDecl *NewParam = transformTemplateParameter(
SemaRef, AliasTemplate->getDeclContext(), TP, Args,
/*NewIndex=*/FPrimeTemplateParams.size(),
getTemplateParameterDepth(TP));
/*NewIndex=*/FPrimeTemplateParams.size(), getDepthAndIndex(TP).first);
FPrimeTemplateParams.push_back(NewParam);

TemplateArgument NewTemplateArgument =
Expand All @@ -1101,7 +1066,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime);
NamedDecl *NewParam = transformTemplateParameter(
SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(),
getTemplateParameterDepth(TP));
getDepthAndIndex(TP).first);
FPrimeTemplateParams.push_back(NewParam);

assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&
Expand Down
Loading