[clang] [clang] WIP: Implement CTAD for type alias template. (PR #77890)

via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 12 00:20:53 PST 2024


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {clang-format}-->


:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff 98c6aa72299caeff6b188e1ff2fc1b39c5b893b6 ccf08bb5e209c98bddcb39b28256cd85cecd93cd -- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaInit.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
``````````

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6a6a30fc52..2bfc387175 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9251,13 +9251,11 @@ public:
                           const TemplateArgumentList &TemplateArgs,
                           sema::TemplateDeductionInfo &Info);
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(TemplateParameterList *TemplateParams,
-                          ArrayRef<TemplateArgument> Ps,
-                          ArrayRef<TemplateArgument> As,
-                          sema::TemplateDeductionInfo &Info,
-                          SmallVectorImpl<DeducedTemplateArgument> &Deduced,
-                          bool NumberOfArgumentsMustMatch);
+  TemplateDeductionResult DeduceTemplateArguments(
+      TemplateParameterList *TemplateParams, ArrayRef<TemplateArgument> Ps,
+      ArrayRef<TemplateArgument> As, sema::TemplateDeductionInfo &Info,
+      SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+      bool NumberOfArgumentsMustMatch);
 
   TemplateDeductionResult SubstituteExplicitTemplateArguments(
       FunctionTemplateDecl *FunctionTemplate,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d247fa74d5..28d103b8d8 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -10577,12 +10577,11 @@ static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD,
   return !(NotSpecialization(RD) && RD->forallBases(NotSpecialization));
 }
 
-
 /// FIXME: this is a copy-paste from SemaTemplate.cpp
 /// Tree transform to "extract" a transformed type from a class template's
 /// constructor to a deduction guide.
 class ExtractTypeForDeductionGuide
-  : public TreeTransform<ExtractTypeForDeductionGuide> {
+    : public TreeTransform<ExtractTypeForDeductionGuide> {
   llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs;
 
 public:
@@ -10626,7 +10625,8 @@ public:
   }
 };
 
-// Transform to form a corresponding deduction guide for type alias template decl.
+// Transform to form a corresponding deduction guide for type alias template
+// decl.
 //
 // This class implements the C++ [over.match.class.deduct]p3:
 //   ... Let g denote the result of substituting these deductions into f. If
