xref: /llvm-project/clang/lib/Sema/SemaTemplateDeductionGuide.cpp (revision f94c481543bdd3b11a668ad78d46593cf974788f)
118c70b07SHaojian Wu //===- SemaTemplateDeductionGude.cpp - Template Argument Deduction---------===//
218c70b07SHaojian Wu //
318c70b07SHaojian Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
418c70b07SHaojian Wu // See https://llvm.org/LICENSE.txt for license information.
518c70b07SHaojian Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
618c70b07SHaojian Wu //
718c70b07SHaojian Wu //===----------------------------------------------------------------------===//
818c70b07SHaojian Wu //
918c70b07SHaojian Wu // This file implements deduction guides for C++ class template argument
1018c70b07SHaojian Wu // deduction.
1118c70b07SHaojian Wu //
1218c70b07SHaojian Wu //===----------------------------------------------------------------------===//
1318c70b07SHaojian Wu 
1418c70b07SHaojian Wu #include "TreeTransform.h"
1518c70b07SHaojian Wu #include "TypeLocBuilder.h"
1618c70b07SHaojian Wu #include "clang/AST/ASTConsumer.h"
1718c70b07SHaojian Wu #include "clang/AST/ASTContext.h"
1818c70b07SHaojian Wu #include "clang/AST/Decl.h"
1918c70b07SHaojian Wu #include "clang/AST/DeclBase.h"
2018c70b07SHaojian Wu #include "clang/AST/DeclCXX.h"
2118c70b07SHaojian Wu #include "clang/AST/DeclFriend.h"
2218c70b07SHaojian Wu #include "clang/AST/DeclTemplate.h"
2318c70b07SHaojian Wu #include "clang/AST/DeclarationName.h"
24dde802b1SSirraide #include "clang/AST/DynamicRecursiveASTVisitor.h"
2518c70b07SHaojian Wu #include "clang/AST/Expr.h"
2618c70b07SHaojian Wu #include "clang/AST/ExprCXX.h"
2718c70b07SHaojian Wu #include "clang/AST/OperationKinds.h"
2818c70b07SHaojian Wu #include "clang/AST/TemplateBase.h"
2918c70b07SHaojian Wu #include "clang/AST/TemplateName.h"
3018c70b07SHaojian Wu #include "clang/AST/Type.h"
3118c70b07SHaojian Wu #include "clang/AST/TypeLoc.h"
3218c70b07SHaojian Wu #include "clang/Basic/LLVM.h"
3318c70b07SHaojian Wu #include "clang/Basic/SourceLocation.h"
3418c70b07SHaojian Wu #include "clang/Basic/Specifiers.h"
3518c70b07SHaojian Wu #include "clang/Basic/TypeTraits.h"
3618c70b07SHaojian Wu #include "clang/Sema/DeclSpec.h"
3718c70b07SHaojian Wu #include "clang/Sema/Initialization.h"
3818c70b07SHaojian Wu #include "clang/Sema/Lookup.h"
3918c70b07SHaojian Wu #include "clang/Sema/Overload.h"
4018c70b07SHaojian Wu #include "clang/Sema/Ownership.h"
4118c70b07SHaojian Wu #include "clang/Sema/Scope.h"
42bb064535SYounan Zhang #include "clang/Sema/SemaInternal.h"
4318c70b07SHaojian Wu #include "clang/Sema/Template.h"
4418c70b07SHaojian Wu #include "clang/Sema/TemplateDeduction.h"
4518c70b07SHaojian Wu #include "llvm/ADT/ArrayRef.h"
4618c70b07SHaojian Wu #include "llvm/ADT/STLExtras.h"
4718c70b07SHaojian Wu #include "llvm/ADT/SmallVector.h"
4818c70b07SHaojian Wu #include "llvm/Support/Casting.h"
4918c70b07SHaojian Wu #include "llvm/Support/ErrorHandling.h"
5018c70b07SHaojian Wu #include <cassert>
5118c70b07SHaojian Wu #include <optional>
5218c70b07SHaojian Wu #include <utility>
5318c70b07SHaojian Wu 
5418c70b07SHaojian Wu using namespace clang;
5518c70b07SHaojian Wu using namespace sema;
5618c70b07SHaojian Wu 
5718c70b07SHaojian Wu namespace {
5818c70b07SHaojian Wu /// Tree transform to "extract" a transformed type from a class template's
5918c70b07SHaojian Wu /// constructor to a deduction guide.
6018c70b07SHaojian Wu class ExtractTypeForDeductionGuide
6118c70b07SHaojian Wu     : public TreeTransform<ExtractTypeForDeductionGuide> {
6218c70b07SHaojian Wu   llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs;
6318c70b07SHaojian Wu   ClassTemplateDecl *NestedPattern;
6418c70b07SHaojian Wu   const MultiLevelTemplateArgumentList *OuterInstantiationArgs;
6518c70b07SHaojian Wu   std::optional<TemplateDeclInstantiator> TypedefNameInstantiator;
6618c70b07SHaojian Wu 
6718c70b07SHaojian Wu public:
6818c70b07SHaojian Wu   typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
6918c70b07SHaojian Wu   ExtractTypeForDeductionGuide(
7018c70b07SHaojian Wu       Sema &SemaRef,
7118c70b07SHaojian Wu       llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
720bc02b99SYounan Zhang       ClassTemplateDecl *NestedPattern = nullptr,
730bc02b99SYounan Zhang       const MultiLevelTemplateArgumentList *OuterInstantiationArgs = nullptr)
7418c70b07SHaojian Wu       : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs),
7518c70b07SHaojian Wu         NestedPattern(NestedPattern),
7618c70b07SHaojian Wu         OuterInstantiationArgs(OuterInstantiationArgs) {
7718c70b07SHaojian Wu     if (OuterInstantiationArgs)
7818c70b07SHaojian Wu       TypedefNameInstantiator.emplace(
7918c70b07SHaojian Wu           SemaRef, SemaRef.getASTContext().getTranslationUnitDecl(),
8018c70b07SHaojian Wu           *OuterInstantiationArgs);
8118c70b07SHaojian Wu   }
8218c70b07SHaojian Wu 
8318c70b07SHaojian Wu   TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
8418c70b07SHaojian Wu 
8518c70b07SHaojian Wu   /// Returns true if it's safe to substitute \p Typedef with
8618c70b07SHaojian Wu   /// \p OuterInstantiationArgs.
8718c70b07SHaojian Wu   bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) {
8818c70b07SHaojian Wu     if (!NestedPattern)
8918c70b07SHaojian Wu       return false;
9018c70b07SHaojian Wu 
9118c70b07SHaojian Wu     static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) {
9218c70b07SHaojian Wu       if (DC->Equals(TargetDC))
9318c70b07SHaojian Wu         return true;
9418c70b07SHaojian Wu       while (DC->isRecord()) {
9518c70b07SHaojian Wu         if (DC->Equals(TargetDC))
9618c70b07SHaojian Wu           return true;
9718c70b07SHaojian Wu         DC = DC->getParent();
9818c70b07SHaojian Wu       }
9918c70b07SHaojian Wu       return false;
10018c70b07SHaojian Wu     };
10118c70b07SHaojian Wu 
10218c70b07SHaojian Wu     if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl()))
10318c70b07SHaojian Wu       return true;
10418c70b07SHaojian Wu     if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext()))
10518c70b07SHaojian Wu       return true;
10618c70b07SHaojian Wu     return false;
10718c70b07SHaojian Wu   }
10818c70b07SHaojian Wu 
10918c70b07SHaojian Wu   QualType
11018c70b07SHaojian Wu   RebuildTemplateSpecializationType(TemplateName Template,
11118c70b07SHaojian Wu                                     SourceLocation TemplateNameLoc,
11218c70b07SHaojian Wu                                     TemplateArgumentListInfo &TemplateArgs) {
11318c70b07SHaojian Wu     if (!OuterInstantiationArgs ||
11418c70b07SHaojian Wu         !isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()))
11518c70b07SHaojian Wu       return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
11618c70b07SHaojian Wu                                                      TemplateArgs);
11718c70b07SHaojian Wu 
11818c70b07SHaojian Wu     auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
11918c70b07SHaojian Wu     auto *Pattern = TATD;
12018c70b07SHaojian Wu     while (Pattern->getInstantiatedFromMemberTemplate())
12118c70b07SHaojian Wu       Pattern = Pattern->getInstantiatedFromMemberTemplate();
12218c70b07SHaojian Wu     if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl()))
12318c70b07SHaojian Wu       return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
12418c70b07SHaojian Wu                                                      TemplateArgs);
12518c70b07SHaojian Wu 
12618c70b07SHaojian Wu     Decl *NewD =
12718c70b07SHaojian Wu         TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD);
12818c70b07SHaojian Wu     if (!NewD)
12918c70b07SHaojian Wu       return QualType();
13018c70b07SHaojian Wu 
13118c70b07SHaojian Wu     auto *NewTATD = cast<TypeAliasTemplateDecl>(NewD);
13218c70b07SHaojian Wu     MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl());
13318c70b07SHaojian Wu 
13418c70b07SHaojian Wu     return Base::RebuildTemplateSpecializationType(
13518c70b07SHaojian Wu         TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
13618c70b07SHaojian Wu   }
13718c70b07SHaojian Wu 
13818c70b07SHaojian Wu   QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
13918c70b07SHaojian Wu     ASTContext &Context = SemaRef.getASTContext();
14018c70b07SHaojian Wu     TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
14118c70b07SHaojian Wu     TypedefNameDecl *Decl = OrigDecl;
14218c70b07SHaojian Wu     // Transform the underlying type of the typedef and clone the Decl only if
14318c70b07SHaojian Wu     // the typedef has a dependent context.
14418c70b07SHaojian Wu     bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext();
14518c70b07SHaojian Wu 
14618c70b07SHaojian Wu     // A typedef/alias Decl within the NestedPattern may reference the outer
14718c70b07SHaojian Wu     // template parameters. They're substituted with corresponding instantiation
14818c70b07SHaojian Wu     // arguments here and in RebuildTemplateSpecializationType() above.
14918c70b07SHaojian Wu     // Otherwise, we would have a CTAD guide with "dangling" template
15018c70b07SHaojian Wu     // parameters.
15118c70b07SHaojian Wu     // For example,
15218c70b07SHaojian Wu     //   template <class T> struct Outer {
15318c70b07SHaojian Wu     //     using Alias = S<T>;
15418c70b07SHaojian Wu     //     template <class U> struct Inner {
15518c70b07SHaojian Wu     //       Inner(Alias);
15618c70b07SHaojian Wu     //     };
15718c70b07SHaojian Wu     //   };
15818c70b07SHaojian Wu     if (OuterInstantiationArgs && InDependentContext &&
15918c70b07SHaojian Wu         TL.getTypePtr()->isInstantiationDependentType()) {
16018c70b07SHaojian Wu       Decl = cast_if_present<TypedefNameDecl>(
16118c70b07SHaojian Wu           TypedefNameInstantiator->InstantiateTypedefNameDecl(
16218c70b07SHaojian Wu               OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl)));
16318c70b07SHaojian Wu       if (!Decl)
16418c70b07SHaojian Wu         return QualType();
16518c70b07SHaojian Wu       MaterializedTypedefs.push_back(Decl);
16618c70b07SHaojian Wu     } else if (InDependentContext) {
16718c70b07SHaojian Wu       TypeLocBuilder InnerTLB;
16818c70b07SHaojian Wu       QualType Transformed =
16918c70b07SHaojian Wu           TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
17018c70b07SHaojian Wu       TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, Transformed);
17118c70b07SHaojian Wu       if (isa<TypeAliasDecl>(OrigDecl))
17218c70b07SHaojian Wu         Decl = TypeAliasDecl::Create(
17318c70b07SHaojian Wu             Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
17418c70b07SHaojian Wu             OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
17518c70b07SHaojian Wu       else {
17618c70b07SHaojian Wu         assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef");
17718c70b07SHaojian Wu         Decl = TypedefDecl::Create(
17818c70b07SHaojian Wu             Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(),
17918c70b07SHaojian Wu             OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI);
18018c70b07SHaojian Wu       }
18118c70b07SHaojian Wu       MaterializedTypedefs.push_back(Decl);
18218c70b07SHaojian Wu     }
18318c70b07SHaojian Wu 
18418c70b07SHaojian Wu     QualType TDTy = Context.getTypedefType(Decl);
18518c70b07SHaojian Wu     TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy);
18618c70b07SHaojian Wu     TypedefTL.setNameLoc(TL.getNameLoc());
18718c70b07SHaojian Wu 
18818c70b07SHaojian Wu     return TDTy;
18918c70b07SHaojian Wu   }
19018c70b07SHaojian Wu };
19118c70b07SHaojian Wu 
19218c70b07SHaojian Wu // Build a deduction guide using the provided information.
19318c70b07SHaojian Wu //
19418c70b07SHaojian Wu // A deduction guide can be either a template or a non-template function
19518c70b07SHaojian Wu // declaration. If \p TemplateParams is null, a non-template function
19618c70b07SHaojian Wu // declaration will be created.
197b46fcb9fSYounan Zhang NamedDecl *
198b46fcb9fSYounan Zhang buildDeductionGuide(Sema &SemaRef, TemplateDecl *OriginalTemplate,
199b46fcb9fSYounan Zhang                     TemplateParameterList *TemplateParams,
200b46fcb9fSYounan Zhang                     CXXConstructorDecl *Ctor, ExplicitSpecifier ES,
201b46fcb9fSYounan Zhang                     TypeSourceInfo *TInfo, SourceLocation LocStart,
20218c70b07SHaojian Wu                     SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
203b46fcb9fSYounan Zhang                     llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {},
204b46fcb9fSYounan Zhang                     Expr *FunctionTrailingRC = nullptr) {
20518c70b07SHaojian Wu   DeclContext *DC = OriginalTemplate->getDeclContext();
20618c70b07SHaojian Wu   auto DeductionGuideName =
20718c70b07SHaojian Wu       SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
20818c70b07SHaojian Wu           OriginalTemplate);
20918c70b07SHaojian Wu 
21018c70b07SHaojian Wu   DeclarationNameInfo Name(DeductionGuideName, Loc);
21118c70b07SHaojian Wu   ArrayRef<ParmVarDecl *> Params =
21218c70b07SHaojian Wu       TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams();
21318c70b07SHaojian Wu 
21418c70b07SHaojian Wu   // Build the implicit deduction guide template.
215b46fcb9fSYounan Zhang   auto *Guide = CXXDeductionGuideDecl::Create(
216b46fcb9fSYounan Zhang       SemaRef.Context, DC, LocStart, ES, Name, TInfo->getType(), TInfo, LocEnd,
217b46fcb9fSYounan Zhang       Ctor, DeductionCandidate::Normal, FunctionTrailingRC);
21818c70b07SHaojian Wu   Guide->setImplicit(IsImplicit);
21918c70b07SHaojian Wu   Guide->setParams(Params);
22018c70b07SHaojian Wu 
22118c70b07SHaojian Wu   for (auto *Param : Params)
22218c70b07SHaojian Wu     Param->setDeclContext(Guide);
22318c70b07SHaojian Wu   for (auto *TD : MaterializedTypedefs)
22418c70b07SHaojian Wu     TD->setDeclContext(Guide);
22518c70b07SHaojian Wu   if (isa<CXXRecordDecl>(DC))
22618c70b07SHaojian Wu     Guide->setAccess(AS_public);
22718c70b07SHaojian Wu 
22818c70b07SHaojian Wu   if (!TemplateParams) {
22918c70b07SHaojian Wu     DC->addDecl(Guide);
23018c70b07SHaojian Wu     return Guide;
23118c70b07SHaojian Wu   }
23218c70b07SHaojian Wu 
23318c70b07SHaojian Wu   auto *GuideTemplate = FunctionTemplateDecl::Create(
23418c70b07SHaojian Wu       SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
23518c70b07SHaojian Wu   GuideTemplate->setImplicit(IsImplicit);
23618c70b07SHaojian Wu   Guide->setDescribedFunctionTemplate(GuideTemplate);
23718c70b07SHaojian Wu 
23818c70b07SHaojian Wu   if (isa<CXXRecordDecl>(DC))
23918c70b07SHaojian Wu     GuideTemplate->setAccess(AS_public);
24018c70b07SHaojian Wu 
24118c70b07SHaojian Wu   DC->addDecl(GuideTemplate);
24218c70b07SHaojian Wu   return GuideTemplate;
24318c70b07SHaojian Wu }
24418c70b07SHaojian Wu 
24518c70b07SHaojian Wu // Transform a given template type parameter `TTP`.
246bb064535SYounan Zhang TemplateTypeParmDecl *transformTemplateTypeParam(
247bb064535SYounan Zhang     Sema &SemaRef, DeclContext *DC, TemplateTypeParmDecl *TTP,
248bb064535SYounan Zhang     MultiLevelTemplateArgumentList &Args, unsigned NewDepth, unsigned NewIndex,
249bb064535SYounan Zhang     bool EvaluateConstraint) {
25018c70b07SHaojian Wu   // TemplateTypeParmDecl's index cannot be changed after creation, so
25118c70b07SHaojian Wu   // substitute it directly.
25218c70b07SHaojian Wu   auto *NewTTP = TemplateTypeParmDecl::Create(
25318c70b07SHaojian Wu       SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
25418c70b07SHaojian Wu       NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
25518c70b07SHaojian Wu       TTP->isParameterPack(), TTP->hasTypeConstraint(),
25618c70b07SHaojian Wu       TTP->isExpandedParameterPack()
25718c70b07SHaojian Wu           ? std::optional<unsigned>(TTP->getNumExpansionParameters())
25818c70b07SHaojian Wu           : std::nullopt);
25918c70b07SHaojian Wu   if (const auto *TC = TTP->getTypeConstraint())
26018c70b07SHaojian Wu     SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
261bb064535SYounan Zhang                                 /*EvaluateConstraint=*/EvaluateConstraint);
26218c70b07SHaojian Wu   if (TTP->hasDefaultArgument()) {
26318c70b07SHaojian Wu     TemplateArgumentLoc InstantiatedDefaultArg;
26418c70b07SHaojian Wu     if (!SemaRef.SubstTemplateArgument(
26518c70b07SHaojian Wu             TTP->getDefaultArgument(), Args, InstantiatedDefaultArg,
26618c70b07SHaojian Wu             TTP->getDefaultArgumentLoc(), TTP->getDeclName()))
26718c70b07SHaojian Wu       NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg);
26818c70b07SHaojian Wu   }
26918c70b07SHaojian Wu   SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP);
27018c70b07SHaojian Wu   return NewTTP;
27118c70b07SHaojian Wu }
27218c70b07SHaojian Wu // Similar to above, but for non-type template or template template parameters.
27318c70b07SHaojian Wu template <typename NonTypeTemplateOrTemplateTemplateParmDecl>
27418c70b07SHaojian Wu NonTypeTemplateOrTemplateTemplateParmDecl *
27518c70b07SHaojian Wu transformTemplateParam(Sema &SemaRef, DeclContext *DC,
27618c70b07SHaojian Wu                        NonTypeTemplateOrTemplateTemplateParmDecl *OldParam,
27718c70b07SHaojian Wu                        MultiLevelTemplateArgumentList &Args, unsigned NewIndex,
27818c70b07SHaojian Wu                        unsigned NewDepth) {
27918c70b07SHaojian Wu   // Ask the template instantiator to do the heavy lifting for us, then adjust
28018c70b07SHaojian Wu   // the index of the parameter once it's done.
28118c70b07SHaojian Wu   auto *NewParam = cast<NonTypeTemplateOrTemplateTemplateParmDecl>(
28218c70b07SHaojian Wu       SemaRef.SubstDecl(OldParam, DC, Args));
28318c70b07SHaojian Wu   NewParam->setPosition(NewIndex);
28418c70b07SHaojian Wu   NewParam->setDepth(NewDepth);
28518c70b07SHaojian Wu   return NewParam;
28618c70b07SHaojian Wu }
28718c70b07SHaojian Wu 
288bb064535SYounan Zhang NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC,
289bb064535SYounan Zhang                                       NamedDecl *TemplateParam,
290bb064535SYounan Zhang                                       MultiLevelTemplateArgumentList &Args,
291bb064535SYounan Zhang                                       unsigned NewIndex, unsigned NewDepth,
292bb064535SYounan Zhang                                       bool EvaluateConstraint = true) {
293bb064535SYounan Zhang   if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
294bb064535SYounan Zhang     return transformTemplateTypeParam(
295bb064535SYounan Zhang         SemaRef, DC, TTP, Args, NewDepth, NewIndex,
296bb064535SYounan Zhang         /*EvaluateConstraint=*/EvaluateConstraint);
297bb064535SYounan Zhang   if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
298bb064535SYounan Zhang     return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth);
299bb064535SYounan Zhang   if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
300bb064535SYounan Zhang     return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth);
301bb064535SYounan Zhang   llvm_unreachable("Unhandled template parameter types");
302bb064535SYounan Zhang }
303bb064535SYounan Zhang 
30418c70b07SHaojian Wu /// Transform to convert portions of a constructor declaration into the
30518c70b07SHaojian Wu /// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
30618c70b07SHaojian Wu struct ConvertConstructorToDeductionGuideTransform {
30718c70b07SHaojian Wu   ConvertConstructorToDeductionGuideTransform(Sema &S,
30818c70b07SHaojian Wu                                               ClassTemplateDecl *Template)
30918c70b07SHaojian Wu       : SemaRef(S), Template(Template) {
31018c70b07SHaojian Wu     // If the template is nested, then we need to use the original
31118c70b07SHaojian Wu     // pattern to iterate over the constructors.
31218c70b07SHaojian Wu     ClassTemplateDecl *Pattern = Template;
31318c70b07SHaojian Wu     while (Pattern->getInstantiatedFromMemberTemplate()) {
31418c70b07SHaojian Wu       if (Pattern->isMemberSpecialization())
31518c70b07SHaojian Wu         break;
31618c70b07SHaojian Wu       Pattern = Pattern->getInstantiatedFromMemberTemplate();
31718c70b07SHaojian Wu       NestedPattern = Pattern;
31818c70b07SHaojian Wu     }
31918c70b07SHaojian Wu 
32018c70b07SHaojian Wu     if (NestedPattern)
32118c70b07SHaojian Wu       OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
32218c70b07SHaojian Wu   }
32318c70b07SHaojian Wu 
32418c70b07SHaojian Wu   Sema &SemaRef;
32518c70b07SHaojian Wu   ClassTemplateDecl *Template;
32618c70b07SHaojian Wu   ClassTemplateDecl *NestedPattern = nullptr;
32718c70b07SHaojian Wu 
32818c70b07SHaojian Wu   DeclContext *DC = Template->getDeclContext();
32918c70b07SHaojian Wu   CXXRecordDecl *Primary = Template->getTemplatedDecl();
33018c70b07SHaojian Wu   DeclarationName DeductionGuideName =
33118c70b07SHaojian Wu       SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template);
33218c70b07SHaojian Wu 
33318c70b07SHaojian Wu   QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary);
33418c70b07SHaojian Wu 
33518c70b07SHaojian Wu   // Index adjustment to apply to convert depth-1 template parameters into
33618c70b07SHaojian Wu   // depth-0 template parameters.
33718c70b07SHaojian Wu   unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size();
33818c70b07SHaojian Wu 
33918c70b07SHaojian Wu   // Instantiation arguments for the outermost depth-1 templates
34018c70b07SHaojian Wu   // when the template is nested
34118c70b07SHaojian Wu   MultiLevelTemplateArgumentList OuterInstantiationArgs;
34218c70b07SHaojian Wu 
34318c70b07SHaojian Wu   /// Transform a constructor declaration into a deduction guide.
34418c70b07SHaojian Wu   NamedDecl *transformConstructor(FunctionTemplateDecl *FTD,
34518c70b07SHaojian Wu                                   CXXConstructorDecl *CD) {
34618c70b07SHaojian Wu     SmallVector<TemplateArgument, 16> SubstArgs;
34718c70b07SHaojian Wu 
34818c70b07SHaojian Wu     LocalInstantiationScope Scope(SemaRef);
34918c70b07SHaojian Wu 
35018c70b07SHaojian Wu     // C++ [over.match.class.deduct]p1:
35118c70b07SHaojian Wu     // -- For each constructor of the class template designated by the
35218c70b07SHaojian Wu     //    template-name, a function template with the following properties:
35318c70b07SHaojian Wu 
35418c70b07SHaojian Wu     //    -- The template parameters are the template parameters of the class
35518c70b07SHaojian Wu     //       template followed by the template parameters (including default
35618c70b07SHaojian Wu     //       template arguments) of the constructor, if any.
35718c70b07SHaojian Wu     TemplateParameterList *TemplateParams =
35818c70b07SHaojian Wu         SemaRef.GetTemplateParameterList(Template);
359b46fcb9fSYounan Zhang     SmallVector<TemplateArgument, 16> Depth1Args;
360b46fcb9fSYounan Zhang     Expr *OuterRC = TemplateParams->getRequiresClause();
36118c70b07SHaojian Wu     if (FTD) {
36218c70b07SHaojian Wu       TemplateParameterList *InnerParams = FTD->getTemplateParameters();
36318c70b07SHaojian Wu       SmallVector<NamedDecl *, 16> AllParams;
36418c70b07SHaojian Wu       AllParams.reserve(TemplateParams->size() + InnerParams->size());
36518c70b07SHaojian Wu       AllParams.insert(AllParams.begin(), TemplateParams->begin(),
36618c70b07SHaojian Wu                        TemplateParams->end());
36718c70b07SHaojian Wu       SubstArgs.reserve(InnerParams->size());
36818c70b07SHaojian Wu       Depth1Args.reserve(InnerParams->size());
36918c70b07SHaojian Wu 
37018c70b07SHaojian Wu       // Later template parameters could refer to earlier ones, so build up
37118c70b07SHaojian Wu       // a list of substituted template arguments as we go.
37218c70b07SHaojian Wu       for (NamedDecl *Param : *InnerParams) {
37318c70b07SHaojian Wu         MultiLevelTemplateArgumentList Args;
37418c70b07SHaojian Wu         Args.setKind(TemplateSubstitutionKind::Rewrite);
37518c70b07SHaojian Wu         Args.addOuterTemplateArguments(Depth1Args);
37618c70b07SHaojian Wu         Args.addOuterRetainedLevel();
37718c70b07SHaojian Wu         if (NestedPattern)
37818c70b07SHaojian Wu           Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
379bb064535SYounan Zhang         auto [Depth, Index] = getDepthAndIndex(Param);
380bb064535SYounan Zhang         NamedDecl *NewParam = transformTemplateParameter(
381bb064535SYounan Zhang             SemaRef, DC, Param, Args, Index + Depth1IndexAdjustment, Depth - 1);
38218c70b07SHaojian Wu         if (!NewParam)
38318c70b07SHaojian Wu           return nullptr;
38418c70b07SHaojian Wu         // Constraints require that we substitute depth-1 arguments
38518c70b07SHaojian Wu         // to match depths when substituted for evaluation later
386c7bfc418SYounan Zhang         Depth1Args.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam));
38718c70b07SHaojian Wu 
38818c70b07SHaojian Wu         if (NestedPattern) {
389bb064535SYounan Zhang           auto [Depth, Index] = getDepthAndIndex(NewParam);
390bb064535SYounan Zhang           NewParam = transformTemplateParameter(
391bb064535SYounan Zhang               SemaRef, DC, NewParam, OuterInstantiationArgs, Index,
392bb064535SYounan Zhang               Depth - OuterInstantiationArgs.getNumSubstitutedLevels(),
393bb064535SYounan Zhang               /*EvaluateConstraint=*/false);
39418c70b07SHaojian Wu         }
39518c70b07SHaojian Wu 
396b46fcb9fSYounan Zhang         assert(getDepthAndIndex(NewParam).first == 0 &&
39718c70b07SHaojian Wu                "Unexpected template parameter depth");
39818c70b07SHaojian Wu 
39918c70b07SHaojian Wu         AllParams.push_back(NewParam);
400c7bfc418SYounan Zhang         SubstArgs.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam));
40118c70b07SHaojian Wu       }
40218c70b07SHaojian Wu 
40318c70b07SHaojian Wu       // Substitute new template parameters into requires-clause if present.
40418c70b07SHaojian Wu       Expr *RequiresClause = nullptr;
40518c70b07SHaojian Wu       if (Expr *InnerRC = InnerParams->getRequiresClause()) {
40618c70b07SHaojian Wu         MultiLevelTemplateArgumentList Args;
40718c70b07SHaojian Wu         Args.setKind(TemplateSubstitutionKind::Rewrite);
40818c70b07SHaojian Wu         Args.addOuterTemplateArguments(Depth1Args);
40918c70b07SHaojian Wu         Args.addOuterRetainedLevel();
41018c70b07SHaojian Wu         if (NestedPattern)
41118c70b07SHaojian Wu           Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
412b46fcb9fSYounan Zhang         ExprResult E =
413b46fcb9fSYounan Zhang             SemaRef.SubstConstraintExprWithoutSatisfaction(InnerRC, Args);
414b46fcb9fSYounan Zhang         if (!E.isUsable())
41518c70b07SHaojian Wu           return nullptr;
416b46fcb9fSYounan Zhang         RequiresClause = E.get();
41718c70b07SHaojian Wu       }
41818c70b07SHaojian Wu 
41918c70b07SHaojian Wu       TemplateParams = TemplateParameterList::Create(
42018c70b07SHaojian Wu           SemaRef.Context, InnerParams->getTemplateLoc(),
42118c70b07SHaojian Wu           InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),
42218c70b07SHaojian Wu           RequiresClause);
42318c70b07SHaojian Wu     }
42418c70b07SHaojian Wu 
42518c70b07SHaojian Wu     // If we built a new template-parameter-list, track that we need to
42618c70b07SHaojian Wu     // substitute references to the old parameters into references to the
42718c70b07SHaojian Wu     // new ones.
42818c70b07SHaojian Wu     MultiLevelTemplateArgumentList Args;
42918c70b07SHaojian Wu     Args.setKind(TemplateSubstitutionKind::Rewrite);
43018c70b07SHaojian Wu     if (FTD) {
43118c70b07SHaojian Wu       Args.addOuterTemplateArguments(SubstArgs);
43218c70b07SHaojian Wu       Args.addOuterRetainedLevel();
43318c70b07SHaojian Wu     }
43418c70b07SHaojian Wu 
43518c70b07SHaojian Wu     FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()
43618c70b07SHaojian Wu                                     ->getTypeLoc()
43718c70b07SHaojian Wu                                     .getAsAdjusted<FunctionProtoTypeLoc>();
43818c70b07SHaojian Wu     assert(FPTL && "no prototype for constructor declaration");
43918c70b07SHaojian Wu 
44018c70b07SHaojian Wu     // Transform the type of the function, adjusting the return type and
44118c70b07SHaojian Wu     // replacing references to the old parameters with references to the
44218c70b07SHaojian Wu     // new ones.
44318c70b07SHaojian Wu     TypeLocBuilder TLB;
44418c70b07SHaojian Wu     SmallVector<ParmVarDecl *, 8> Params;
44518c70b07SHaojian Wu     SmallVector<TypedefNameDecl *, 4> MaterializedTypedefs;
44618c70b07SHaojian Wu     QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args,
44718c70b07SHaojian Wu                                                   MaterializedTypedefs);
44818c70b07SHaojian Wu     if (NewType.isNull())
44918c70b07SHaojian Wu       return nullptr;
45018c70b07SHaojian Wu     TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
45118c70b07SHaojian Wu 
452b46fcb9fSYounan Zhang     // At this point, the function parameters are already 'instantiated' in the
453b46fcb9fSYounan Zhang     // current scope. Substitute into the constructor's trailing
454b46fcb9fSYounan Zhang     // requires-clause, if any.
455b46fcb9fSYounan Zhang     Expr *FunctionTrailingRC = nullptr;
456b46fcb9fSYounan Zhang     if (Expr *RC = CD->getTrailingRequiresClause()) {
457b46fcb9fSYounan Zhang       MultiLevelTemplateArgumentList Args;
458b46fcb9fSYounan Zhang       Args.setKind(TemplateSubstitutionKind::Rewrite);
459b46fcb9fSYounan Zhang       Args.addOuterTemplateArguments(Depth1Args);
460b46fcb9fSYounan Zhang       Args.addOuterRetainedLevel();
461b46fcb9fSYounan Zhang       if (NestedPattern)
462b46fcb9fSYounan Zhang         Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
463b46fcb9fSYounan Zhang       ExprResult E = SemaRef.SubstConstraintExprWithoutSatisfaction(RC, Args);
464b46fcb9fSYounan Zhang       if (!E.isUsable())
465b46fcb9fSYounan Zhang         return nullptr;
466b46fcb9fSYounan Zhang       FunctionTrailingRC = E.get();
467b46fcb9fSYounan Zhang     }
468b46fcb9fSYounan Zhang 
469b46fcb9fSYounan Zhang     // C++ [over.match.class.deduct]p1:
470b46fcb9fSYounan Zhang     // If C is defined, for each constructor of C, a function template with
471b46fcb9fSYounan Zhang     // the following properties:
472b46fcb9fSYounan Zhang     // [...]
473b46fcb9fSYounan Zhang     // - The associated constraints are the conjunction of the associated
474b46fcb9fSYounan Zhang     // constraints of C and the associated constraints of the constructor, if
475b46fcb9fSYounan Zhang     // any.
476b46fcb9fSYounan Zhang     if (OuterRC) {
477b46fcb9fSYounan Zhang       // The outer template parameters are not transformed, so their
478b46fcb9fSYounan Zhang       // associated constraints don't need substitution.
479b46fcb9fSYounan Zhang       if (!FunctionTrailingRC)
480b46fcb9fSYounan Zhang         FunctionTrailingRC = OuterRC;
481b46fcb9fSYounan Zhang       else
482b46fcb9fSYounan Zhang         FunctionTrailingRC = BinaryOperator::Create(
483b46fcb9fSYounan Zhang             SemaRef.Context, /*lhs=*/OuterRC, /*rhs=*/FunctionTrailingRC,
484b46fcb9fSYounan Zhang             BO_LAnd, SemaRef.Context.BoolTy, VK_PRValue, OK_Ordinary,
485b46fcb9fSYounan Zhang             TemplateParams->getTemplateLoc(), FPOptionsOverride());
486b46fcb9fSYounan Zhang     }
487b46fcb9fSYounan Zhang 
48818c70b07SHaojian Wu     return buildDeductionGuide(
48918c70b07SHaojian Wu         SemaRef, Template, TemplateParams, CD, CD->getExplicitSpecifier(),
49018c70b07SHaojian Wu         NewTInfo, CD->getBeginLoc(), CD->getLocation(), CD->getEndLoc(),
491b46fcb9fSYounan Zhang         /*IsImplicit=*/true, MaterializedTypedefs, FunctionTrailingRC);
49218c70b07SHaojian Wu   }
49318c70b07SHaojian Wu 
49418c70b07SHaojian Wu   /// Build a deduction guide with the specified parameter types.
49518c70b07SHaojian Wu   NamedDecl *buildSimpleDeductionGuide(MutableArrayRef<QualType> ParamTypes) {
49618c70b07SHaojian Wu     SourceLocation Loc = Template->getLocation();
49718c70b07SHaojian Wu 
49818c70b07SHaojian Wu     // Build the requested type.
49918c70b07SHaojian Wu     FunctionProtoType::ExtProtoInfo EPI;
50018c70b07SHaojian Wu     EPI.HasTrailingReturn = true;
50118c70b07SHaojian Wu     QualType Result = SemaRef.BuildFunctionType(DeducedType, ParamTypes, Loc,
50218c70b07SHaojian Wu                                                 DeductionGuideName, EPI);
50318c70b07SHaojian Wu     TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(Result, Loc);
50418c70b07SHaojian Wu     if (NestedPattern)
50518c70b07SHaojian Wu       TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,
50618c70b07SHaojian Wu                               DeductionGuideName);
50718c70b07SHaojian Wu 
50818c70b07SHaojian Wu     if (!TSI)
50918c70b07SHaojian Wu       return nullptr;
51018c70b07SHaojian Wu 
51118c70b07SHaojian Wu     FunctionProtoTypeLoc FPTL =
51218c70b07SHaojian Wu         TSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
51318c70b07SHaojian Wu 
51418c70b07SHaojian Wu     // Build the parameters, needed during deduction / substitution.
51518c70b07SHaojian Wu     SmallVector<ParmVarDecl *, 4> Params;
51618c70b07SHaojian Wu     for (auto T : ParamTypes) {
51718c70b07SHaojian Wu       auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T, Loc);
51818c70b07SHaojian Wu       if (NestedPattern)
51918c70b07SHaojian Wu         TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc,
52018c70b07SHaojian Wu                                 DeclarationName());
52118c70b07SHaojian Wu       if (!TSI)
52218c70b07SHaojian Wu         return nullptr;
52318c70b07SHaojian Wu 
52418c70b07SHaojian Wu       ParmVarDecl *NewParam =
52518c70b07SHaojian Wu           ParmVarDecl::Create(SemaRef.Context, DC, Loc, Loc, nullptr,
52618c70b07SHaojian Wu                               TSI->getType(), TSI, SC_None, nullptr);
52718c70b07SHaojian Wu       NewParam->setScopeInfo(0, Params.size());
52818c70b07SHaojian Wu       FPTL.setParam(Params.size(), NewParam);
52918c70b07SHaojian Wu       Params.push_back(NewParam);
53018c70b07SHaojian Wu     }
53118c70b07SHaojian Wu 
53218c70b07SHaojian Wu     return buildDeductionGuide(
53318c70b07SHaojian Wu         SemaRef, Template, SemaRef.GetTemplateParameterList(Template), nullptr,
53418c70b07SHaojian Wu         ExplicitSpecifier(), TSI, Loc, Loc, Loc, /*IsImplicit=*/true);
53518c70b07SHaojian Wu   }
53618c70b07SHaojian Wu 
53718c70b07SHaojian Wu private:
53818c70b07SHaojian Wu   QualType transformFunctionProtoType(
53918c70b07SHaojian Wu       TypeLocBuilder &TLB, FunctionProtoTypeLoc TL,
54018c70b07SHaojian Wu       SmallVectorImpl<ParmVarDecl *> &Params,
54118c70b07SHaojian Wu       MultiLevelTemplateArgumentList &Args,
54218c70b07SHaojian Wu       SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) {
54318c70b07SHaojian Wu     SmallVector<QualType, 4> ParamTypes;
54418c70b07SHaojian Wu     const FunctionProtoType *T = TL.getTypePtr();
54518c70b07SHaojian Wu 
54618c70b07SHaojian Wu     //    -- The types of the function parameters are those of the constructor.
54718c70b07SHaojian Wu     for (auto *OldParam : TL.getParams()) {
54818c70b07SHaojian Wu       ParmVarDecl *NewParam = OldParam;
54918c70b07SHaojian Wu       // Given
55018c70b07SHaojian Wu       //   template <class T> struct C {
55118c70b07SHaojian Wu       //     template <class U> struct D {
55218c70b07SHaojian Wu       //       template <class V> D(U, V);
55318c70b07SHaojian Wu       //     };
55418c70b07SHaojian Wu       //   };
55518c70b07SHaojian Wu       // First, transform all the references to template parameters that are
55618c70b07SHaojian Wu       // defined outside of the surrounding class template. That is T in the
55718c70b07SHaojian Wu       // above example.
55818c70b07SHaojian Wu       if (NestedPattern) {
55918c70b07SHaojian Wu         NewParam = transformFunctionTypeParam(
56018c70b07SHaojian Wu             NewParam, OuterInstantiationArgs, MaterializedTypedefs,
56118c70b07SHaojian Wu             /*TransformingOuterPatterns=*/true);
56218c70b07SHaojian Wu         if (!NewParam)
56318c70b07SHaojian Wu           return QualType();
56418c70b07SHaojian Wu       }
56518c70b07SHaojian Wu       // Then, transform all the references to template parameters that are
56618c70b07SHaojian Wu       // defined at the class template and the constructor. In this example,
56718c70b07SHaojian Wu       // they're U and V, respectively.
56818c70b07SHaojian Wu       NewParam =
56918c70b07SHaojian Wu           transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs,
57018c70b07SHaojian Wu                                      /*TransformingOuterPatterns=*/false);
57118c70b07SHaojian Wu       if (!NewParam)
57218c70b07SHaojian Wu         return QualType();
57318c70b07SHaojian Wu       ParamTypes.push_back(NewParam->getType());
57418c70b07SHaojian Wu       Params.push_back(NewParam);
57518c70b07SHaojian Wu     }
57618c70b07SHaojian Wu 
57718c70b07SHaojian Wu     //    -- The return type is the class template specialization designated by
57818c70b07SHaojian Wu     //       the template-name and template arguments corresponding to the
57918c70b07SHaojian Wu     //       template parameters obtained from the class template.
58018c70b07SHaojian Wu     //
58118c70b07SHaojian Wu     // We use the injected-class-name type of the primary template instead.
58218c70b07SHaojian Wu     // This has the convenient property that it is different from any type that
58318c70b07SHaojian Wu     // the user can write in a deduction-guide (because they cannot enter the
58418c70b07SHaojian Wu     // context of the template), so implicit deduction guides can never collide
58518c70b07SHaojian Wu     // with explicit ones.
58618c70b07SHaojian Wu     QualType ReturnType = DeducedType;
58718c70b07SHaojian Wu     TLB.pushTypeSpec(ReturnType).setNameLoc(Primary->getLocation());
58818c70b07SHaojian Wu 
58918c70b07SHaojian Wu     // Resolving a wording defect, we also inherit the variadicness of the
59018c70b07SHaojian Wu     // constructor.
59118c70b07SHaojian Wu     FunctionProtoType::ExtProtoInfo EPI;
59218c70b07SHaojian Wu     EPI.Variadic = T->isVariadic();
59318c70b07SHaojian Wu     EPI.HasTrailingReturn = true;
59418c70b07SHaojian Wu 
59518c70b07SHaojian Wu     QualType Result = SemaRef.BuildFunctionType(
59618c70b07SHaojian Wu         ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI);
59718c70b07SHaojian Wu     if (Result.isNull())
59818c70b07SHaojian Wu       return QualType();
59918c70b07SHaojian Wu 
60018c70b07SHaojian Wu     FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
60118c70b07SHaojian Wu     NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
60218c70b07SHaojian Wu     NewTL.setLParenLoc(TL.getLParenLoc());
60318c70b07SHaojian Wu     NewTL.setRParenLoc(TL.getRParenLoc());
60418c70b07SHaojian Wu     NewTL.setExceptionSpecRange(SourceRange());
60518c70b07SHaojian Wu     NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
60618c70b07SHaojian Wu     for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I)
60718c70b07SHaojian Wu       NewTL.setParam(I, Params[I]);
60818c70b07SHaojian Wu 
60918c70b07SHaojian Wu     return Result;
61018c70b07SHaojian Wu   }
61118c70b07SHaojian Wu 
61218c70b07SHaojian Wu   ParmVarDecl *transformFunctionTypeParam(
61318c70b07SHaojian Wu       ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args,
61418c70b07SHaojian Wu       llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
61518c70b07SHaojian Wu       bool TransformingOuterPatterns) {
61618c70b07SHaojian Wu     TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
61718c70b07SHaojian Wu     TypeSourceInfo *NewDI;
61818c70b07SHaojian Wu     if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) {
61918c70b07SHaojian Wu       // Expand out the one and only element in each inner pack.
62018c70b07SHaojian Wu       Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0);
62118c70b07SHaojian Wu       NewDI =
62218c70b07SHaojian Wu           SemaRef.SubstType(PackTL.getPatternLoc(), Args,
62318c70b07SHaojian Wu                             OldParam->getLocation(), OldParam->getDeclName());
62418c70b07SHaojian Wu       if (!NewDI)
62518c70b07SHaojian Wu         return nullptr;
62618c70b07SHaojian Wu       NewDI =
62718c70b07SHaojian Wu           SemaRef.CheckPackExpansion(NewDI, PackTL.getEllipsisLoc(),
62818c70b07SHaojian Wu                                      PackTL.getTypePtr()->getNumExpansions());
62918c70b07SHaojian Wu     } else
63018c70b07SHaojian Wu       NewDI = SemaRef.SubstType(OldDI, Args, OldParam->getLocation(),
63118c70b07SHaojian Wu                                 OldParam->getDeclName());
63218c70b07SHaojian Wu     if (!NewDI)
63318c70b07SHaojian Wu       return nullptr;
63418c70b07SHaojian Wu 
63518c70b07SHaojian Wu     // Extract the type. This (for instance) replaces references to typedef
63618c70b07SHaojian Wu     // members of the current instantiations with the definitions of those
63718c70b07SHaojian Wu     // typedefs, avoiding triggering instantiation of the deduced type during
63818c70b07SHaojian Wu     // deduction.
63918c70b07SHaojian Wu     NewDI = ExtractTypeForDeductionGuide(
64018c70b07SHaojian Wu                 SemaRef, MaterializedTypedefs, NestedPattern,
64118c70b07SHaojian Wu                 TransformingOuterPatterns ? &Args : nullptr)
64218c70b07SHaojian Wu                 .transform(NewDI);
64318c70b07SHaojian Wu 
64418c70b07SHaojian Wu     // Resolving a wording defect, we also inherit default arguments from the
64518c70b07SHaojian Wu     // constructor.
64618c70b07SHaojian Wu     ExprResult NewDefArg;
64718c70b07SHaojian Wu     if (OldParam->hasDefaultArg()) {
64818c70b07SHaojian Wu       // We don't care what the value is (we won't use it); just create a
64918c70b07SHaojian Wu       // placeholder to indicate there is a default argument.
65018c70b07SHaojian Wu       QualType ParamTy = NewDI->getType();
65118c70b07SHaojian Wu       NewDefArg = new (SemaRef.Context)
65218c70b07SHaojian Wu           OpaqueValueExpr(OldParam->getDefaultArgRange().getBegin(),
65318c70b07SHaojian Wu                           ParamTy.getNonLValueExprType(SemaRef.Context),
65418c70b07SHaojian Wu                           ParamTy->isLValueReferenceType()   ? VK_LValue
65518c70b07SHaojian Wu                           : ParamTy->isRValueReferenceType() ? VK_XValue
65618c70b07SHaojian Wu                                                              : VK_PRValue);
65718c70b07SHaojian Wu     }
65818c70b07SHaojian Wu     // Handle arrays and functions decay.
65918c70b07SHaojian Wu     auto NewType = NewDI->getType();
66018c70b07SHaojian Wu     if (NewType->isArrayType() || NewType->isFunctionType())
66118c70b07SHaojian Wu       NewType = SemaRef.Context.getDecayedType(NewType);
66218c70b07SHaojian Wu 
66318c70b07SHaojian Wu     ParmVarDecl *NewParam = ParmVarDecl::Create(
66418c70b07SHaojian Wu         SemaRef.Context, DC, OldParam->getInnerLocStart(),
66518c70b07SHaojian Wu         OldParam->getLocation(), OldParam->getIdentifier(), NewType, NewDI,
66618c70b07SHaojian Wu         OldParam->getStorageClass(), NewDefArg.get());
66718c70b07SHaojian Wu     NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
66818c70b07SHaojian Wu                            OldParam->getFunctionScopeIndex());
66918c70b07SHaojian Wu     SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
67018c70b07SHaojian Wu     return NewParam;
67118c70b07SHaojian Wu   }
67218c70b07SHaojian Wu };
67318c70b07SHaojian Wu 
67418c70b07SHaojian Wu // Find all template parameters that appear in the given DeducedArgs.
67518c70b07SHaojian Wu // Return the indices of the template parameters in the TemplateParams.
67618c70b07SHaojian Wu SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
67718c70b07SHaojian Wu     const TemplateParameterList *TemplateParamsList,
67818c70b07SHaojian Wu     ArrayRef<TemplateArgument> DeducedArgs) {
679dde802b1SSirraide   struct TemplateParamsReferencedFinder : DynamicRecursiveASTVisitor {
68018c70b07SHaojian Wu     const TemplateParameterList *TemplateParamList;
68118c70b07SHaojian Wu     llvm::BitVector ReferencedTemplateParams;
68218c70b07SHaojian Wu 
68318c70b07SHaojian Wu     TemplateParamsReferencedFinder(
68418c70b07SHaojian Wu         const TemplateParameterList *TemplateParamList)
68518c70b07SHaojian Wu         : TemplateParamList(TemplateParamList),
68618c70b07SHaojian Wu           ReferencedTemplateParams(TemplateParamList->size()) {}
68718c70b07SHaojian Wu 
688dde802b1SSirraide     bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) override {
68918c70b07SHaojian Wu       // We use the index and depth to retrieve the corresponding template
69018c70b07SHaojian Wu       // parameter from the parameter list, which is more robost.
69118c70b07SHaojian Wu       Mark(TTP->getDepth(), TTP->getIndex());
69218c70b07SHaojian Wu       return true;
69318c70b07SHaojian Wu     }
69418c70b07SHaojian Wu 
695dde802b1SSirraide     bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
69618c70b07SHaojian Wu       MarkAppeared(DRE->getFoundDecl());
69718c70b07SHaojian Wu       return true;
69818c70b07SHaojian Wu     }
69918c70b07SHaojian Wu 
700dde802b1SSirraide     bool TraverseTemplateName(TemplateName Template) override {
70118c70b07SHaojian Wu       if (auto *TD = Template.getAsTemplateDecl())
70218c70b07SHaojian Wu         MarkAppeared(TD);
703dde802b1SSirraide       return DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
70418c70b07SHaojian Wu     }
70518c70b07SHaojian Wu 
70618c70b07SHaojian Wu     void MarkAppeared(NamedDecl *ND) {
70718c70b07SHaojian Wu       if (llvm::isa<NonTypeTemplateParmDecl, TemplateTypeParmDecl,
708bb064535SYounan Zhang                     TemplateTemplateParmDecl>(ND)) {
709bb064535SYounan Zhang         auto [Depth, Index] = getDepthAndIndex(ND);
710bb064535SYounan Zhang         Mark(Depth, Index);
711bb064535SYounan Zhang       }
71218c70b07SHaojian Wu     }
71318c70b07SHaojian Wu     void Mark(unsigned Depth, unsigned Index) {
71418c70b07SHaojian Wu       if (Index < TemplateParamList->size() &&
71518c70b07SHaojian Wu           TemplateParamList->getParam(Index)->getTemplateDepth() == Depth)
71618c70b07SHaojian Wu         ReferencedTemplateParams.set(Index);
71718c70b07SHaojian Wu     }
71818c70b07SHaojian Wu   };
71918c70b07SHaojian Wu   TemplateParamsReferencedFinder Finder(TemplateParamsList);
72018c70b07SHaojian Wu   Finder.TraverseTemplateArguments(DeducedArgs);
72118c70b07SHaojian Wu 
72218c70b07SHaojian Wu   SmallVector<unsigned> Results;
72318c70b07SHaojian Wu   for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {
72418c70b07SHaojian Wu     if (Finder.ReferencedTemplateParams[Index])
72518c70b07SHaojian Wu       Results.push_back(Index);
72618c70b07SHaojian Wu   }
72718c70b07SHaojian Wu   return Results;
72818c70b07SHaojian Wu }
72918c70b07SHaojian Wu 
73018c70b07SHaojian Wu bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
73118c70b07SHaojian Wu   // Check whether we've already declared deduction guides for this template.
73218c70b07SHaojian Wu   // FIXME: Consider storing a flag on the template to indicate this.
73318c70b07SHaojian Wu   assert(Name.getNameKind() ==
73418c70b07SHaojian Wu              DeclarationName::NameKind::CXXDeductionGuideName &&
73518c70b07SHaojian Wu          "name must be a deduction guide name");
73618c70b07SHaojian Wu   auto Existing = DC->lookup(Name);
73718c70b07SHaojian Wu   for (auto *D : Existing)
73818c70b07SHaojian Wu     if (D->isImplicit())
73918c70b07SHaojian Wu       return true;
74018c70b07SHaojian Wu   return false;
74118c70b07SHaojian Wu }
74218c70b07SHaojian Wu 
74318c70b07SHaojian Wu // Build the associated constraints for the alias deduction guides.
74418c70b07SHaojian Wu // C++ [over.match.class.deduct]p3.3:
74518c70b07SHaojian Wu //   The associated constraints ([temp.constr.decl]) are the conjunction of the
74618c70b07SHaojian Wu //   associated constraints of g and a constraint that is satisfied if and only
74718c70b07SHaojian Wu //   if the arguments of A are deducible (see below) from the return type.
74818c70b07SHaojian Wu //
74918c70b07SHaojian Wu // The return result is expected to be the require-clause for the synthesized
75018c70b07SHaojian Wu // alias deduction guide.
75118c70b07SHaojian Wu Expr *
75218c70b07SHaojian Wu buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
75318c70b07SHaojian Wu                            TypeAliasTemplateDecl *AliasTemplate,
75418c70b07SHaojian Wu                            ArrayRef<DeducedTemplateArgument> DeduceResults,
75518c70b07SHaojian Wu                            unsigned FirstUndeducedParamIdx, Expr *IsDeducible) {
75618c70b07SHaojian Wu   Expr *RC = F->getTemplateParameters()->getRequiresClause();
75718c70b07SHaojian Wu   if (!RC)
75818c70b07SHaojian Wu     return IsDeducible;
75918c70b07SHaojian Wu 
76018c70b07SHaojian Wu   ASTContext &Context = SemaRef.Context;
76118c70b07SHaojian Wu   LocalInstantiationScope Scope(SemaRef);
76218c70b07SHaojian Wu 
76318c70b07SHaojian Wu   // In the clang AST, constraint nodes are deliberately not instantiated unless
76418c70b07SHaojian Wu   // they are actively being evaluated. Consequently, occurrences of template
76518c70b07SHaojian Wu   // parameters in the require-clause expression have a subtle "depth"
76618c70b07SHaojian Wu   // difference compared to normal occurrences in places, such as function
76718c70b07SHaojian Wu   // parameters. When transforming the require-clause, we must take this
76818c70b07SHaojian Wu   // distinction into account:
76918c70b07SHaojian Wu   //
77018c70b07SHaojian Wu   //   1) In the transformed require-clause, occurrences of template parameters
77118c70b07SHaojian Wu   //   must use the "uninstantiated" depth;
77218c70b07SHaojian Wu   //   2) When substituting on the require-clause expr of the underlying
77318c70b07SHaojian Wu   //   deduction guide, we must use the entire set of template argument lists;
77418c70b07SHaojian Wu   //
77518c70b07SHaojian Wu   // It's important to note that we're performing this transformation on an
77618c70b07SHaojian Wu   // *instantiated* AliasTemplate.
77718c70b07SHaojian Wu 
77818c70b07SHaojian Wu   // For 1), if the alias template is nested within a class template, we
77918c70b07SHaojian Wu   // calcualte the 'uninstantiated' depth by adding the substitution level back.
78018c70b07SHaojian Wu   unsigned AdjustDepth = 0;
78118c70b07SHaojian Wu   if (auto *PrimaryTemplate =
78218c70b07SHaojian Wu           AliasTemplate->getInstantiatedFromMemberTemplate())
78318c70b07SHaojian Wu     AdjustDepth = PrimaryTemplate->getTemplateDepth();
78418c70b07SHaojian Wu 
78518c70b07SHaojian Wu   // We rebuild all template parameters with the uninstantiated depth, and
78618c70b07SHaojian Wu   // build template arguments refer to them.
78718c70b07SHaojian Wu   SmallVector<TemplateArgument> AdjustedAliasTemplateArgs;
78818c70b07SHaojian Wu 
78918c70b07SHaojian Wu   for (auto *TP : *AliasTemplate->getTemplateParameters()) {
79018c70b07SHaojian Wu     // Rebuild any internal references to earlier parameters and reindex
79118c70b07SHaojian Wu     // as we go.
79218c70b07SHaojian Wu     MultiLevelTemplateArgumentList Args;
79318c70b07SHaojian Wu     Args.setKind(TemplateSubstitutionKind::Rewrite);
79418c70b07SHaojian Wu     Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs);
79518c70b07SHaojian Wu     NamedDecl *NewParam = transformTemplateParameter(
79618c70b07SHaojian Wu         SemaRef, AliasTemplate->getDeclContext(), TP, Args,
79718c70b07SHaojian Wu         /*NewIndex=*/AdjustedAliasTemplateArgs.size(),
798bb064535SYounan Zhang         getDepthAndIndex(TP).first + AdjustDepth);
79918c70b07SHaojian Wu 
800c7bfc418SYounan Zhang     TemplateArgument NewTemplateArgument =
801c7bfc418SYounan Zhang         Context.getInjectedTemplateArg(NewParam);
80218c70b07SHaojian Wu     AdjustedAliasTemplateArgs.push_back(NewTemplateArgument);
80318c70b07SHaojian Wu   }
80418c70b07SHaojian Wu   // Template arguments used to transform the template arguments in
80518c70b07SHaojian Wu   // DeducedResults.
80644ab3805SKrystian Stasiowski   SmallVector<TemplateArgument> TemplateArgsForBuildingRC(
80718c70b07SHaojian Wu       F->getTemplateParameters()->size());
80818c70b07SHaojian Wu   // Transform the transformed template args
80918c70b07SHaojian Wu   MultiLevelTemplateArgumentList Args;
81018c70b07SHaojian Wu   Args.setKind(TemplateSubstitutionKind::Rewrite);
81118c70b07SHaojian Wu   Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs);
81218c70b07SHaojian Wu 
81318c70b07SHaojian Wu   for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
81418c70b07SHaojian Wu     const auto &D = DeduceResults[Index];
81518c70b07SHaojian Wu     if (D.isNull()) { // non-deduced template parameters of f
81618c70b07SHaojian Wu       NamedDecl *TP = F->getTemplateParameters()->getParam(Index);
81718c70b07SHaojian Wu       MultiLevelTemplateArgumentList Args;
81818c70b07SHaojian Wu       Args.setKind(TemplateSubstitutionKind::Rewrite);
81944ab3805SKrystian Stasiowski       Args.addOuterTemplateArguments(TemplateArgsForBuildingRC);
82018c70b07SHaojian Wu       // Rebuild the template parameter with updated depth and index.
821bb064535SYounan Zhang       NamedDecl *NewParam =
822bb064535SYounan Zhang           transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,
82318c70b07SHaojian Wu                                      /*NewIndex=*/FirstUndeducedParamIdx,
824bb064535SYounan Zhang                                      getDepthAndIndex(TP).first + AdjustDepth);
82518c70b07SHaojian Wu       FirstUndeducedParamIdx += 1;
82644ab3805SKrystian Stasiowski       assert(TemplateArgsForBuildingRC[Index].isNull());
82744ab3805SKrystian Stasiowski       TemplateArgsForBuildingRC[Index] =
82844ab3805SKrystian Stasiowski           Context.getInjectedTemplateArg(NewParam);
82918c70b07SHaojian Wu       continue;
83018c70b07SHaojian Wu     }
83118c70b07SHaojian Wu     TemplateArgumentLoc Input =
83218c70b07SHaojian Wu         SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{});
83318c70b07SHaojian Wu     TemplateArgumentLoc Output;
83418c70b07SHaojian Wu     if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) {
83544ab3805SKrystian Stasiowski       assert(TemplateArgsForBuildingRC[Index].isNull() &&
83618c70b07SHaojian Wu              "InstantiatedArgs must be null before setting");
83744ab3805SKrystian Stasiowski       TemplateArgsForBuildingRC[Index] = Output.getArgument();
83818c70b07SHaojian Wu     }
83918c70b07SHaojian Wu   }
84018c70b07SHaojian Wu 
84144ab3805SKrystian Stasiowski   // A list of template arguments for transforming the require-clause of F.
84244ab3805SKrystian Stasiowski   // It must contain the entire set of template argument lists.
84344ab3805SKrystian Stasiowski   MultiLevelTemplateArgumentList ArgsForBuildingRC;
84444ab3805SKrystian Stasiowski   ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
84544ab3805SKrystian Stasiowski   ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC);
84618c70b07SHaojian Wu   // For 2), if the underlying deduction guide F is nested in a class template,
84718c70b07SHaojian Wu   // we need the entire template argument list, as the constraint AST in the
84818c70b07SHaojian Wu   // require-clause of F remains completely uninstantiated.
84918c70b07SHaojian Wu   //
85018c70b07SHaojian Wu   // For example:
85118c70b07SHaojian Wu   //   template <typename T> // depth 0
85218c70b07SHaojian Wu   //   struct Outer {
85318c70b07SHaojian Wu   //      template <typename U>
85418c70b07SHaojian Wu   //      struct Foo { Foo(U); };
85518c70b07SHaojian Wu   //
85618c70b07SHaojian Wu   //      template <typename U> // depth 1
85718c70b07SHaojian Wu   //      requires C<U>
85818c70b07SHaojian Wu   //      Foo(U) -> Foo<int>;
85918c70b07SHaojian Wu   //   };
86018c70b07SHaojian Wu   //   template <typename U>
86118c70b07SHaojian Wu   //   using AFoo = Outer<int>::Foo<U>;
86218c70b07SHaojian Wu   //
86318c70b07SHaojian Wu   // In this scenario, the deduction guide for `Foo` inside `Outer<int>`:
86418c70b07SHaojian Wu   //   - The occurrence of U in the require-expression is [depth:1, index:0]
86518c70b07SHaojian Wu   //   - The occurrence of U in the function parameter is [depth:0, index:0]
86618c70b07SHaojian Wu   //   - The template parameter of U is [depth:0, index:0]
86718c70b07SHaojian Wu   //
86844ab3805SKrystian Stasiowski   // We add the outer template arguments which is [int] to the multi-level arg
86944ab3805SKrystian Stasiowski   // list to ensure that the occurrence U in `C<U>` will be replaced with int
87044ab3805SKrystian Stasiowski   // during the substitution.
87144ab3805SKrystian Stasiowski   //
87218c70b07SHaojian Wu   // NOTE: The underlying deduction guide F is instantiated -- either from an
87318c70b07SHaojian Wu   // explicitly-written deduction guide member, or from a constructor.
87444ab3805SKrystian Stasiowski   // getInstantiatedFromMemberTemplate() can only handle the former case, so we
87544ab3805SKrystian Stasiowski   // check the DeclContext kind.
87644ab3805SKrystian Stasiowski   if (F->getLexicalDeclContext()->getDeclKind() ==
87744ab3805SKrystian Stasiowski       clang::Decl::ClassTemplateSpecialization) {
87844ab3805SKrystian Stasiowski     auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs(
87944ab3805SKrystian Stasiowski         F, F->getLexicalDeclContext(),
88044ab3805SKrystian Stasiowski         /*Final=*/false, /*Innermost=*/std::nullopt,
88118c70b07SHaojian Wu         /*RelativeToPrimary=*/true,
88244ab3805SKrystian Stasiowski         /*Pattern=*/nullptr,
88318c70b07SHaojian Wu         /*ForConstraintInstantiation=*/true);
88444ab3805SKrystian Stasiowski     for (auto It : OuterLevelArgs)
88544ab3805SKrystian Stasiowski       ArgsForBuildingRC.addOuterTemplateArguments(It.Args);
88644ab3805SKrystian Stasiowski   }
88718c70b07SHaojian Wu 
88818c70b07SHaojian Wu   ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
88918c70b07SHaojian Wu   if (E.isInvalid())
89018c70b07SHaojian Wu     return nullptr;
89118c70b07SHaojian Wu 
89218c70b07SHaojian Wu   auto Conjunction =
89318c70b07SHaojian Wu       SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{},
89418c70b07SHaojian Wu                          BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible);
89518c70b07SHaojian Wu   if (Conjunction.isInvalid())
89618c70b07SHaojian Wu     return nullptr;
89718c70b07SHaojian Wu   return Conjunction.getAs<Expr>();
89818c70b07SHaojian Wu }
89918c70b07SHaojian Wu // Build the is_deducible constraint for the alias deduction guides.
90018c70b07SHaojian Wu // [over.match.class.deduct]p3.3:
90118c70b07SHaojian Wu //    ... and a constraint that is satisfied if and only if the arguments
90218c70b07SHaojian Wu //    of A are deducible (see below) from the return type.
90318c70b07SHaojian Wu Expr *buildIsDeducibleConstraint(Sema &SemaRef,
90418c70b07SHaojian Wu                                  TypeAliasTemplateDecl *AliasTemplate,
90518c70b07SHaojian Wu                                  QualType ReturnType,
90618c70b07SHaojian Wu                                  SmallVector<NamedDecl *> TemplateParams) {
90718c70b07SHaojian Wu   ASTContext &Context = SemaRef.Context;
90818c70b07SHaojian Wu   // Constraint AST nodes must use uninstantiated depth.
90918c70b07SHaojian Wu   if (auto *PrimaryTemplate =
91018c70b07SHaojian Wu           AliasTemplate->getInstantiatedFromMemberTemplate();
91118c70b07SHaojian Wu       PrimaryTemplate && TemplateParams.size() > 0) {
91218c70b07SHaojian Wu     LocalInstantiationScope Scope(SemaRef);
91318c70b07SHaojian Wu 
91418c70b07SHaojian Wu     // Adjust the depth for TemplateParams.
91518c70b07SHaojian Wu     unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth();
91618c70b07SHaojian Wu     SmallVector<TemplateArgument> TransformedTemplateArgs;
91718c70b07SHaojian Wu     for (auto *TP : TemplateParams) {
91818c70b07SHaojian Wu       // Rebuild any internal references to earlier parameters and reindex
91918c70b07SHaojian Wu       // as we go.
92018c70b07SHaojian Wu       MultiLevelTemplateArgumentList Args;
92118c70b07SHaojian Wu       Args.setKind(TemplateSubstitutionKind::Rewrite);
92218c70b07SHaojian Wu       Args.addOuterTemplateArguments(TransformedTemplateArgs);
92318c70b07SHaojian Wu       NamedDecl *NewParam = transformTemplateParameter(
92418c70b07SHaojian Wu           SemaRef, AliasTemplate->getDeclContext(), TP, Args,
92518c70b07SHaojian Wu           /*NewIndex=*/TransformedTemplateArgs.size(),
926bb064535SYounan Zhang           getDepthAndIndex(TP).first + AdjustDepth);
92718c70b07SHaojian Wu 
928c7bfc418SYounan Zhang       TemplateArgument NewTemplateArgument =
929c7bfc418SYounan Zhang           Context.getInjectedTemplateArg(NewParam);
93018c70b07SHaojian Wu       TransformedTemplateArgs.push_back(NewTemplateArgument);
93118c70b07SHaojian Wu     }
93218c70b07SHaojian Wu     // Transformed the ReturnType to restore the uninstantiated depth.
93318c70b07SHaojian Wu     MultiLevelTemplateArgumentList Args;
93418c70b07SHaojian Wu     Args.setKind(TemplateSubstitutionKind::Rewrite);
93518c70b07SHaojian Wu     Args.addOuterTemplateArguments(TransformedTemplateArgs);
93618c70b07SHaojian Wu     ReturnType = SemaRef.SubstType(
93718c70b07SHaojian Wu         ReturnType, Args, AliasTemplate->getLocation(),
93818c70b07SHaojian Wu         Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate));
93918c70b07SHaojian Wu   };
94018c70b07SHaojian Wu 
94118c70b07SHaojian Wu   SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = {
94218c70b07SHaojian Wu       Context.getTrivialTypeSourceInfo(
94318c70b07SHaojian Wu           Context.getDeducedTemplateSpecializationType(
94418c70b07SHaojian Wu               TemplateName(AliasTemplate), /*DeducedType=*/QualType(),
9453972ed57SYounan Zhang               /*IsDependent=*/true)), // template specialization type whose
94618c70b07SHaojian Wu                                       // arguments will be deduced.
94718c70b07SHaojian Wu       Context.getTrivialTypeSourceInfo(
9483972ed57SYounan Zhang           ReturnType), // type from which template arguments are deduced.
94918c70b07SHaojian Wu   };
95018c70b07SHaojian Wu   return TypeTraitExpr::Create(
95118c70b07SHaojian Wu       Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(),
95218c70b07SHaojian Wu       TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs,
95318c70b07SHaojian Wu       AliasTemplate->getLocation(), /*Value*/ false);
95418c70b07SHaojian Wu }
95518c70b07SHaojian Wu 
95618c70b07SHaojian Wu std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>>
95718c70b07SHaojian Wu getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
95818c70b07SHaojian Wu   // Unwrap the sugared ElaboratedType.
95918c70b07SHaojian Wu   auto RhsType = AliasTemplate->getTemplatedDecl()
96018c70b07SHaojian Wu                      ->getUnderlyingType()
96118c70b07SHaojian Wu                      .getSingleStepDesugaredType(SemaRef.Context);
96218c70b07SHaojian Wu   TemplateDecl *Template = nullptr;
96318c70b07SHaojian Wu   llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs;
96418c70b07SHaojian Wu   if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) {
96518c70b07SHaojian Wu     // Cases where the RHS of the alias is dependent. e.g.
96618c70b07SHaojian Wu     //   template<typename T>
96718c70b07SHaojian Wu     //   using AliasFoo1 = Foo<T>; // a class/type alias template specialization
96818c70b07SHaojian Wu     Template = TST->getTemplateName().getAsTemplateDecl();
96918c70b07SHaojian Wu     AliasRhsTemplateArgs = TST->template_arguments();
97018c70b07SHaojian Wu   } else if (const auto *RT = RhsType->getAs<RecordType>()) {
97118c70b07SHaojian Wu     // Cases where template arguments in the RHS of the alias are not
97218c70b07SHaojian Wu     // dependent. e.g.
97318c70b07SHaojian Wu     //   using AliasFoo = Foo<bool>;
97418c70b07SHaojian Wu     if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(
97518c70b07SHaojian Wu             RT->getAsCXXRecordDecl())) {
97618c70b07SHaojian Wu       Template = CTSD->getSpecializedTemplate();
97718c70b07SHaojian Wu       AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
97818c70b07SHaojian Wu     }
97918c70b07SHaojian Wu   } else {
98018c70b07SHaojian Wu     assert(false && "unhandled RHS type of the alias");
98118c70b07SHaojian Wu   }
98218c70b07SHaojian Wu   return {Template, AliasRhsTemplateArgs};
98318c70b07SHaojian Wu }
98418c70b07SHaojian Wu 
98518c70b07SHaojian Wu // Build deduction guides for a type alias template from the given underlying
98618c70b07SHaojian Wu // deduction guide F.
98718c70b07SHaojian Wu FunctionTemplateDecl *
98818c70b07SHaojian Wu BuildDeductionGuideForTypeAlias(Sema &SemaRef,
98918c70b07SHaojian Wu                                 TypeAliasTemplateDecl *AliasTemplate,
99018c70b07SHaojian Wu                                 FunctionTemplateDecl *F, SourceLocation Loc) {
99118c70b07SHaojian Wu   LocalInstantiationScope Scope(SemaRef);
99218c70b07SHaojian Wu   Sema::InstantiatingTemplate BuildingDeductionGuides(
99318c70b07SHaojian Wu       SemaRef, AliasTemplate->getLocation(), F,
99418c70b07SHaojian Wu       Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
99518c70b07SHaojian Wu   if (BuildingDeductionGuides.isInvalid())
99618c70b07SHaojian Wu     return nullptr;
99718c70b07SHaojian Wu 
99818c70b07SHaojian Wu   auto &Context = SemaRef.Context;
99918c70b07SHaojian Wu   auto [Template, AliasRhsTemplateArgs] =
100018c70b07SHaojian Wu       getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
100118c70b07SHaojian Wu 
100218c70b07SHaojian Wu   auto RType = F->getTemplatedDecl()->getReturnType();
100318c70b07SHaojian Wu   // The (trailing) return type of the deduction guide.
100418c70b07SHaojian Wu   const TemplateSpecializationType *FReturnType =
100518c70b07SHaojian Wu       RType->getAs<TemplateSpecializationType>();
100618c70b07SHaojian Wu   if (const auto *InjectedCNT = RType->getAs<InjectedClassNameType>())
100718c70b07SHaojian Wu     // implicitly-generated deduction guide.
100818c70b07SHaojian Wu     FReturnType = InjectedCNT->getInjectedTST();
100918c70b07SHaojian Wu   else if (const auto *ET = RType->getAs<ElaboratedType>())
101018c70b07SHaojian Wu     // explicit deduction guide.
101118c70b07SHaojian Wu     FReturnType = ET->getNamedType()->getAs<TemplateSpecializationType>();
101218c70b07SHaojian Wu   assert(FReturnType && "expected to see a return type");
101318c70b07SHaojian Wu   // Deduce template arguments of the deduction guide f from the RHS of
101418c70b07SHaojian Wu   // the alias.
101518c70b07SHaojian Wu   //
101618c70b07SHaojian Wu   // C++ [over.match.class.deduct]p3: ...For each function or function
101718c70b07SHaojian Wu   // template f in the guides of the template named by the
101818c70b07SHaojian Wu   // simple-template-id of the defining-type-id, the template arguments
101918c70b07SHaojian Wu   // of the return type of f are deduced from the defining-type-id of A
102018c70b07SHaojian Wu   // according to the process in [temp.deduct.type] with the exception
102118c70b07SHaojian Wu   // that deduction does not fail if not all template arguments are
102218c70b07SHaojian Wu   // deduced.
102318c70b07SHaojian Wu   //
102418c70b07SHaojian Wu   //
102518c70b07SHaojian Wu   //  template<typename X, typename Y>
102618c70b07SHaojian Wu   //  f(X, Y) -> f<Y, X>;
102718c70b07SHaojian Wu   //
102818c70b07SHaojian Wu   //  template<typename U>
102918c70b07SHaojian Wu   //  using alias = f<int, U>;
103018c70b07SHaojian Wu   //
103118c70b07SHaojian Wu   // The RHS of alias is f<int, U>, we deduced the template arguments of
103218c70b07SHaojian Wu   // the return type of the deduction guide from it: Y->int, X->U
103318c70b07SHaojian Wu   sema::TemplateDeductionInfo TDeduceInfo(Loc);
103418c70b07SHaojian Wu   // Must initialize n elements, this is required by DeduceTemplateArguments.
103518c70b07SHaojian Wu   SmallVector<DeducedTemplateArgument> DeduceResults(
103618c70b07SHaojian Wu       F->getTemplateParameters()->size());
103718c70b07SHaojian Wu 
103818c70b07SHaojian Wu   // FIXME: DeduceTemplateArguments stops immediately at the first
1039fd4f94ddSYounan Zhang   // non-deducible template argument. However, this doesn't seem to cause
104018c70b07SHaojian Wu   // issues for practice cases, we probably need to extend it to continue
104118c70b07SHaojian Wu   // performing deduction for rest of arguments to align with the C++
104218c70b07SHaojian Wu   // standard.
104318c70b07SHaojian Wu   SemaRef.DeduceTemplateArguments(
104418c70b07SHaojian Wu       F->getTemplateParameters(), FReturnType->template_arguments(),
104518c70b07SHaojian Wu       AliasRhsTemplateArgs, TDeduceInfo, DeduceResults,
104618c70b07SHaojian Wu       /*NumberOfArgumentsMustMatch=*/false);
104718c70b07SHaojian Wu 
104818c70b07SHaojian Wu   SmallVector<TemplateArgument> DeducedArgs;
104918c70b07SHaojian Wu   SmallVector<unsigned> NonDeducedTemplateParamsInFIndex;
105018c70b07SHaojian Wu   // !!NOTE: DeduceResults respects the sequence of template parameters of
105118c70b07SHaojian Wu   // the deduction guide f.
105218c70b07SHaojian Wu   for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
105318c70b07SHaojian Wu     if (const auto &D = DeduceResults[Index]; !D.isNull()) // Deduced
105418c70b07SHaojian Wu       DeducedArgs.push_back(D);
105518c70b07SHaojian Wu     else
105618c70b07SHaojian Wu       NonDeducedTemplateParamsInFIndex.push_back(Index);
105718c70b07SHaojian Wu   }
105818c70b07SHaojian Wu   auto DeducedAliasTemplateParams =
105918c70b07SHaojian Wu       TemplateParamsReferencedInTemplateArgumentList(
106018c70b07SHaojian Wu           AliasTemplate->getTemplateParameters(), DeducedArgs);
106118c70b07SHaojian Wu   // All template arguments null by default.
106218c70b07SHaojian Wu   SmallVector<TemplateArgument> TemplateArgsForBuildingFPrime(
106318c70b07SHaojian Wu       F->getTemplateParameters()->size());
106418c70b07SHaojian Wu 
106518c70b07SHaojian Wu   // Create a template parameter list for the synthesized deduction guide f'.
106618c70b07SHaojian Wu   //
106718c70b07SHaojian Wu   // C++ [over.match.class.deduct]p3.2:
106818c70b07SHaojian Wu   //   If f is a function template, f' is a function template whose template
106918c70b07SHaojian Wu   //   parameter list consists of all the template parameters of A
107018c70b07SHaojian Wu   //   (including their default template arguments) that appear in the above
107118c70b07SHaojian Wu   //   deductions or (recursively) in their default template arguments
107218c70b07SHaojian Wu   SmallVector<NamedDecl *> FPrimeTemplateParams;
107318c70b07SHaojian Wu   // Store template arguments that refer to the newly-created template
107418c70b07SHaojian Wu   // parameters, used for building `TemplateArgsForBuildingFPrime`.
107518c70b07SHaojian Wu   SmallVector<TemplateArgument, 16> TransformedDeducedAliasArgs(
107618c70b07SHaojian Wu       AliasTemplate->getTemplateParameters()->size());
107718c70b07SHaojian Wu 
107818c70b07SHaojian Wu   for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {
107918c70b07SHaojian Wu     auto *TP =
108018c70b07SHaojian Wu         AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx);
108118c70b07SHaojian Wu     // Rebuild any internal references to earlier parameters and reindex as
108218c70b07SHaojian Wu     // we go.
108318c70b07SHaojian Wu     MultiLevelTemplateArgumentList Args;
108418c70b07SHaojian Wu     Args.setKind(TemplateSubstitutionKind::Rewrite);
108518c70b07SHaojian Wu     Args.addOuterTemplateArguments(TransformedDeducedAliasArgs);
108618c70b07SHaojian Wu     NamedDecl *NewParam = transformTemplateParameter(
108718c70b07SHaojian Wu         SemaRef, AliasTemplate->getDeclContext(), TP, Args,
1088bb064535SYounan Zhang         /*NewIndex=*/FPrimeTemplateParams.size(), getDepthAndIndex(TP).first);
108918c70b07SHaojian Wu     FPrimeTemplateParams.push_back(NewParam);
109018c70b07SHaojian Wu 
1091c7bfc418SYounan Zhang     TemplateArgument NewTemplateArgument =
1092c7bfc418SYounan Zhang         Context.getInjectedTemplateArg(NewParam);
109318c70b07SHaojian Wu     TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument;
109418c70b07SHaojian Wu   }
109518c70b07SHaojian Wu   unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size();
1096fd4f94ddSYounan Zhang 
1097fd4f94ddSYounan Zhang   // To form a deduction guide f' from f, we leverage clang's instantiation
1098fd4f94ddSYounan Zhang   // mechanism, we construct a template argument list where the template
1099fd4f94ddSYounan Zhang   // arguments refer to the newly-created template parameters of f', and
1100fd4f94ddSYounan Zhang   // then apply instantiation on this template argument list to instantiate
1101fd4f94ddSYounan Zhang   // f, this ensures all template parameter occurrences are updated
1102fd4f94ddSYounan Zhang   // correctly.
1103fd4f94ddSYounan Zhang   //
1104fd4f94ddSYounan Zhang   // The template argument list is formed, in order, from
1105fd4f94ddSYounan Zhang   //   1) For the template parameters of the alias, the corresponding deduced
1106fd4f94ddSYounan Zhang   //      template arguments
1107fd4f94ddSYounan Zhang   //   2) For the non-deduced template parameters of f. the
1108fd4f94ddSYounan Zhang   //      (rebuilt) template arguments corresponding.
1109fd4f94ddSYounan Zhang   //
1110fd4f94ddSYounan Zhang   // Note: the non-deduced template arguments of `f` might refer to arguments
1111fd4f94ddSYounan Zhang   // deduced in 1), as in a type constraint.
1112fd4f94ddSYounan Zhang   MultiLevelTemplateArgumentList Args;
1113fd4f94ddSYounan Zhang   Args.setKind(TemplateSubstitutionKind::Rewrite);
1114fd4f94ddSYounan Zhang   Args.addOuterTemplateArguments(TransformedDeducedAliasArgs);
1115fd4f94ddSYounan Zhang   for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
1116fd4f94ddSYounan Zhang     const auto &D = DeduceResults[Index];
1117fd4f94ddSYounan Zhang     if (D.isNull()) {
1118fd4f94ddSYounan Zhang       // 2): Non-deduced template parameters would be substituted later.
1119fd4f94ddSYounan Zhang       continue;
1120fd4f94ddSYounan Zhang     }
1121fd4f94ddSYounan Zhang     TemplateArgumentLoc Input =
1122fd4f94ddSYounan Zhang         SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{});
1123fd4f94ddSYounan Zhang     TemplateArgumentLoc Output;
1124fd4f94ddSYounan Zhang     if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) {
1125fd4f94ddSYounan Zhang       assert(TemplateArgsForBuildingFPrime[Index].isNull() &&
1126fd4f94ddSYounan Zhang              "InstantiatedArgs must be null before setting");
1127fd4f94ddSYounan Zhang       TemplateArgsForBuildingFPrime[Index] = Output.getArgument();
1128fd4f94ddSYounan Zhang     }
1129fd4f94ddSYounan Zhang   }
1130fd4f94ddSYounan Zhang 
1131fd4f94ddSYounan Zhang   // Case 2)
113218c70b07SHaojian Wu   //   ...followed by the template parameters of f that were not deduced
113318c70b07SHaojian Wu   //   (including their default template arguments)
113418c70b07SHaojian Wu   for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) {
113518c70b07SHaojian Wu     auto *TP = F->getTemplateParameters()->getParam(FTemplateParamIdx);
113618c70b07SHaojian Wu     MultiLevelTemplateArgumentList Args;
113718c70b07SHaojian Wu     Args.setKind(TemplateSubstitutionKind::Rewrite);
113818c70b07SHaojian Wu     // We take a shortcut here, it is ok to reuse the
113918c70b07SHaojian Wu     // TemplateArgsForBuildingFPrime.
114018c70b07SHaojian Wu     Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime);
114118c70b07SHaojian Wu     NamedDecl *NewParam = transformTemplateParameter(
114218c70b07SHaojian Wu         SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(),
1143bb064535SYounan Zhang         getDepthAndIndex(TP).first);
114418c70b07SHaojian Wu     FPrimeTemplateParams.push_back(NewParam);
114518c70b07SHaojian Wu 
114618c70b07SHaojian Wu     assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&
114718c70b07SHaojian Wu            "The argument must be null before setting");
114818c70b07SHaojian Wu     TemplateArgsForBuildingFPrime[FTemplateParamIdx] =
1149c7bfc418SYounan Zhang         Context.getInjectedTemplateArg(NewParam);
115018c70b07SHaojian Wu   }
115118c70b07SHaojian Wu 
115218c70b07SHaojian Wu   auto *TemplateArgListForBuildingFPrime =
115318c70b07SHaojian Wu       TemplateArgumentList::CreateCopy(Context, TemplateArgsForBuildingFPrime);
115418c70b07SHaojian Wu   // Form the f' by substituting the template arguments into f.
115518c70b07SHaojian Wu   if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration(
115618c70b07SHaojian Wu           F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(),
115718c70b07SHaojian Wu           Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
115818c70b07SHaojian Wu     auto *GG = cast<CXXDeductionGuideDecl>(FPrime);
115918c70b07SHaojian Wu 
116018c70b07SHaojian Wu     Expr *IsDeducible = buildIsDeducibleConstraint(
116118c70b07SHaojian Wu         SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams);
116218c70b07SHaojian Wu     Expr *RequiresClause =
116318c70b07SHaojian Wu         buildAssociatedConstraints(SemaRef, F, AliasTemplate, DeduceResults,
116418c70b07SHaojian Wu                                    FirstUndeducedParamIdx, IsDeducible);
116518c70b07SHaojian Wu 
116618c70b07SHaojian Wu     auto *FPrimeTemplateParamList = TemplateParameterList::Create(
116718c70b07SHaojian Wu         Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
116818c70b07SHaojian Wu         AliasTemplate->getTemplateParameters()->getLAngleLoc(),
116918c70b07SHaojian Wu         FPrimeTemplateParams,
117018c70b07SHaojian Wu         AliasTemplate->getTemplateParameters()->getRAngleLoc(),
117118c70b07SHaojian Wu         /*RequiresClause=*/RequiresClause);
117218c70b07SHaojian Wu     auto *Result = cast<FunctionTemplateDecl>(buildDeductionGuide(
117318c70b07SHaojian Wu         SemaRef, AliasTemplate, FPrimeTemplateParamList,
117418c70b07SHaojian Wu         GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(),
117518c70b07SHaojian Wu         GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(),
117618c70b07SHaojian Wu         AliasTemplate->getLocation(), AliasTemplate->getEndLoc(),
117718c70b07SHaojian Wu         F->isImplicit()));
1178*f94c4815Santangelo     auto *DGuide = cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl());
1179*f94c4815Santangelo     DGuide->setDeductionCandidateKind(GG->getDeductionCandidateKind());
1180*f94c4815Santangelo     DGuide->setSourceDeductionGuide(
1181*f94c4815Santangelo         cast<CXXDeductionGuideDecl>(F->getTemplatedDecl()));
1182*f94c4815Santangelo     DGuide->setSourceDeductionGuideKind(
1183*f94c4815Santangelo         CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
118418c70b07SHaojian Wu     return Result;
118518c70b07SHaojian Wu   }
118618c70b07SHaojian Wu   return nullptr;
118718c70b07SHaojian Wu }
118818c70b07SHaojian Wu 
118918c70b07SHaojian Wu void DeclareImplicitDeductionGuidesForTypeAlias(
119018c70b07SHaojian Wu     Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
119118c70b07SHaojian Wu   if (AliasTemplate->isInvalidDecl())
119218c70b07SHaojian Wu     return;
119318c70b07SHaojian Wu   auto &Context = SemaRef.Context;
119418c70b07SHaojian Wu   // FIXME: if there is an explicit deduction guide after the first use of the
119518c70b07SHaojian Wu   // type alias usage, we will not cover this explicit deduction guide. fix this
119618c70b07SHaojian Wu   // case.
119718c70b07SHaojian Wu   if (hasDeclaredDeductionGuides(
119818c70b07SHaojian Wu           Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
119918c70b07SHaojian Wu           AliasTemplate->getDeclContext()))
120018c70b07SHaojian Wu     return;
120118c70b07SHaojian Wu   auto [Template, AliasRhsTemplateArgs] =
120218c70b07SHaojian Wu       getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate);
120318c70b07SHaojian Wu   if (!Template)
120418c70b07SHaojian Wu     return;
120518c70b07SHaojian Wu   DeclarationNameInfo NameInfo(
120618c70b07SHaojian Wu       Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
120718c70b07SHaojian Wu   LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
120818c70b07SHaojian Wu   SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
120918c70b07SHaojian Wu   Guides.suppressDiagnostics();
121018c70b07SHaojian Wu 
121118c70b07SHaojian Wu   for (auto *G : Guides) {
121218c70b07SHaojian Wu     if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(G)) {
121318c70b07SHaojian Wu       // The deduction guide is a non-template function decl, we just clone it.
121418c70b07SHaojian Wu       auto *FunctionType =
121518c70b07SHaojian Wu           SemaRef.Context.getTrivialTypeSourceInfo(DG->getType());
121618c70b07SHaojian Wu       FunctionProtoTypeLoc FPTL =
121718c70b07SHaojian Wu           FunctionType->getTypeLoc().castAs<FunctionProtoTypeLoc>();
121818c70b07SHaojian Wu 
121918c70b07SHaojian Wu       // Clone the parameters.
122018c70b07SHaojian Wu       for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) {
122118c70b07SHaojian Wu         const auto *P = DG->getParamDecl(I);
122218c70b07SHaojian Wu         auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(P->getType());
122318c70b07SHaojian Wu         ParmVarDecl *NewParam = ParmVarDecl::Create(
122418c70b07SHaojian Wu             SemaRef.Context, G->getDeclContext(),
122518c70b07SHaojian Wu             DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr,
122618c70b07SHaojian Wu             TSI->getType(), TSI, SC_None, nullptr);
122718c70b07SHaojian Wu         NewParam->setScopeInfo(0, I);
122818c70b07SHaojian Wu         FPTL.setParam(I, NewParam);
122918c70b07SHaojian Wu       }
123018c70b07SHaojian Wu       auto *Transformed = cast<FunctionDecl>(buildDeductionGuide(
123118c70b07SHaojian Wu           SemaRef, AliasTemplate, /*TemplateParams=*/nullptr,
123218c70b07SHaojian Wu           /*Constructor=*/nullptr, DG->getExplicitSpecifier(), FunctionType,
123318c70b07SHaojian Wu           AliasTemplate->getBeginLoc(), AliasTemplate->getLocation(),
123418c70b07SHaojian Wu           AliasTemplate->getEndLoc(), DG->isImplicit()));
123518c70b07SHaojian Wu 
123618c70b07SHaojian Wu       // FIXME: Here the synthesized deduction guide is not a templated
123718c70b07SHaojian Wu       // function. Per [dcl.decl]p4, the requires-clause shall be present only
123818c70b07SHaojian Wu       // if the declarator declares a templated function, a bug in standard?
123918c70b07SHaojian Wu       auto *Constraint = buildIsDeducibleConstraint(
124018c70b07SHaojian Wu           SemaRef, AliasTemplate, Transformed->getReturnType(), {});
124118c70b07SHaojian Wu       if (auto *RC = DG->getTrailingRequiresClause()) {
124218c70b07SHaojian Wu         auto Conjunction =
124318c70b07SHaojian Wu             SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{},
124418c70b07SHaojian Wu                                BinaryOperatorKind::BO_LAnd, RC, Constraint);
124518c70b07SHaojian Wu         if (!Conjunction.isInvalid())
124618c70b07SHaojian Wu           Constraint = Conjunction.getAs<Expr>();
124718c70b07SHaojian Wu       }
124818c70b07SHaojian Wu       Transformed->setTrailingRequiresClause(Constraint);
124918c70b07SHaojian Wu     }
125018c70b07SHaojian Wu     FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G);
125118c70b07SHaojian Wu     if (!F)
125218c70b07SHaojian Wu       continue;
125318c70b07SHaojian Wu     // The **aggregate** deduction guides are handled in a different code path
125418c70b07SHaojian Wu     // (DeclareAggregateDeductionGuideFromInitList), which involves the tricky
125518c70b07SHaojian Wu     // cache.
125618c70b07SHaojian Wu     if (cast<CXXDeductionGuideDecl>(F->getTemplatedDecl())
125718c70b07SHaojian Wu             ->getDeductionCandidateKind() == DeductionCandidate::Aggregate)
125818c70b07SHaojian Wu       continue;
125918c70b07SHaojian Wu 
126018c70b07SHaojian Wu     BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc);
126118c70b07SHaojian Wu   }
126218c70b07SHaojian Wu }
126318c70b07SHaojian Wu 
126418c70b07SHaojian Wu // Build an aggregate deduction guide for a type alias template.
126518c70b07SHaojian Wu FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias(
126618c70b07SHaojian Wu     Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
126718c70b07SHaojian Wu     MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
126818c70b07SHaojian Wu   TemplateDecl *RHSTemplate =
126918c70b07SHaojian Wu       getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;
127018c70b07SHaojian Wu   if (!RHSTemplate)
127118c70b07SHaojian Wu     return nullptr;
12720bc02b99SYounan Zhang 
12730bc02b99SYounan Zhang   llvm::SmallVector<TypedefNameDecl *> TypedefDecls;
12740bc02b99SYounan Zhang   llvm::SmallVector<QualType> NewParamTypes;
12750bc02b99SYounan Zhang   ExtractTypeForDeductionGuide TypeAliasTransformer(SemaRef, TypedefDecls);
12760bc02b99SYounan Zhang   for (QualType P : ParamTypes) {
12770bc02b99SYounan Zhang     QualType Type = TypeAliasTransformer.TransformType(P);
12780bc02b99SYounan Zhang     if (Type.isNull())
12790bc02b99SYounan Zhang       return nullptr;
12800bc02b99SYounan Zhang     NewParamTypes.push_back(Type);
12810bc02b99SYounan Zhang   }
12820bc02b99SYounan Zhang 
128318c70b07SHaojian Wu   auto *RHSDeductionGuide = SemaRef.DeclareAggregateDeductionGuideFromInitList(
12840bc02b99SYounan Zhang       RHSTemplate, NewParamTypes, Loc);
128518c70b07SHaojian Wu   if (!RHSDeductionGuide)
128618c70b07SHaojian Wu     return nullptr;
12870bc02b99SYounan Zhang 
12880bc02b99SYounan Zhang   for (TypedefNameDecl *TD : TypedefDecls)
12890bc02b99SYounan Zhang     TD->setDeclContext(RHSDeductionGuide->getTemplatedDecl());
12900bc02b99SYounan Zhang 
129118c70b07SHaojian Wu   return BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate,
129218c70b07SHaojian Wu                                          RHSDeductionGuide, Loc);
129318c70b07SHaojian Wu }
129418c70b07SHaojian Wu 
129518c70b07SHaojian Wu } // namespace
129618c70b07SHaojian Wu 
129718c70b07SHaojian Wu FunctionTemplateDecl *Sema::DeclareAggregateDeductionGuideFromInitList(
129818c70b07SHaojian Wu     TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
129918c70b07SHaojian Wu     SourceLocation Loc) {
130018c70b07SHaojian Wu   llvm::FoldingSetNodeID ID;
130118c70b07SHaojian Wu   ID.AddPointer(Template);
130218c70b07SHaojian Wu   for (auto &T : ParamTypes)
130318c70b07SHaojian Wu     T.getCanonicalType().Profile(ID);
130418c70b07SHaojian Wu   unsigned Hash = ID.ComputeHash();
130518c70b07SHaojian Wu 
130618c70b07SHaojian Wu   auto Found = AggregateDeductionCandidates.find(Hash);
130718c70b07SHaojian Wu   if (Found != AggregateDeductionCandidates.end()) {
130818c70b07SHaojian Wu     CXXDeductionGuideDecl *GD = Found->getSecond();
130918c70b07SHaojian Wu     return GD->getDescribedFunctionTemplate();
131018c70b07SHaojian Wu   }
131118c70b07SHaojian Wu 
131218c70b07SHaojian Wu   if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) {
131318c70b07SHaojian Wu     if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias(
131418c70b07SHaojian Wu             *this, AliasTemplate, ParamTypes, Loc)) {
131518c70b07SHaojian Wu       auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl());
131618c70b07SHaojian Wu       GD->setDeductionCandidateKind(DeductionCandidate::Aggregate);
131718c70b07SHaojian Wu       AggregateDeductionCandidates[Hash] = GD;
131818c70b07SHaojian Wu       return FTD;
131918c70b07SHaojian Wu     }
132018c70b07SHaojian Wu   }
132118c70b07SHaojian Wu 
132218c70b07SHaojian Wu   if (CXXRecordDecl *DefRecord =
132318c70b07SHaojian Wu           cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) {
132418c70b07SHaojian Wu     if (TemplateDecl *DescribedTemplate =
132518c70b07SHaojian Wu             DefRecord->getDescribedClassTemplate())
132618c70b07SHaojian Wu       Template = DescribedTemplate;
132718c70b07SHaojian Wu   }
132818c70b07SHaojian Wu 
132918c70b07SHaojian Wu   DeclContext *DC = Template->getDeclContext();
133018c70b07SHaojian Wu   if (DC->isDependentContext())
133118c70b07SHaojian Wu     return nullptr;
133218c70b07SHaojian Wu 
133318c70b07SHaojian Wu   ConvertConstructorToDeductionGuideTransform Transform(
133418c70b07SHaojian Wu       *this, cast<ClassTemplateDecl>(Template));
133518c70b07SHaojian Wu   if (!isCompleteType(Loc, Transform.DeducedType))
133618c70b07SHaojian Wu     return nullptr;
133718c70b07SHaojian Wu 
133818c70b07SHaojian Wu   // In case we were expanding a pack when we attempted to declare deduction
133918c70b07SHaojian Wu   // guides, turn off pack expansion for everything we're about to do.
134018c70b07SHaojian Wu   ArgumentPackSubstitutionIndexRAII SubstIndex(*this,
134118c70b07SHaojian Wu                                                /*NewSubstitutionIndex=*/-1);
134218c70b07SHaojian Wu   // Create a template instantiation record to track the "instantiation" of
134318c70b07SHaojian Wu   // constructors into deduction guides.
134418c70b07SHaojian Wu   InstantiatingTemplate BuildingDeductionGuides(
134518c70b07SHaojian Wu       *this, Loc, Template,
134618c70b07SHaojian Wu       Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
134718c70b07SHaojian Wu   if (BuildingDeductionGuides.isInvalid())
134818c70b07SHaojian Wu     return nullptr;
134918c70b07SHaojian Wu 
135018c70b07SHaojian Wu   ClassTemplateDecl *Pattern =
135118c70b07SHaojian Wu       Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
135218c70b07SHaojian Wu   ContextRAII SavedContext(*this, Pattern->getTemplatedDecl());
135318c70b07SHaojian Wu 
135418c70b07SHaojian Wu   auto *FTD = cast<FunctionTemplateDecl>(
135518c70b07SHaojian Wu       Transform.buildSimpleDeductionGuide(ParamTypes));
135618c70b07SHaojian Wu   SavedContext.pop();
135718c70b07SHaojian Wu   auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl());
135818c70b07SHaojian Wu   GD->setDeductionCandidateKind(DeductionCandidate::Aggregate);
135918c70b07SHaojian Wu   AggregateDeductionCandidates[Hash] = GD;
136018c70b07SHaojian Wu   return FTD;
136118c70b07SHaojian Wu }
136218c70b07SHaojian Wu 
136318c70b07SHaojian Wu void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
136418c70b07SHaojian Wu                                           SourceLocation Loc) {
136518c70b07SHaojian Wu   if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) {
136618c70b07SHaojian Wu     DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc);
136718c70b07SHaojian Wu     return;
136818c70b07SHaojian Wu   }
136918c70b07SHaojian Wu   if (CXXRecordDecl *DefRecord =
137018c70b07SHaojian Wu           cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) {
137118c70b07SHaojian Wu     if (TemplateDecl *DescribedTemplate =
137218c70b07SHaojian Wu             DefRecord->getDescribedClassTemplate())
137318c70b07SHaojian Wu       Template = DescribedTemplate;
137418c70b07SHaojian Wu   }
137518c70b07SHaojian Wu 
137618c70b07SHaojian Wu   DeclContext *DC = Template->getDeclContext();
137718c70b07SHaojian Wu   if (DC->isDependentContext())
137818c70b07SHaojian Wu     return;
137918c70b07SHaojian Wu 
138018c70b07SHaojian Wu   ConvertConstructorToDeductionGuideTransform Transform(
138118c70b07SHaojian Wu       *this, cast<ClassTemplateDecl>(Template));
138218c70b07SHaojian Wu   if (!isCompleteType(Loc, Transform.DeducedType))
138318c70b07SHaojian Wu     return;
138418c70b07SHaojian Wu 
138518c70b07SHaojian Wu   if (hasDeclaredDeductionGuides(Transform.DeductionGuideName, DC))
138618c70b07SHaojian Wu     return;
138718c70b07SHaojian Wu 
138818c70b07SHaojian Wu   // In case we were expanding a pack when we attempted to declare deduction
138918c70b07SHaojian Wu   // guides, turn off pack expansion for everything we're about to do.
139018c70b07SHaojian Wu   ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
139118c70b07SHaojian Wu   // Create a template instantiation record to track the "instantiation" of
139218c70b07SHaojian Wu   // constructors into deduction guides.
139318c70b07SHaojian Wu   InstantiatingTemplate BuildingDeductionGuides(
139418c70b07SHaojian Wu       *this, Loc, Template,
139518c70b07SHaojian Wu       Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
139618c70b07SHaojian Wu   if (BuildingDeductionGuides.isInvalid())
139718c70b07SHaojian Wu     return;
139818c70b07SHaojian Wu 
139918c70b07SHaojian Wu   // Convert declared constructors into deduction guide templates.
140018c70b07SHaojian Wu   // FIXME: Skip constructors for which deduction must necessarily fail (those
140118c70b07SHaojian Wu   // for which some class template parameter without a default argument never
140218c70b07SHaojian Wu   // appears in a deduced context).
140318c70b07SHaojian Wu   ClassTemplateDecl *Pattern =
140418c70b07SHaojian Wu       Transform.NestedPattern ? Transform.NestedPattern : Transform.Template;
140518c70b07SHaojian Wu   ContextRAII SavedContext(*this, Pattern->getTemplatedDecl());
140618c70b07SHaojian Wu   llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors;
140718c70b07SHaojian Wu   bool AddedAny = false;
140818c70b07SHaojian Wu   for (NamedDecl *D : LookupConstructors(Pattern->getTemplatedDecl())) {
140918c70b07SHaojian Wu     D = D->getUnderlyingDecl();
141018c70b07SHaojian Wu     if (D->isInvalidDecl() || D->isImplicit())
141118c70b07SHaojian Wu       continue;
141218c70b07SHaojian Wu 
141318c70b07SHaojian Wu     D = cast<NamedDecl>(D->getCanonicalDecl());
141418c70b07SHaojian Wu 
141518c70b07SHaojian Wu     // Within C++20 modules, we may have multiple same constructors in
141618c70b07SHaojian Wu     // multiple same RecordDecls. And it doesn't make sense to create
141718c70b07SHaojian Wu     // duplicated deduction guides for the duplicated constructors.
141818c70b07SHaojian Wu     if (ProcessedCtors.count(D))
141918c70b07SHaojian Wu       continue;
142018c70b07SHaojian Wu 
142118c70b07SHaojian Wu     auto *FTD = dyn_cast<FunctionTemplateDecl>(D);
142218c70b07SHaojian Wu     auto *CD =
142318c70b07SHaojian Wu         dyn_cast_or_null<CXXConstructorDecl>(FTD ? FTD->getTemplatedDecl() : D);
142418c70b07SHaojian Wu     // Class-scope explicit specializations (MS extension) do not result in
142518c70b07SHaojian Wu     // deduction guides.
142618c70b07SHaojian Wu     if (!CD || (!FTD && CD->isFunctionTemplateSpecialization()))
142718c70b07SHaojian Wu       continue;
142818c70b07SHaojian Wu 
142918c70b07SHaojian Wu     // Cannot make a deduction guide when unparsed arguments are present.
143018c70b07SHaojian Wu     if (llvm::any_of(CD->parameters(), [](ParmVarDecl *P) {
143118c70b07SHaojian Wu           return !P || P->hasUnparsedDefaultArg();
143218c70b07SHaojian Wu         }))
143318c70b07SHaojian Wu       continue;
143418c70b07SHaojian Wu 
143518c70b07SHaojian Wu     ProcessedCtors.insert(D);
143618c70b07SHaojian Wu     Transform.transformConstructor(FTD, CD);
143718c70b07SHaojian Wu     AddedAny = true;
143818c70b07SHaojian Wu   }
143918c70b07SHaojian Wu 
144018c70b07SHaojian Wu   // C++17 [over.match.class.deduct]
144118c70b07SHaojian Wu   //    --  If C is not defined or does not declare any constructors, an
144218c70b07SHaojian Wu   //    additional function template derived as above from a hypothetical
144318c70b07SHaojian Wu   //    constructor C().
144418c70b07SHaojian Wu   if (!AddedAny)
14454dd55c56SJay Foad     Transform.buildSimpleDeductionGuide({});
144618c70b07SHaojian Wu 
144718c70b07SHaojian Wu   //    -- An additional function template derived as above from a hypothetical
144818c70b07SHaojian Wu   //    constructor C(C), called the copy deduction candidate.
144918c70b07SHaojian Wu   cast<CXXDeductionGuideDecl>(
145018c70b07SHaojian Wu       cast<FunctionTemplateDecl>(
145118c70b07SHaojian Wu           Transform.buildSimpleDeductionGuide(Transform.DeducedType))
145218c70b07SHaojian Wu           ->getTemplatedDecl())
145318c70b07SHaojian Wu       ->setDeductionCandidateKind(DeductionCandidate::Copy);
145418c70b07SHaojian Wu 
145518c70b07SHaojian Wu   SavedContext.pop();
145618c70b07SHaojian Wu }
1457