-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Refactor: Move CTAD code from SemaTemplate.cpp to a dedicated file, NFC #98524
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
Conversation
… file, NFC Split out the Class Template Argument Deduction (CTAD) related code from SemaTemplate.cpp to a dedicated file. These code has grown significantly, and moving it to a separate file will improve code organization.
@llvm/pr-subscribers-clang Author: Haojian Wu (hokein) ChangesSplit out the deduction guide related code from SemaTemplate.cpp to a dedicated file. These code has grown significantly, and moving it to a separate file will improve code organization. Patch is 127.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/98524.diff 4 Files Affected:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 57994f4033922..48dff1b76cc57 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -560,13 +560,14 @@ class Sema final : public SemaBase {
// 23. Statement Attribute Handling (SemaStmtAttr.cpp)
// 24. C++ Templates (SemaTemplate.cpp)
// 25. C++ Template Argument Deduction (SemaTemplateDeduction.cpp)
- // 26. C++ Template Instantiation (SemaTemplateInstantiate.cpp)
- // 27. C++ Template Declaration Instantiation
+ // 26. C++ Template Deduction Guide (SemaTemplateDeductionGuide.cpp)
+ // 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp)
+ // 28. C++ Template Declaration Instantiation
// (SemaTemplateInstantiateDecl.cpp)
- // 28. C++ Variadic Templates (SemaTemplateVariadic.cpp)
- // 29. Constraints and Concepts (SemaConcept.cpp)
- // 30. Types (SemaType.cpp)
- // 31. FixIt Helpers (SemaFixItUtils.cpp)
+ // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp)
+ // 30. Constraints and Concepts (SemaConcept.cpp)
+ // 31. Types (SemaType.cpp)
+ // 32. FixIt Helpers (SemaFixItUtils.cpp)
/// \name Semantic Analysis
/// Implementations are in Sema.cpp
@@ -11356,6 +11357,10 @@ class Sema final : public SemaBase {
bool &IsMemberSpecialization, bool &Invalid,
bool SuppressDiagnostic = false);
+ /// Returns the template parameter list with all default template argument
+ /// information.
+ TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD);
+
DeclResult CheckClassTemplate(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
@@ -12019,15 +12024,6 @@ class Sema final : public SemaBase {
unsigned TemplateDepth,
const Expr *Constraint);
- /// Declare implicit deduction guides for a class template if we've
- /// not already done so.
- void DeclareImplicitDeductionGuides(TemplateDecl *Template,
- SourceLocation Loc);
-
- FunctionTemplateDecl *DeclareAggregateDeductionGuideFromInitList(
- TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
- SourceLocation Loc);
-
/// Find the failed Boolean condition within a given Boolean
/// constant expression, and describe it with a string.
std::pair<Expr *, std::string> findFailedBooleanCondition(Expr *Cond);
@@ -12580,6 +12576,27 @@ class Sema final : public SemaBase {
//
//
+ /// \name C++ Template Deduction Guide
+ /// Implementations are in SemaTemplateDeductionGuide.cpp
+ ///@{
+
+ /// Declare implicit deduction guides for a class template if we've
+ /// not already done so.
+ void DeclareImplicitDeductionGuides(TemplateDecl *Template,
+ SourceLocation Loc);
+
+ FunctionTemplateDecl *DeclareAggregateDeductionGuideFromInitList(
+ TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
+ SourceLocation Loc);
+
+ ///@}
+
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
+
/// \name C++ Template Instantiation
/// Implementations are in SemaTemplateInstantiate.cpp
///@{
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 980a83d4431aa..5934c8c30daf9 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -82,6 +82,7 @@ add_clang_library(clangSema
SemaSystemZ.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
+ SemaTemplateDeductionGuide.cpp
SemaTemplateInstantiate.cpp
SemaTemplateInstantiateDecl.cpp
SemaTemplateVariadic.cpp
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 29d668e4fd8d7..bb8ec9738f260 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1764,7 +1764,7 @@ static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
// Returns the template parameter list with all default template argument
// information.
-static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) {
+TemplateParameterList *Sema::GetTemplateParameterList(TemplateDecl *TD) {
// Make sure we get the template parameter list from the most
// recent declaration, since that is the only one that is guaranteed to
// have all the default template argument information.
@@ -2173,1385 +2173,6 @@ DeclResult Sema::CheckClassTemplate(
return NewTemplate;
}
-namespace {
-/// Tree transform to "extract" a transformed type from a class template's
-/// constructor to a deduction guide.
-class ExtractTypeForDeductionGuide
- : public TreeTransform<ExtractTypeForDeductionGuide> {
- llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs;
- ClassTemplateDecl *NestedPattern;
- const MultiLevelTemplateArgumentList *OuterInstantiationArgs;
- std::optional<TemplateDeclInstantiator> TypedefNameInstantiator;
-
-public:
- typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
- ExtractTypeForDeductionGuide(
- Sema &SemaRef,
- llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
- ClassTemplateDecl *NestedPattern,
- const MultiLevelTemplateArgumentList *OuterInstantiationArgs)
- : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs),
- NestedPattern(NestedPattern),
- OuterInstantiationArgs(OuterInstantiationArgs) {
- if (OuterInstantiationArgs)
- TypedefNameInstantiator.emplace(
- SemaRef, SemaRef.getASTContext().getTranslationUnitDecl(),
- *OuterInstantiationArgs);
- }
-
- TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
-
- /// Returns true if it's safe to substitute \p Typedef with
- /// \p OuterInstantiationArgs.
- bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) {
- if (!NestedPattern)
- return false;
-
- static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) {
- if (DC->Equals(TargetDC))
- return true;
- while (DC->isRecord()) {
- if (DC->Equals(TargetDC))
- return true;
- DC = DC->getParent();
- }
- return false;
- };
-
- if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl()))
- return true;
- if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext()))
- return true;
- return false;
- }
-
- QualType
- RebuildTemplateSpecializationType(TemplateName Template,
- SourceLocation TemplateNameLoc,
- TemplateArgumentListInfo &TemplateArgs) {
- if (!OuterInstantiationArgs ||
- !isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()))
- return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
- TemplateArgs);
-
- auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
- auto *Pattern = TATD;
- while (Pattern->getInstantiatedFromMemberTemplate())
- Pattern = Pattern->getInstantiatedFromMemberTemplate();
- if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl()))
- return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
- TemplateArgs);
-
- Decl *NewD =
- TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD);
- if (!NewD)
- return QualType();
-
- auto *NewTATD = cast<TypeAliasTemplateDecl>(NewD);
- MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl());
-
- return Base::RebuildTemplateSpecializationType(
- TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
- }
-
- QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
- ASTContext &Context = SemaRef.getASTContext();
- TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
- TypedefNameDecl *Decl = OrigDecl;
- // Transform the underlying type of the typedef and clone the Decl only if
- // the typedef has a dependent context.
- bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext();
-
- // A typedef/alias Decl within the NestedPattern may reference the outer
- // template parameters. They're substituted with corresponding instantiation
- // arguments here and in RebuildTemplateSpecializationType() above.
- // Otherwise, we would have a CTAD guide with "dangling" template
- // parameters.
- // For example,
- // template <class T> struct Outer {
- // using Alias = S<T>;
- // template <class U> struct Inner {
- // Inner(Alias);
- // };
- // };
- if (OuterInstantiationArgs && InDependentContext &&
- TL.getTypePtr()->isInstantiationDependentType()) {
- Decl = cast_if_present<TypedefNameDecl>(
- TypedefNameInstantiator->InstantiateTypedefNameDecl(
- OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl)));
- if (!Decl)
- return QualType();
- MaterializedTypedefs.push_back(Decl);
- } else if (InDependentContext) {
- TypeLocBuilder InnerTLB;
- QualType Transformed =
- TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
- TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, Transformed);
- if (isa<TypeAliasDecl>(OrigDecl))
- Decl = TypeAliasDecl::Create(
- Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
- OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
- else {
- assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
- Decl = TypedefDecl::Create(
- Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
- OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
- }
- MaterializedTypedefs.push_back(Decl);
- }
-
- QualType TDTy = Context.getTypedefType(Decl);
- TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy);
- TypedefTL.setNameLoc(TL.getNameLoc());
-
- return TDTy;
- }
-};
-
-// Build a deduction guide using the provided information.
-//
-// A deduction guide can be either a template or a non-template function
-// declaration. If \p TemplateParams is null, a non-template function
-// declaration will be created.
-NamedDecl *buildDeductionGuide(
- Sema &SemaRef, TemplateDecl *OriginalTemplate,
- TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
- ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
- SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
- llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}) {
- DeclContext *DC = OriginalTemplate->getDeclContext();
- auto DeductionGuideName =
- SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
- OriginalTemplate);
-
- DeclarationNameInfo Name(DeductionGuideName, Loc);
- ArrayRef<ParmVarDecl *> Params =
- TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams();
-
- // Build the implicit deduction guide template.
- auto *Guide =
- CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
- TInfo->getType(), TInfo, LocEnd, Ctor);
- Guide->setImplicit(IsImplicit);
- Guide->setParams(Params);
-
- for (auto *Param : Params)
- Param->setDeclContext(Guide);
- for (auto *TD : MaterializedTypedefs)
- TD->setDeclContext(Guide);
- if (isa<CXXRecordDecl>(DC))
- Guide->setAccess(AS_public);
-
- if (!TemplateParams) {
- DC->addDecl(Guide);
- return Guide;
- }
-
- auto *GuideTemplate = FunctionTemplateDecl::Create(
- SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
- GuideTemplate->setImplicit(IsImplicit);
- Guide->setDescribedFunctionTemplate(GuideTemplate);
-
- if (isa<CXXRecordDecl>(DC))
- GuideTemplate->setAccess(AS_public);
-
- DC->addDecl(GuideTemplate);
- return GuideTemplate;
-}
-
-// Transform a given template type parameter `TTP`.
-TemplateTypeParmDecl *
-transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC,
- TemplateTypeParmDecl *TTP,
- MultiLevelTemplateArgumentList &Args,
- unsigned NewDepth, unsigned NewIndex) {
- // TemplateTypeParmDecl's index cannot be changed after creation, so
- // substitute it directly.
- auto *NewTTP = TemplateTypeParmDecl::Create(
- SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
- NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
- TTP->isParameterPack(), TTP->hasTypeConstraint(),
- TTP->isExpandedParameterPack()
- ? std::optional<unsigned>(TTP->getNumExpansionParameters())
- : std::nullopt);
- if (const auto *TC = TTP->getTypeConstraint())
- SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
- /*EvaluateConstraint=*/true);
- if (TTP->hasDefaultArgument()) {
- TemplateArgumentLoc InstantiatedDefaultArg;
- if (!SemaRef.SubstTemplateArgument(
- TTP->getDefaultArgument(), Args, InstantiatedDefaultArg,
- TTP->getDefaultArgumentLoc(), TTP->getDeclName()))
- NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg);
- }
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP);
- return NewTTP;
-}
-// Similar to above, but for non-type template or template template parameters.
-template <typename NonTypeTemplateOrTemplateTemplateParmDecl>
-NonTypeTemplateOrTemplateTemplateParmDecl *
-transformTemplateParam(Sema &SemaRef, DeclContext *DC,
- NonTypeTemplateOrTemplateTemplateParmDecl *OldParam,
- MultiLevelTemplateArgumentList &Args, unsigned NewIndex,
- unsigned NewDepth) {
- // Ask the template instantiator to do the heavy lifting for us, then adjust
- // the index of the parameter once it's done.
- auto *NewParam = cast<NonTypeTemplateOrTemplateTemplateParmDecl>(
- SemaRef.SubstDecl(OldParam, DC, Args));
- NewParam->setPosition(NewIndex);
- NewParam->setDepth(NewDepth);
- return NewParam;
-}
-
-/// Transform to convert portions of a constructor declaration into the
-/// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
-struct ConvertConstructorToDeductionGuideTransform {
- ConvertConstructorToDeductionGuideTransform(Sema &S,
- ClassTemplateDecl *Template)
- : SemaRef(S), Template(Template) {
- // If the template is nested, then we need to use the original
- // pattern to iterate over the constructors.
- ClassTemplateDecl *Pattern = Template;
- while (Pattern->getInstantiatedFromMemberTemplate()) {
- if (Pattern->isMemberSpecialization())
- break;
- Pattern = Pattern->getInstantiatedFromMemberTemplate();
- NestedPattern = Pattern;
- }
-
- if (NestedPattern)
- OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
- }
-
- Sema &SemaRef;
- ClassTemplateDecl *Template;
- ClassTemplateDecl *NestedPattern = nullptr;
-
- DeclContext *DC = Template->getDeclContext();
- CXXRecordDecl *Primary = Template->getTemplatedDecl();
- DeclarationName DeductionGuideName =
- SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template);
-
- QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary);
-
- // Index adjustment to apply to convert depth-1 template parameters into
- // depth-0 template parameters.
- unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size();
-
- // Instantiation arguments for the outermost depth-1 templates
- // when the template is nested
- MultiLevelTemplateArgumentList OuterInstantiationArgs;
-
- /// Transform a constructor declaration into a deduction guide.
- NamedDecl *transformConstructor(FunctionTemplateDecl *FTD,
- CXXConstructorDecl *CD) {
- SmallVector<TemplateArgument, 16> SubstArgs;
-
- LocalInstantiationScope Scope(SemaRef);
-
- // C++ [over.match.class.deduct]p1:
- // -- For each constructor of the class template designated by the
- // template-name, a function template with the following properties:
-
- // -- The template parameters are the template parameters of the class
- // template followed by the template parameters (including default
- // template arguments) of the constructor, if any.
- TemplateParameterList *TemplateParams = GetTemplateParameterList(Template);
- if (FTD) {
- TemplateParameterList *InnerParams = FTD->getTemplateParameters();
- SmallVector<NamedDecl *, 16> AllParams;
- SmallVector<TemplateArgument, 16> Depth1Args;
- AllParams.reserve(TemplateParams->size() + InnerParams->size());
- AllParams.insert(AllParams.begin(),
- TemplateParams->begin(), TemplateParams->end());
- SubstArgs.reserve(InnerParams->size());
- Depth1Args.reserve(InnerParams->size());
-
- // Later template parameters could refer to earlier ones, so build up
- // a list of substituted template arguments as we go.
- for (NamedDecl *Param : *InnerParams) {
- MultiLevelTemplateArgumentList Args;
- Args.setKind(TemplateSubstitutionKind::Rewrite);
- Args.addOuterTemplateArguments(Depth1Args);
- Args.addOuterRetainedLevel();
- if (NestedPattern)
- Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
- NamedDecl *NewParam = transformTemplateParameter(Param, Args);
- 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.getCanonicalTemplateArgument(
- SemaRef.Context.getInjectedTemplateArg(NewParam)));
-
- if (NestedPattern) {
- TemplateDeclInstantiator Instantiator(SemaRef, DC,
- OuterInstantiationArgs);
- Instantiator.setEvaluateConstraints(false);
- SemaRef.runWithSufficientStackSpace(NewParam->getLocation(), [&] {
- NewParam = cast<NamedDecl>(Instantiator.Visit(NewParam));
- });
- }
-
- assert(NewParam->getTemplateDepth() == 0 &&
- "Unexpected template parameter depth");
-
- AllParams.push_back(NewParam);
- SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument(
- SemaRef.Context.getInjectedTemplateArg(NewParam)));
- }
-
- // Substitute new template parameters into requires-clause if present.
- Expr *RequiresClause = nullptr;
- if (Expr *InnerRC = InnerParams->getRequiresClause()) {
- MultiLevelTemplateArgumentList Args;
- Args.setKind(TemplateSubstitutionKind::Rewrite);
- Args.addOuterTemplateArguments(Depth1Args);
- Args.addOuterRetainedLevel();
- if (NestedPattern)
- Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
- ExprResult E = SemaRef.SubstExpr(InnerRC, Args);
- if (E.isInvalid())
- return nullptr;
- RequiresClause = E.getAs<Expr>();
- }
-
- TemplateParams = TemplateParameterList::Create(
- SemaRef.Context, InnerParams->getTemplateLoc(),
- InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),
- RequiresClause);
- }
-
- // If we built a new template-parameter-list, track that we need to
- // substitute references to the old parameters into references to the
- // new ones.
- MultiLevelTemplateArgumentList Args;
- Args.setKind(TemplateSubstitutionKind::Rewrite);
- if (FTD) {
- Args.addOuterTemplateArguments(SubstArgs);
- Args.addOuterRetainedLevel();
- }
-
- FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc()
- .getAsAdjusted<FunctionProtoTypeLoc>();
- assert(FPTL && "no prototype for constructor declaration");
-
- // Transform the type of the function, adjusting the return type and
- // replacing references to the old parameters with references to the
- // new ones.
- TypeLocBuilder TLB;
- SmallVector<ParmVarDecl*, 8> Params;
- SmallVector<Typ...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/912 Here is the relevant piece of the build log for the reference:
|
LGTM |
Split out the deduction guide related code from SemaTemplate.cpp to a dedicated file.
These code has grown significantly, and moving it to a separate file will improve code organization.