@@ -10684,7 +10684,7 @@ struct AliasTemplateDeductionGuideTransform {
     int Index = 0;
     TemplateParameterList *TemplateParams = nullptr;
 
-    for (TemplateTypeParmDecl* Param : DeducedTemplateTypeParDecls) {
+    for (TemplateTypeParmDecl *Param : DeducedTemplateTypeParDecls) {
       MultiLevelTemplateArgumentList Args;
 
       Args.setKind(TemplateSubstitutionKind::Rewrite);
@@ -10706,7 +10706,7 @@ struct AliasTemplateDeductionGuideTransform {
 
     TemplateParams = TemplateParameterList::Create(
         SemaRef.Context, SourceLocation(), SourceLocation(), AllParams,
-        SourceLocation(), /*requiresClause */nullptr);
+        SourceLocation(), /*requiresClause */ nullptr);
 
     MultiLevelTemplateArgumentList Args;
     Args.setKind(TemplateSubstitutionKind::Rewrite);
@@ -10722,7 +10722,7 @@ struct AliasTemplateDeductionGuideTransform {
     // replacing references to the old parameters with references to the
     // new ones.
     TypeLocBuilder TLB;
-    SmallVector<ParmVarDecl*, 8> Params;
+    SmallVector<ParmVarDecl *, 8> Params;
     SmallVector<TypedefNameDecl *, 4> MaterializedTypedefs;
     QualType NewType = transformFunctionProtoType(
         TLB, FPTL, Params, Args, UnderlyingCDGD->getReturnType(),
@@ -10745,16 +10745,16 @@ private:
   /// to earlier parameters and renumbering as we go.
   NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam,
                                         MultiLevelTemplateArgumentList &Args,
-                                        int Index ) {
+                                        int Index) {
     if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) {
       // TemplateTypeParmDecl's index cannot be changed after creation, so
       // substitute it directly.
       auto *NewTTP = TemplateTypeParmDecl::Create(
           SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(),
           // FIXME: is the depth/index right?
-          TTP->getDepth(),  Index,
-          TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
-          TTP->isParameterPack(), TTP->hasTypeConstraint(),
+          TTP->getDepth(), Index, TTP->getIdentifier(),
+          TTP->wasDeclaredWithTypename(), TTP->isParameterPack(),
+          TTP->hasTypeConstraint(),
           TTP->isExpandedParameterPack()
               ? std::optional<unsigned>(TTP->getNumExpansionParameters())
               : std::nullopt);
@@ -10779,7 +10779,7 @@ private:
     return transformTemplateParameterImpl(
         cast<NonTypeTemplateParmDecl>(TemplateParam), Args);
   }
-  template<typename TemplateParmDecl>
+  template <typename TemplateParmDecl>
   TemplateParmDecl *
   transformTemplateParameterImpl(TemplateParmDecl *OldParam,
                                  MultiLevelTemplateArgumentList &Args) {
@@ -10794,12 +10794,10 @@ private:
     return NewParam;
   }
 
-
   QualType transformFunctionProtoType(
       TypeLocBuilder &TLB, FunctionProtoTypeLoc TL,
       SmallVectorImpl<ParmVarDecl *> &Params,
-      MultiLevelTemplateArgumentList &Args,
-      QualType ReturnType,
+      MultiLevelTemplateArgumentList &Args, QualType ReturnType,
       SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) {
     SmallVector<QualType, 4> ParamTypes;
     const FunctionProtoType *T = TL.getTypePtr();
@@ -10817,8 +10815,8 @@ private:
       Params.push_back(NewParam);
     }
 
-    // The return type of the deduction guide f is InjectedClassNameType, transform
-    // it to a TemplateSpecializationType.
+    // The return type of the deduction guide f is InjectedClassNameType,
+    // transform it to a TemplateSpecializationType.
     if (const auto *ET = ReturnType->getAs<InjectedClassNameType>()) {
       ReturnType = ET->getInjectedSpecializationType();
     }
@@ -10898,14 +10896,10 @@ private:
                                                              : VK_PRValue);
     }
 
-    ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC,
-                                                OldParam->getInnerLocStart(),
-                                                OldParam->getLocation(),
-                                                OldParam->getIdentifier(),
-                                                NewDI->getType(),
-                                                NewDI,
-                                                OldParam->getStorageClass(),
-                                                NewDefArg.get());
+    ParmVarDecl *NewParam = ParmVarDecl::Create(
+        SemaRef.Context, DC, OldParam->getInnerLocStart(),
+        OldParam->getLocation(), OldParam->getIdentifier(), NewDI->getType(),
+        NewDI, OldParam->getStorageClass(), NewDefArg.get());
     NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
                            OldParam->getFunctionScopeIndex());
     SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
@@ -10967,7 +10961,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
   auto *Template =
       dyn_cast_or_null<ClassTemplateDecl>(TemplateName.getAsTemplateDecl());
 
-  TypeAliasTemplateDecl* AliasTemplate = nullptr;
+  TypeAliasTemplateDecl *AliasTemplate = nullptr;
   if (!Template) {
     if ((AliasTemplate = dyn_cast_or_null<TypeAliasTemplateDecl>(
              TemplateName.getAsTemplateDecl()))) {
@@ -11022,14 +11016,14 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
 
   SmallVector<DeclAccessPair> GuidesCandidates;
   if (AliasTemplate) {
-    for (auto* Guide : Guides) {
+    for (auto *Guide : Guides) {
       if (!dyn_cast_or_null<FunctionTemplateDecl>(Guide))
         continue;
       auto RType = dyn_cast<FunctionTemplateDecl>(Guide)
                        ->getTemplatedDecl()
                        ->getReturnType();
       // The (trailing) return type of the deduction guide.
-      const TemplateSpecializationType * ReturnTST = nullptr;
+      const TemplateSpecializationType *ReturnTST = nullptr;
       if (const auto *InjectedCNT = RType->getAs<InjectedClassNameType>()) {
         // for implicitly-generated deduction guide.
         ReturnTST = InjectedCNT->getInjectedTST();
@@ -11039,89 +11033,87 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
       }
       assert(ReturnTST);
       if (ReturnTST) {
-          SmallVector<DeducedTemplateArgument> DeduceResults;
-          SmallVector<TemplateArgument> DeducedArgs;
-          DeduceResults.resize(ReturnTST->template_arguments().size());
-          sema::TemplateDeductionInfo TDeduceInfo({});
-          // Deduce template arguments of the deduction guide from the RHS of
-          // the alias.
-          //
-          // C++ [over.match.class.deduct]p3: ...For each function or function
-          // template f in the guides of the template named by the
-          // simple-template-id of the defining-type-id, the template arguments
-          // of the return type of f are deduced from the defining-type-id of A
-          // according to the process in [temp.deduct.type] with the exception
-          // that deduction does not fail if not all template arguments are
-          // deduced.
-          //
-          //
-          //  template<typename X, typename Y>
-          //  f(X, Y) -> f<Y, X>
+        SmallVector<DeducedTemplateArgument> DeduceResults;
+        SmallVector<TemplateArgument> DeducedArgs;
+        DeduceResults.resize(ReturnTST->template_arguments().size());
+        sema::TemplateDeductionInfo TDeduceInfo({});
+        // Deduce template arguments of the deduction guide from the RHS of
+        // the alias.
+        //
+        // C++ [over.match.class.deduct]p3: ...For each function or function
+        // template f in the guides of the template named by the
+        // simple-template-id of the defining-type-id, the template arguments
+        // of the return type of f are deduced from the defining-type-id of A
+        // according to the process in [temp.deduct.type] with the exception
+        // that deduction does not fail if not all template arguments are
+        // deduced.
+        //
+        //
+        //  template<typename X, typename Y>
+        //  f(X, Y) -> f<Y, X>
+        //
+        //  template<typename U>
+        //  using alias = f<int, U>;
+        //
+        // The RHS of alias is f<int, U>, we deduced the template arguments of
+        // the return type of the deduction guide from it: Y->int, X -> U
+        const auto *AliasRhsTST = AliasTemplate->getTemplatedDecl()
+                                      ->getUnderlyingType()
+                                      .getDesugaredType(this->Context)
+                                      ->getAs<TemplateSpecializationType>();
+        assert(AliasRhsTST);
+
+        if (DeduceTemplateArguments(AliasTemplate->getTemplateParameters(),
+                                    ReturnTST->template_arguments(),
+                                    AliasRhsTST->template_arguments(),
+                                    TDeduceInfo, DeduceResults,
+                                    /*NumberOfArgumentsMustMatch*/ false)) {
+          // FIXME: not all template arguments are deduced, we should continue
+          // to proceed with all deduced results.
+        } else {
+          // Happy case, all template arguments are deduced.
+          for (auto D : DeduceResults)
+            DeducedArgs.push_back(D);
+
+          auto *DeducedArgList =
+              TemplateArgumentList::CreateCopy(this->Context, DeducedArgs);
+
+          AliasTemplateDeductionGuideTransform Transform(*this, AliasTemplate);
+
+          // Substitute all above deduced template arguments into the
+          // deduction guide f.
           //
-          //  template<typename U>
-          //  using alias = f<int, U>;
+          // FIXME: is using the InstantiateFunctionDeclaration API a right
+          // implement choice? It has some side effects which creates a
+          // specialization for the deduction guide function template, and
+          // the specialization is added to the the FunctionTemplateDecl, this
+          // is not specified by C++ standard.
           //
-          // The RHS of alias is f<int, U>, we deduced the template arguments of
-          // the return type of the deduction guide from it: Y->int, X -> U
-          const auto* AliasRhsTST = AliasTemplate->getTemplatedDecl()
-                         ->getUnderlyingType()
-                         .getDesugaredType(this->Context)
-                         ->getAs<TemplateSpecializationType>();
-          assert(AliasRhsTST);
-
-          if (DeduceTemplateArguments(AliasTemplate->getTemplateParameters(),
-                                      ReturnTST->template_arguments(),
-                                      AliasRhsTST->template_arguments(),
-                                      TDeduceInfo, DeduceResults,
-                                      /*NumberOfArgumentsMustMatch*/ false)) {
-            // FIXME: not all template arguments are deduced, we should continue
-            // to proceed with all deduced results.
-          } else {
-            // Happy case, all template arguments are deduced.
-            for (auto D : DeduceResults)
-              DeducedArgs.push_back(D);
-
-            auto *DeducedArgList =
-                TemplateArgumentList::CreateCopy(this->Context, DeducedArgs);
-
-            AliasTemplateDeductionGuideTransform Transform(
-                *this, AliasTemplate);
-
-            // Substitute all above deduced template arguments into the
-            // deduction guide f.
-            //
-            // FIXME: is using the InstantiateFunctionDeclaration API a right
-            // implement choice? It has some side effects which creates a
-            // specialization for the deduction guide function template, and
-            // the specialization is added to the the FunctionTemplateDecl, this
-            // is not specified by C++ standard.
-            //
-            // FIXME: Should we cache the result?
-            if (auto *K = InstantiateFunctionDeclaration(
-                    dyn_cast<FunctionTemplateDecl>(Guide), DeducedArgList,
-                    SourceLocation(),
-                    Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
-              InstantiatingTemplate BuildingDeductionGuides(
-                  *this, SourceLocation(), AliasTemplate,
-                  Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
-              auto *D = Transform.transformUnderlyingFunctionTemplate(
-                  dyn_cast<CXXDeductionGuideDecl>(K), DeducedArgs);
-              // FIXME: implement the assoicated constraint per C++
-              // [over.match.class.deduct]p3.3:
-              //    The associated constraints ([temp.constr.decl]) are the
-              //    conjunction of the associated constraints of g and a
-              //    constraint that is satisfied if and only if the arguments of
-              //    A are deducible (see below) from the return type.
-              // This could be implemented as part of function overload
-              // resolution below.
-              GuidesCandidates.push_back(
-                  DeclAccessPair::make(D, AccessSpecifier::AS_public));
-            }
+          // FIXME: Should we cache the result?
+          if (auto *K = InstantiateFunctionDeclaration(
+                  dyn_cast<FunctionTemplateDecl>(Guide), DeducedArgList,
+                  SourceLocation(),
+                  Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
+            InstantiatingTemplate BuildingDeductionGuides(
+                *this, SourceLocation(), AliasTemplate,
+                Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
+            auto *D = Transform.transformUnderlyingFunctionTemplate(
+                dyn_cast<CXXDeductionGuideDecl>(K), DeducedArgs);
+            // FIXME: implement the assoicated constraint per C++
+            // [over.match.class.deduct]p3.3:
+            //    The associated constraints ([temp.constr.decl]) are the
+            //    conjunction of the associated constraints of g and a
+            //    constraint that is satisfied if and only if the arguments of
+            //    A are deducible (see below) from the return type.
+            // This could be implemented as part of function overload
+            // resolution below.
+            GuidesCandidates.push_back(
+                DeclAccessPair::make(D, AccessSpecifier::AS_public));
           }
+        }
       }
     }
-  }
-  else {
+  } else {
     for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) {
       GuidesCandidates.push_back(I.getPair());
     }
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 2f548b1a9f..5129a9cfce 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -517,10 +517,9 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
     : InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
                             InstantiationRange, FunctionTemplate, nullptr,
                             TemplateArgs, &DeductionInfo) {
-  assert(
-    Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
-    Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution ||
-    Kind == CodeSynthesisContext::BuildingDeductionGuides);
+  assert(Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
+         Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution ||
+         Kind == CodeSynthesisContext::BuildingDeductionGuides);
 }
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(
@@ -1420,8 +1419,7 @@ namespace {
     QualType TransformInjectedClassNameType(TypeLocBuilder &TLB,
                                             InjectedClassNameTypeLoc TL) {
       // Return a TemplateSpecializationType for building deduction guides
-      Decl *D = TransformDecl(TL.getNameLoc(),
-                              TL.getTypePtr()->getDecl());
+      Decl *D = TransformDecl(TL.getNameLoc(), TL.getTypePtr()->getDecl());
       if (!D) {
         if (SemaRef.CodeSynthesisContexts.back().Kind !=
             Sema::CodeSynthesisContext::BuildingDeductionGuides)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 71c014b650..086d8de385 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4849,16 +4849,13 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New,
 ///
 /// Usually this should not be used, and template argument deduction should be
 /// used in its place.
-FunctionDecl *
-Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
-                                     const TemplateArgumentList *Args,
-                                     SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC) {
+FunctionDecl *Sema::InstantiateFunctionDeclaration(
+    FunctionTemplateDecl *FTD, const TemplateArgumentList *Args,
+    SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC) {
   FunctionDecl *FD = FTD->getTemplatedDecl();
 
   sema::TemplateDeductionInfo Info(Loc);
-  InstantiatingTemplate Inst(
-      *this, Loc, FTD, Args->asArray(),
-      CSC, Info);
+  InstantiatingTemplate Inst(*this, Loc, FTD, Args->asArray(), CSC, Info);
   if (Inst.isInvalid())
     return nullptr;
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/77890


More information about the cfe-commits mailing list