10fca6ea1SDimitry Andric //===- SemaTemplateDeductionGude.cpp - Template Argument Deduction---------===// 20fca6ea1SDimitry Andric // 30fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60fca6ea1SDimitry Andric // 70fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 80fca6ea1SDimitry Andric // 90fca6ea1SDimitry Andric // This file implements deduction guides for C++ class template argument 100fca6ea1SDimitry Andric // deduction. 110fca6ea1SDimitry Andric // 120fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 130fca6ea1SDimitry Andric 140fca6ea1SDimitry Andric #include "TreeTransform.h" 150fca6ea1SDimitry Andric #include "TypeLocBuilder.h" 160fca6ea1SDimitry Andric #include "clang/AST/ASTConsumer.h" 170fca6ea1SDimitry Andric #include "clang/AST/ASTContext.h" 180fca6ea1SDimitry Andric #include "clang/AST/Decl.h" 190fca6ea1SDimitry Andric #include "clang/AST/DeclBase.h" 200fca6ea1SDimitry Andric #include "clang/AST/DeclCXX.h" 210fca6ea1SDimitry Andric #include "clang/AST/DeclFriend.h" 220fca6ea1SDimitry Andric #include "clang/AST/DeclTemplate.h" 230fca6ea1SDimitry Andric #include "clang/AST/DeclarationName.h" 240fca6ea1SDimitry Andric #include "clang/AST/Expr.h" 250fca6ea1SDimitry Andric #include "clang/AST/ExprCXX.h" 260fca6ea1SDimitry Andric #include "clang/AST/OperationKinds.h" 270fca6ea1SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 280fca6ea1SDimitry Andric #include "clang/AST/TemplateBase.h" 290fca6ea1SDimitry Andric #include "clang/AST/TemplateName.h" 300fca6ea1SDimitry Andric #include "clang/AST/Type.h" 310fca6ea1SDimitry Andric #include "clang/AST/TypeLoc.h" 320fca6ea1SDimitry Andric #include "clang/Basic/LLVM.h" 330fca6ea1SDimitry Andric #include "clang/Basic/SourceLocation.h" 340fca6ea1SDimitry Andric #include "clang/Basic/Specifiers.h" 350fca6ea1SDimitry Andric #include "clang/Basic/TypeTraits.h" 360fca6ea1SDimitry Andric #include "clang/Sema/DeclSpec.h" 370fca6ea1SDimitry Andric #include "clang/Sema/Initialization.h" 380fca6ea1SDimitry Andric #include "clang/Sema/Lookup.h" 390fca6ea1SDimitry Andric #include "clang/Sema/Overload.h" 400fca6ea1SDimitry Andric #include "clang/Sema/Ownership.h" 410fca6ea1SDimitry Andric #include "clang/Sema/Scope.h" 420fca6ea1SDimitry Andric #include "clang/Sema/Template.h" 430fca6ea1SDimitry Andric #include "clang/Sema/TemplateDeduction.h" 440fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h" 450fca6ea1SDimitry Andric #include "llvm/ADT/DenseSet.h" 460fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 470fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h" 480fca6ea1SDimitry Andric #include "llvm/Support/Casting.h" 490fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 500fca6ea1SDimitry Andric #include <cassert> 510fca6ea1SDimitry Andric #include <optional> 520fca6ea1SDimitry Andric #include <utility> 530fca6ea1SDimitry Andric 540fca6ea1SDimitry Andric using namespace clang; 550fca6ea1SDimitry Andric using namespace sema; 560fca6ea1SDimitry Andric 570fca6ea1SDimitry Andric namespace { 580fca6ea1SDimitry Andric /// Tree transform to "extract" a transformed type from a class template's 590fca6ea1SDimitry Andric /// constructor to a deduction guide. 600fca6ea1SDimitry Andric class ExtractTypeForDeductionGuide 610fca6ea1SDimitry Andric : public TreeTransform<ExtractTypeForDeductionGuide> { 620fca6ea1SDimitry Andric llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs; 630fca6ea1SDimitry Andric ClassTemplateDecl *NestedPattern; 640fca6ea1SDimitry Andric const MultiLevelTemplateArgumentList *OuterInstantiationArgs; 650fca6ea1SDimitry Andric std::optional<TemplateDeclInstantiator> TypedefNameInstantiator; 660fca6ea1SDimitry Andric 670fca6ea1SDimitry Andric public: 680fca6ea1SDimitry Andric typedef TreeTransform<ExtractTypeForDeductionGuide> Base; 690fca6ea1SDimitry Andric ExtractTypeForDeductionGuide( 700fca6ea1SDimitry Andric Sema &SemaRef, 710fca6ea1SDimitry Andric llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs, 72*d686ce93SDimitry Andric ClassTemplateDecl *NestedPattern = nullptr, 73*d686ce93SDimitry Andric const MultiLevelTemplateArgumentList *OuterInstantiationArgs = nullptr) 740fca6ea1SDimitry Andric : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs), 750fca6ea1SDimitry Andric NestedPattern(NestedPattern), 760fca6ea1SDimitry Andric OuterInstantiationArgs(OuterInstantiationArgs) { 770fca6ea1SDimitry Andric if (OuterInstantiationArgs) 780fca6ea1SDimitry Andric TypedefNameInstantiator.emplace( 790fca6ea1SDimitry Andric SemaRef, SemaRef.getASTContext().getTranslationUnitDecl(), 800fca6ea1SDimitry Andric *OuterInstantiationArgs); 810fca6ea1SDimitry Andric } 820fca6ea1SDimitry Andric 830fca6ea1SDimitry Andric TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } 840fca6ea1SDimitry Andric 850fca6ea1SDimitry Andric /// Returns true if it's safe to substitute \p Typedef with 860fca6ea1SDimitry Andric /// \p OuterInstantiationArgs. 870fca6ea1SDimitry Andric bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) { 880fca6ea1SDimitry Andric if (!NestedPattern) 890fca6ea1SDimitry Andric return false; 900fca6ea1SDimitry Andric 910fca6ea1SDimitry Andric static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) { 920fca6ea1SDimitry Andric if (DC->Equals(TargetDC)) 930fca6ea1SDimitry Andric return true; 940fca6ea1SDimitry Andric while (DC->isRecord()) { 950fca6ea1SDimitry Andric if (DC->Equals(TargetDC)) 960fca6ea1SDimitry Andric return true; 970fca6ea1SDimitry Andric DC = DC->getParent(); 980fca6ea1SDimitry Andric } 990fca6ea1SDimitry Andric return false; 1000fca6ea1SDimitry Andric }; 1010fca6ea1SDimitry Andric 1020fca6ea1SDimitry Andric if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl())) 1030fca6ea1SDimitry Andric return true; 1040fca6ea1SDimitry Andric if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext())) 1050fca6ea1SDimitry Andric return true; 1060fca6ea1SDimitry Andric return false; 1070fca6ea1SDimitry Andric } 1080fca6ea1SDimitry Andric 1090fca6ea1SDimitry Andric QualType 1100fca6ea1SDimitry Andric RebuildTemplateSpecializationType(TemplateName Template, 1110fca6ea1SDimitry Andric SourceLocation TemplateNameLoc, 1120fca6ea1SDimitry Andric TemplateArgumentListInfo &TemplateArgs) { 1130fca6ea1SDimitry Andric if (!OuterInstantiationArgs || 1140fca6ea1SDimitry Andric !isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) 1150fca6ea1SDimitry Andric return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, 1160fca6ea1SDimitry Andric TemplateArgs); 1170fca6ea1SDimitry Andric 1180fca6ea1SDimitry Andric auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); 1190fca6ea1SDimitry Andric auto *Pattern = TATD; 1200fca6ea1SDimitry Andric while (Pattern->getInstantiatedFromMemberTemplate()) 1210fca6ea1SDimitry Andric Pattern = Pattern->getInstantiatedFromMemberTemplate(); 1220fca6ea1SDimitry Andric if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl())) 1230fca6ea1SDimitry Andric return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, 1240fca6ea1SDimitry Andric TemplateArgs); 1250fca6ea1SDimitry Andric 1260fca6ea1SDimitry Andric Decl *NewD = 1270fca6ea1SDimitry Andric TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD); 1280fca6ea1SDimitry Andric if (!NewD) 1290fca6ea1SDimitry Andric return QualType(); 1300fca6ea1SDimitry Andric 1310fca6ea1SDimitry Andric auto *NewTATD = cast<TypeAliasTemplateDecl>(NewD); 1320fca6ea1SDimitry Andric MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl()); 1330fca6ea1SDimitry Andric 1340fca6ea1SDimitry Andric return Base::RebuildTemplateSpecializationType( 1350fca6ea1SDimitry Andric TemplateName(NewTATD), TemplateNameLoc, TemplateArgs); 1360fca6ea1SDimitry Andric } 1370fca6ea1SDimitry Andric 1380fca6ea1SDimitry Andric QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { 1390fca6ea1SDimitry Andric ASTContext &Context = SemaRef.getASTContext(); 1400fca6ea1SDimitry Andric TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); 1410fca6ea1SDimitry Andric TypedefNameDecl *Decl = OrigDecl; 1420fca6ea1SDimitry Andric // Transform the underlying type of the typedef and clone the Decl only if 1430fca6ea1SDimitry Andric // the typedef has a dependent context. 1440fca6ea1SDimitry Andric bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext(); 1450fca6ea1SDimitry Andric 1460fca6ea1SDimitry Andric // A typedef/alias Decl within the NestedPattern may reference the outer 1470fca6ea1SDimitry Andric // template parameters. They're substituted with corresponding instantiation 1480fca6ea1SDimitry Andric // arguments here and in RebuildTemplateSpecializationType() above. 1490fca6ea1SDimitry Andric // Otherwise, we would have a CTAD guide with "dangling" template 1500fca6ea1SDimitry Andric // parameters. 1510fca6ea1SDimitry Andric // For example, 1520fca6ea1SDimitry Andric // template <class T> struct Outer { 1530fca6ea1SDimitry Andric // using Alias = S<T>; 1540fca6ea1SDimitry Andric // template <class U> struct Inner { 1550fca6ea1SDimitry Andric // Inner(Alias); 1560fca6ea1SDimitry Andric // }; 1570fca6ea1SDimitry Andric // }; 1580fca6ea1SDimitry Andric if (OuterInstantiationArgs && InDependentContext && 1590fca6ea1SDimitry Andric TL.getTypePtr()->isInstantiationDependentType()) { 1600fca6ea1SDimitry Andric Decl = cast_if_present<TypedefNameDecl>( 1610fca6ea1SDimitry Andric TypedefNameInstantiator->InstantiateTypedefNameDecl( 1620fca6ea1SDimitry Andric OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl))); 1630fca6ea1SDimitry Andric if (!Decl) 1640fca6ea1SDimitry Andric return QualType(); 1650fca6ea1SDimitry Andric MaterializedTypedefs.push_back(Decl); 1660fca6ea1SDimitry Andric } else if (InDependentContext) { 1670fca6ea1SDimitry Andric TypeLocBuilder InnerTLB; 1680fca6ea1SDimitry Andric QualType Transformed = 1690fca6ea1SDimitry Andric TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); 1700fca6ea1SDimitry Andric TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, Transformed); 1710fca6ea1SDimitry Andric if (isa<TypeAliasDecl>(OrigDecl)) 1720fca6ea1SDimitry Andric Decl = TypeAliasDecl::Create( 1730fca6ea1SDimitry Andric Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), 1740fca6ea1SDimitry Andric OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); 1750fca6ea1SDimitry Andric else { 1760fca6ea1SDimitry Andric assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef"); 1770fca6ea1SDimitry Andric Decl = TypedefDecl::Create( 1780fca6ea1SDimitry Andric Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), 1790fca6ea1SDimitry Andric OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); 1800fca6ea1SDimitry Andric } 1810fca6ea1SDimitry Andric MaterializedTypedefs.push_back(Decl); 1820fca6ea1SDimitry Andric } 1830fca6ea1SDimitry Andric 1840fca6ea1SDimitry Andric QualType TDTy = Context.getTypedefType(Decl); 1850fca6ea1SDimitry Andric TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy); 1860fca6ea1SDimitry Andric TypedefTL.setNameLoc(TL.getNameLoc()); 1870fca6ea1SDimitry Andric 1880fca6ea1SDimitry Andric return TDTy; 1890fca6ea1SDimitry Andric } 1900fca6ea1SDimitry Andric }; 1910fca6ea1SDimitry Andric 1920fca6ea1SDimitry Andric // Build a deduction guide using the provided information. 1930fca6ea1SDimitry Andric // 1940fca6ea1SDimitry Andric // A deduction guide can be either a template or a non-template function 1950fca6ea1SDimitry Andric // declaration. If \p TemplateParams is null, a non-template function 1960fca6ea1SDimitry Andric // declaration will be created. 1970fca6ea1SDimitry Andric NamedDecl *buildDeductionGuide( 1980fca6ea1SDimitry Andric Sema &SemaRef, TemplateDecl *OriginalTemplate, 1990fca6ea1SDimitry Andric TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor, 2000fca6ea1SDimitry Andric ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart, 2010fca6ea1SDimitry Andric SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit, 2020fca6ea1SDimitry Andric llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}) { 2030fca6ea1SDimitry Andric DeclContext *DC = OriginalTemplate->getDeclContext(); 2040fca6ea1SDimitry Andric auto DeductionGuideName = 2050fca6ea1SDimitry Andric SemaRef.Context.DeclarationNames.getCXXDeductionGuideName( 2060fca6ea1SDimitry Andric OriginalTemplate); 2070fca6ea1SDimitry Andric 2080fca6ea1SDimitry Andric DeclarationNameInfo Name(DeductionGuideName, Loc); 2090fca6ea1SDimitry Andric ArrayRef<ParmVarDecl *> Params = 2100fca6ea1SDimitry Andric TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(); 2110fca6ea1SDimitry Andric 2120fca6ea1SDimitry Andric // Build the implicit deduction guide template. 2130fca6ea1SDimitry Andric auto *Guide = 2140fca6ea1SDimitry Andric CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name, 2150fca6ea1SDimitry Andric TInfo->getType(), TInfo, LocEnd, Ctor); 2160fca6ea1SDimitry Andric Guide->setImplicit(IsImplicit); 2170fca6ea1SDimitry Andric Guide->setParams(Params); 2180fca6ea1SDimitry Andric 2190fca6ea1SDimitry Andric for (auto *Param : Params) 2200fca6ea1SDimitry Andric Param->setDeclContext(Guide); 2210fca6ea1SDimitry Andric for (auto *TD : MaterializedTypedefs) 2220fca6ea1SDimitry Andric TD->setDeclContext(Guide); 2230fca6ea1SDimitry Andric if (isa<CXXRecordDecl>(DC)) 2240fca6ea1SDimitry Andric Guide->setAccess(AS_public); 2250fca6ea1SDimitry Andric 2260fca6ea1SDimitry Andric if (!TemplateParams) { 2270fca6ea1SDimitry Andric DC->addDecl(Guide); 2280fca6ea1SDimitry Andric return Guide; 2290fca6ea1SDimitry Andric } 2300fca6ea1SDimitry Andric 2310fca6ea1SDimitry Andric auto *GuideTemplate = FunctionTemplateDecl::Create( 2320fca6ea1SDimitry Andric SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide); 2330fca6ea1SDimitry Andric GuideTemplate->setImplicit(IsImplicit); 2340fca6ea1SDimitry Andric Guide->setDescribedFunctionTemplate(GuideTemplate); 2350fca6ea1SDimitry Andric 2360fca6ea1SDimitry Andric if (isa<CXXRecordDecl>(DC)) 2370fca6ea1SDimitry Andric GuideTemplate->setAccess(AS_public); 2380fca6ea1SDimitry Andric 2390fca6ea1SDimitry Andric DC->addDecl(GuideTemplate); 2400fca6ea1SDimitry Andric return GuideTemplate; 2410fca6ea1SDimitry Andric } 2420fca6ea1SDimitry Andric 2430fca6ea1SDimitry Andric // Transform a given template type parameter `TTP`. 2440fca6ea1SDimitry Andric TemplateTypeParmDecl * 2450fca6ea1SDimitry Andric transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC, 2460fca6ea1SDimitry Andric TemplateTypeParmDecl *TTP, 2470fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, 2480fca6ea1SDimitry Andric unsigned NewDepth, unsigned NewIndex) { 2490fca6ea1SDimitry Andric // TemplateTypeParmDecl's index cannot be changed after creation, so 2500fca6ea1SDimitry Andric // substitute it directly. 2510fca6ea1SDimitry Andric auto *NewTTP = TemplateTypeParmDecl::Create( 2520fca6ea1SDimitry Andric SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth, 2530fca6ea1SDimitry Andric NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(), 2540fca6ea1SDimitry Andric TTP->isParameterPack(), TTP->hasTypeConstraint(), 2550fca6ea1SDimitry Andric TTP->isExpandedParameterPack() 2560fca6ea1SDimitry Andric ? std::optional<unsigned>(TTP->getNumExpansionParameters()) 2570fca6ea1SDimitry Andric : std::nullopt); 2580fca6ea1SDimitry Andric if (const auto *TC = TTP->getTypeConstraint()) 2590fca6ea1SDimitry Andric SemaRef.SubstTypeConstraint(NewTTP, TC, Args, 2600fca6ea1SDimitry Andric /*EvaluateConstraint=*/true); 2610fca6ea1SDimitry Andric if (TTP->hasDefaultArgument()) { 2620fca6ea1SDimitry Andric TemplateArgumentLoc InstantiatedDefaultArg; 2630fca6ea1SDimitry Andric if (!SemaRef.SubstTemplateArgument( 2640fca6ea1SDimitry Andric TTP->getDefaultArgument(), Args, InstantiatedDefaultArg, 2650fca6ea1SDimitry Andric TTP->getDefaultArgumentLoc(), TTP->getDeclName())) 2660fca6ea1SDimitry Andric NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg); 2670fca6ea1SDimitry Andric } 2680fca6ea1SDimitry Andric SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP); 2690fca6ea1SDimitry Andric return NewTTP; 2700fca6ea1SDimitry Andric } 2710fca6ea1SDimitry Andric // Similar to above, but for non-type template or template template parameters. 2720fca6ea1SDimitry Andric template <typename NonTypeTemplateOrTemplateTemplateParmDecl> 2730fca6ea1SDimitry Andric NonTypeTemplateOrTemplateTemplateParmDecl * 2740fca6ea1SDimitry Andric transformTemplateParam(Sema &SemaRef, DeclContext *DC, 2750fca6ea1SDimitry Andric NonTypeTemplateOrTemplateTemplateParmDecl *OldParam, 2760fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, unsigned NewIndex, 2770fca6ea1SDimitry Andric unsigned NewDepth) { 2780fca6ea1SDimitry Andric // Ask the template instantiator to do the heavy lifting for us, then adjust 2790fca6ea1SDimitry Andric // the index of the parameter once it's done. 2800fca6ea1SDimitry Andric auto *NewParam = cast<NonTypeTemplateOrTemplateTemplateParmDecl>( 2810fca6ea1SDimitry Andric SemaRef.SubstDecl(OldParam, DC, Args)); 2820fca6ea1SDimitry Andric NewParam->setPosition(NewIndex); 2830fca6ea1SDimitry Andric NewParam->setDepth(NewDepth); 2840fca6ea1SDimitry Andric return NewParam; 2850fca6ea1SDimitry Andric } 2860fca6ea1SDimitry Andric 2870fca6ea1SDimitry Andric /// Transform to convert portions of a constructor declaration into the 2880fca6ea1SDimitry Andric /// corresponding deduction guide, per C++1z [over.match.class.deduct]p1. 2890fca6ea1SDimitry Andric struct ConvertConstructorToDeductionGuideTransform { 2900fca6ea1SDimitry Andric ConvertConstructorToDeductionGuideTransform(Sema &S, 2910fca6ea1SDimitry Andric ClassTemplateDecl *Template) 2920fca6ea1SDimitry Andric : SemaRef(S), Template(Template) { 2930fca6ea1SDimitry Andric // If the template is nested, then we need to use the original 2940fca6ea1SDimitry Andric // pattern to iterate over the constructors. 2950fca6ea1SDimitry Andric ClassTemplateDecl *Pattern = Template; 2960fca6ea1SDimitry Andric while (Pattern->getInstantiatedFromMemberTemplate()) { 2970fca6ea1SDimitry Andric if (Pattern->isMemberSpecialization()) 2980fca6ea1SDimitry Andric break; 2990fca6ea1SDimitry Andric Pattern = Pattern->getInstantiatedFromMemberTemplate(); 3000fca6ea1SDimitry Andric NestedPattern = Pattern; 3010fca6ea1SDimitry Andric } 3020fca6ea1SDimitry Andric 3030fca6ea1SDimitry Andric if (NestedPattern) 3040fca6ea1SDimitry Andric OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template); 3050fca6ea1SDimitry Andric } 3060fca6ea1SDimitry Andric 3070fca6ea1SDimitry Andric Sema &SemaRef; 3080fca6ea1SDimitry Andric ClassTemplateDecl *Template; 3090fca6ea1SDimitry Andric ClassTemplateDecl *NestedPattern = nullptr; 3100fca6ea1SDimitry Andric 3110fca6ea1SDimitry Andric DeclContext *DC = Template->getDeclContext(); 3120fca6ea1SDimitry Andric CXXRecordDecl *Primary = Template->getTemplatedDecl(); 3130fca6ea1SDimitry Andric DeclarationName DeductionGuideName = 3140fca6ea1SDimitry Andric SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template); 3150fca6ea1SDimitry Andric 3160fca6ea1SDimitry Andric QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary); 3170fca6ea1SDimitry Andric 3180fca6ea1SDimitry Andric // Index adjustment to apply to convert depth-1 template parameters into 3190fca6ea1SDimitry Andric // depth-0 template parameters. 3200fca6ea1SDimitry Andric unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size(); 3210fca6ea1SDimitry Andric 3220fca6ea1SDimitry Andric // Instantiation arguments for the outermost depth-1 templates 3230fca6ea1SDimitry Andric // when the template is nested 3240fca6ea1SDimitry Andric MultiLevelTemplateArgumentList OuterInstantiationArgs; 3250fca6ea1SDimitry Andric 3260fca6ea1SDimitry Andric /// Transform a constructor declaration into a deduction guide. 3270fca6ea1SDimitry Andric NamedDecl *transformConstructor(FunctionTemplateDecl *FTD, 3280fca6ea1SDimitry Andric CXXConstructorDecl *CD) { 3290fca6ea1SDimitry Andric SmallVector<TemplateArgument, 16> SubstArgs; 3300fca6ea1SDimitry Andric 3310fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 3320fca6ea1SDimitry Andric 3330fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p1: 3340fca6ea1SDimitry Andric // -- For each constructor of the class template designated by the 3350fca6ea1SDimitry Andric // template-name, a function template with the following properties: 3360fca6ea1SDimitry Andric 3370fca6ea1SDimitry Andric // -- The template parameters are the template parameters of the class 3380fca6ea1SDimitry Andric // template followed by the template parameters (including default 3390fca6ea1SDimitry Andric // template arguments) of the constructor, if any. 3400fca6ea1SDimitry Andric TemplateParameterList *TemplateParams = 3410fca6ea1SDimitry Andric SemaRef.GetTemplateParameterList(Template); 3420fca6ea1SDimitry Andric if (FTD) { 3430fca6ea1SDimitry Andric TemplateParameterList *InnerParams = FTD->getTemplateParameters(); 3440fca6ea1SDimitry Andric SmallVector<NamedDecl *, 16> AllParams; 3450fca6ea1SDimitry Andric SmallVector<TemplateArgument, 16> Depth1Args; 3460fca6ea1SDimitry Andric AllParams.reserve(TemplateParams->size() + InnerParams->size()); 3470fca6ea1SDimitry Andric AllParams.insert(AllParams.begin(), TemplateParams->begin(), 3480fca6ea1SDimitry Andric TemplateParams->end()); 3490fca6ea1SDimitry Andric SubstArgs.reserve(InnerParams->size()); 3500fca6ea1SDimitry Andric Depth1Args.reserve(InnerParams->size()); 3510fca6ea1SDimitry Andric 3520fca6ea1SDimitry Andric // Later template parameters could refer to earlier ones, so build up 3530fca6ea1SDimitry Andric // a list of substituted template arguments as we go. 3540fca6ea1SDimitry Andric for (NamedDecl *Param : *InnerParams) { 3550fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 3560fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 3570fca6ea1SDimitry Andric Args.addOuterTemplateArguments(Depth1Args); 3580fca6ea1SDimitry Andric Args.addOuterRetainedLevel(); 3590fca6ea1SDimitry Andric if (NestedPattern) 3600fca6ea1SDimitry Andric Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); 3610fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter(Param, Args); 3620fca6ea1SDimitry Andric if (!NewParam) 3630fca6ea1SDimitry Andric return nullptr; 3640fca6ea1SDimitry Andric // Constraints require that we substitute depth-1 arguments 3650fca6ea1SDimitry Andric // to match depths when substituted for evaluation later 3660fca6ea1SDimitry Andric Depth1Args.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); 3670fca6ea1SDimitry Andric 3680fca6ea1SDimitry Andric if (NestedPattern) { 3690fca6ea1SDimitry Andric TemplateDeclInstantiator Instantiator(SemaRef, DC, 3700fca6ea1SDimitry Andric OuterInstantiationArgs); 3710fca6ea1SDimitry Andric Instantiator.setEvaluateConstraints(false); 3720fca6ea1SDimitry Andric SemaRef.runWithSufficientStackSpace(NewParam->getLocation(), [&] { 3730fca6ea1SDimitry Andric NewParam = cast<NamedDecl>(Instantiator.Visit(NewParam)); 3740fca6ea1SDimitry Andric }); 3750fca6ea1SDimitry Andric } 3760fca6ea1SDimitry Andric 3770fca6ea1SDimitry Andric assert(NewParam->getTemplateDepth() == 0 && 3780fca6ea1SDimitry Andric "Unexpected template parameter depth"); 3790fca6ea1SDimitry Andric 3800fca6ea1SDimitry Andric AllParams.push_back(NewParam); 3810fca6ea1SDimitry Andric SubstArgs.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); 3820fca6ea1SDimitry Andric } 3830fca6ea1SDimitry Andric 3840fca6ea1SDimitry Andric // Substitute new template parameters into requires-clause if present. 3850fca6ea1SDimitry Andric Expr *RequiresClause = nullptr; 3860fca6ea1SDimitry Andric if (Expr *InnerRC = InnerParams->getRequiresClause()) { 3870fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 3880fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 3890fca6ea1SDimitry Andric Args.addOuterTemplateArguments(Depth1Args); 3900fca6ea1SDimitry Andric Args.addOuterRetainedLevel(); 3910fca6ea1SDimitry Andric if (NestedPattern) 3920fca6ea1SDimitry Andric Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); 3930fca6ea1SDimitry Andric ExprResult E = SemaRef.SubstExpr(InnerRC, Args); 3940fca6ea1SDimitry Andric if (E.isInvalid()) 3950fca6ea1SDimitry Andric return nullptr; 3960fca6ea1SDimitry Andric RequiresClause = E.getAs<Expr>(); 3970fca6ea1SDimitry Andric } 3980fca6ea1SDimitry Andric 3990fca6ea1SDimitry Andric TemplateParams = TemplateParameterList::Create( 4000fca6ea1SDimitry Andric SemaRef.Context, InnerParams->getTemplateLoc(), 4010fca6ea1SDimitry Andric InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(), 4020fca6ea1SDimitry Andric RequiresClause); 4030fca6ea1SDimitry Andric } 4040fca6ea1SDimitry Andric 4050fca6ea1SDimitry Andric // If we built a new template-parameter-list, track that we need to 4060fca6ea1SDimitry Andric // substitute references to the old parameters into references to the 4070fca6ea1SDimitry Andric // new ones. 4080fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 4090fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 4100fca6ea1SDimitry Andric if (FTD) { 4110fca6ea1SDimitry Andric Args.addOuterTemplateArguments(SubstArgs); 4120fca6ea1SDimitry Andric Args.addOuterRetainedLevel(); 4130fca6ea1SDimitry Andric } 4140fca6ea1SDimitry Andric 4150fca6ea1SDimitry Andric FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo() 4160fca6ea1SDimitry Andric ->getTypeLoc() 4170fca6ea1SDimitry Andric .getAsAdjusted<FunctionProtoTypeLoc>(); 4180fca6ea1SDimitry Andric assert(FPTL && "no prototype for constructor declaration"); 4190fca6ea1SDimitry Andric 4200fca6ea1SDimitry Andric // Transform the type of the function, adjusting the return type and 4210fca6ea1SDimitry Andric // replacing references to the old parameters with references to the 4220fca6ea1SDimitry Andric // new ones. 4230fca6ea1SDimitry Andric TypeLocBuilder TLB; 4240fca6ea1SDimitry Andric SmallVector<ParmVarDecl *, 8> Params; 4250fca6ea1SDimitry Andric SmallVector<TypedefNameDecl *, 4> MaterializedTypedefs; 4260fca6ea1SDimitry Andric QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args, 4270fca6ea1SDimitry Andric MaterializedTypedefs); 4280fca6ea1SDimitry Andric if (NewType.isNull()) 4290fca6ea1SDimitry Andric return nullptr; 4300fca6ea1SDimitry Andric TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); 4310fca6ea1SDimitry Andric 4320fca6ea1SDimitry Andric return buildDeductionGuide( 4330fca6ea1SDimitry Andric SemaRef, Template, TemplateParams, CD, CD->getExplicitSpecifier(), 4340fca6ea1SDimitry Andric NewTInfo, CD->getBeginLoc(), CD->getLocation(), CD->getEndLoc(), 4350fca6ea1SDimitry Andric /*IsImplicit=*/true, MaterializedTypedefs); 4360fca6ea1SDimitry Andric } 4370fca6ea1SDimitry Andric 4380fca6ea1SDimitry Andric /// Build a deduction guide with the specified parameter types. 4390fca6ea1SDimitry Andric NamedDecl *buildSimpleDeductionGuide(MutableArrayRef<QualType> ParamTypes) { 4400fca6ea1SDimitry Andric SourceLocation Loc = Template->getLocation(); 4410fca6ea1SDimitry Andric 4420fca6ea1SDimitry Andric // Build the requested type. 4430fca6ea1SDimitry Andric FunctionProtoType::ExtProtoInfo EPI; 4440fca6ea1SDimitry Andric EPI.HasTrailingReturn = true; 4450fca6ea1SDimitry Andric QualType Result = SemaRef.BuildFunctionType(DeducedType, ParamTypes, Loc, 4460fca6ea1SDimitry Andric DeductionGuideName, EPI); 4470fca6ea1SDimitry Andric TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(Result, Loc); 4480fca6ea1SDimitry Andric if (NestedPattern) 4490fca6ea1SDimitry Andric TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc, 4500fca6ea1SDimitry Andric DeductionGuideName); 4510fca6ea1SDimitry Andric 4520fca6ea1SDimitry Andric if (!TSI) 4530fca6ea1SDimitry Andric return nullptr; 4540fca6ea1SDimitry Andric 4550fca6ea1SDimitry Andric FunctionProtoTypeLoc FPTL = 4560fca6ea1SDimitry Andric TSI->getTypeLoc().castAs<FunctionProtoTypeLoc>(); 4570fca6ea1SDimitry Andric 4580fca6ea1SDimitry Andric // Build the parameters, needed during deduction / substitution. 4590fca6ea1SDimitry Andric SmallVector<ParmVarDecl *, 4> Params; 4600fca6ea1SDimitry Andric for (auto T : ParamTypes) { 4610fca6ea1SDimitry Andric auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T, Loc); 4620fca6ea1SDimitry Andric if (NestedPattern) 4630fca6ea1SDimitry Andric TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc, 4640fca6ea1SDimitry Andric DeclarationName()); 4650fca6ea1SDimitry Andric if (!TSI) 4660fca6ea1SDimitry Andric return nullptr; 4670fca6ea1SDimitry Andric 4680fca6ea1SDimitry Andric ParmVarDecl *NewParam = 4690fca6ea1SDimitry Andric ParmVarDecl::Create(SemaRef.Context, DC, Loc, Loc, nullptr, 4700fca6ea1SDimitry Andric TSI->getType(), TSI, SC_None, nullptr); 4710fca6ea1SDimitry Andric NewParam->setScopeInfo(0, Params.size()); 4720fca6ea1SDimitry Andric FPTL.setParam(Params.size(), NewParam); 4730fca6ea1SDimitry Andric Params.push_back(NewParam); 4740fca6ea1SDimitry Andric } 4750fca6ea1SDimitry Andric 4760fca6ea1SDimitry Andric return buildDeductionGuide( 4770fca6ea1SDimitry Andric SemaRef, Template, SemaRef.GetTemplateParameterList(Template), nullptr, 4780fca6ea1SDimitry Andric ExplicitSpecifier(), TSI, Loc, Loc, Loc, /*IsImplicit=*/true); 4790fca6ea1SDimitry Andric } 4800fca6ea1SDimitry Andric 4810fca6ea1SDimitry Andric private: 4820fca6ea1SDimitry Andric /// Transform a constructor template parameter into a deduction guide template 4830fca6ea1SDimitry Andric /// parameter, rebuilding any internal references to earlier parameters and 4840fca6ea1SDimitry Andric /// renumbering as we go. 4850fca6ea1SDimitry Andric NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam, 4860fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args) { 4870fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 4880fca6ea1SDimitry Andric return transformTemplateTypeParam( 4890fca6ea1SDimitry Andric SemaRef, DC, TTP, Args, TTP->getDepth() - 1, 4900fca6ea1SDimitry Andric Depth1IndexAdjustment + TTP->getIndex()); 4910fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 4920fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, TTP, Args, 4930fca6ea1SDimitry Andric Depth1IndexAdjustment + TTP->getIndex(), 4940fca6ea1SDimitry Andric TTP->getDepth() - 1); 4950fca6ea1SDimitry Andric auto *NTTP = cast<NonTypeTemplateParmDecl>(TemplateParam); 4960fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, NTTP, Args, 4970fca6ea1SDimitry Andric Depth1IndexAdjustment + NTTP->getIndex(), 4980fca6ea1SDimitry Andric NTTP->getDepth() - 1); 4990fca6ea1SDimitry Andric } 5000fca6ea1SDimitry Andric 5010fca6ea1SDimitry Andric QualType transformFunctionProtoType( 5020fca6ea1SDimitry Andric TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, 5030fca6ea1SDimitry Andric SmallVectorImpl<ParmVarDecl *> &Params, 5040fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, 5050fca6ea1SDimitry Andric SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) { 5060fca6ea1SDimitry Andric SmallVector<QualType, 4> ParamTypes; 5070fca6ea1SDimitry Andric const FunctionProtoType *T = TL.getTypePtr(); 5080fca6ea1SDimitry Andric 5090fca6ea1SDimitry Andric // -- The types of the function parameters are those of the constructor. 5100fca6ea1SDimitry Andric for (auto *OldParam : TL.getParams()) { 5110fca6ea1SDimitry Andric ParmVarDecl *NewParam = OldParam; 5120fca6ea1SDimitry Andric // Given 5130fca6ea1SDimitry Andric // template <class T> struct C { 5140fca6ea1SDimitry Andric // template <class U> struct D { 5150fca6ea1SDimitry Andric // template <class V> D(U, V); 5160fca6ea1SDimitry Andric // }; 5170fca6ea1SDimitry Andric // }; 5180fca6ea1SDimitry Andric // First, transform all the references to template parameters that are 5190fca6ea1SDimitry Andric // defined outside of the surrounding class template. That is T in the 5200fca6ea1SDimitry Andric // above example. 5210fca6ea1SDimitry Andric if (NestedPattern) { 5220fca6ea1SDimitry Andric NewParam = transformFunctionTypeParam( 5230fca6ea1SDimitry Andric NewParam, OuterInstantiationArgs, MaterializedTypedefs, 5240fca6ea1SDimitry Andric /*TransformingOuterPatterns=*/true); 5250fca6ea1SDimitry Andric if (!NewParam) 5260fca6ea1SDimitry Andric return QualType(); 5270fca6ea1SDimitry Andric } 5280fca6ea1SDimitry Andric // Then, transform all the references to template parameters that are 5290fca6ea1SDimitry Andric // defined at the class template and the constructor. In this example, 5300fca6ea1SDimitry Andric // they're U and V, respectively. 5310fca6ea1SDimitry Andric NewParam = 5320fca6ea1SDimitry Andric transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs, 5330fca6ea1SDimitry Andric /*TransformingOuterPatterns=*/false); 5340fca6ea1SDimitry Andric if (!NewParam) 5350fca6ea1SDimitry Andric return QualType(); 5360fca6ea1SDimitry Andric ParamTypes.push_back(NewParam->getType()); 5370fca6ea1SDimitry Andric Params.push_back(NewParam); 5380fca6ea1SDimitry Andric } 5390fca6ea1SDimitry Andric 5400fca6ea1SDimitry Andric // -- The return type is the class template specialization designated by 5410fca6ea1SDimitry Andric // the template-name and template arguments corresponding to the 5420fca6ea1SDimitry Andric // template parameters obtained from the class template. 5430fca6ea1SDimitry Andric // 5440fca6ea1SDimitry Andric // We use the injected-class-name type of the primary template instead. 5450fca6ea1SDimitry Andric // This has the convenient property that it is different from any type that 5460fca6ea1SDimitry Andric // the user can write in a deduction-guide (because they cannot enter the 5470fca6ea1SDimitry Andric // context of the template), so implicit deduction guides can never collide 5480fca6ea1SDimitry Andric // with explicit ones. 5490fca6ea1SDimitry Andric QualType ReturnType = DeducedType; 5500fca6ea1SDimitry Andric TLB.pushTypeSpec(ReturnType).setNameLoc(Primary->getLocation()); 5510fca6ea1SDimitry Andric 5520fca6ea1SDimitry Andric // Resolving a wording defect, we also inherit the variadicness of the 5530fca6ea1SDimitry Andric // constructor. 5540fca6ea1SDimitry Andric FunctionProtoType::ExtProtoInfo EPI; 5550fca6ea1SDimitry Andric EPI.Variadic = T->isVariadic(); 5560fca6ea1SDimitry Andric EPI.HasTrailingReturn = true; 5570fca6ea1SDimitry Andric 5580fca6ea1SDimitry Andric QualType Result = SemaRef.BuildFunctionType( 5590fca6ea1SDimitry Andric ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI); 5600fca6ea1SDimitry Andric if (Result.isNull()) 5610fca6ea1SDimitry Andric return QualType(); 5620fca6ea1SDimitry Andric 5630fca6ea1SDimitry Andric FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); 5640fca6ea1SDimitry Andric NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); 5650fca6ea1SDimitry Andric NewTL.setLParenLoc(TL.getLParenLoc()); 5660fca6ea1SDimitry Andric NewTL.setRParenLoc(TL.getRParenLoc()); 5670fca6ea1SDimitry Andric NewTL.setExceptionSpecRange(SourceRange()); 5680fca6ea1SDimitry Andric NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); 5690fca6ea1SDimitry Andric for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I) 5700fca6ea1SDimitry Andric NewTL.setParam(I, Params[I]); 5710fca6ea1SDimitry Andric 5720fca6ea1SDimitry Andric return Result; 5730fca6ea1SDimitry Andric } 5740fca6ea1SDimitry Andric 5750fca6ea1SDimitry Andric ParmVarDecl *transformFunctionTypeParam( 5760fca6ea1SDimitry Andric ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args, 5770fca6ea1SDimitry Andric llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs, 5780fca6ea1SDimitry Andric bool TransformingOuterPatterns) { 5790fca6ea1SDimitry Andric TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); 5800fca6ea1SDimitry Andric TypeSourceInfo *NewDI; 5810fca6ea1SDimitry Andric if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { 5820fca6ea1SDimitry Andric // Expand out the one and only element in each inner pack. 5830fca6ea1SDimitry Andric Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0); 5840fca6ea1SDimitry Andric NewDI = 5850fca6ea1SDimitry Andric SemaRef.SubstType(PackTL.getPatternLoc(), Args, 5860fca6ea1SDimitry Andric OldParam->getLocation(), OldParam->getDeclName()); 5870fca6ea1SDimitry Andric if (!NewDI) 5880fca6ea1SDimitry Andric return nullptr; 5890fca6ea1SDimitry Andric NewDI = 5900fca6ea1SDimitry Andric SemaRef.CheckPackExpansion(NewDI, PackTL.getEllipsisLoc(), 5910fca6ea1SDimitry Andric PackTL.getTypePtr()->getNumExpansions()); 5920fca6ea1SDimitry Andric } else 5930fca6ea1SDimitry Andric NewDI = SemaRef.SubstType(OldDI, Args, OldParam->getLocation(), 5940fca6ea1SDimitry Andric OldParam->getDeclName()); 5950fca6ea1SDimitry Andric if (!NewDI) 5960fca6ea1SDimitry Andric return nullptr; 5970fca6ea1SDimitry Andric 5980fca6ea1SDimitry Andric // Extract the type. This (for instance) replaces references to typedef 5990fca6ea1SDimitry Andric // members of the current instantiations with the definitions of those 6000fca6ea1SDimitry Andric // typedefs, avoiding triggering instantiation of the deduced type during 6010fca6ea1SDimitry Andric // deduction. 6020fca6ea1SDimitry Andric NewDI = ExtractTypeForDeductionGuide( 6030fca6ea1SDimitry Andric SemaRef, MaterializedTypedefs, NestedPattern, 6040fca6ea1SDimitry Andric TransformingOuterPatterns ? &Args : nullptr) 6050fca6ea1SDimitry Andric .transform(NewDI); 6060fca6ea1SDimitry Andric 6070fca6ea1SDimitry Andric // Resolving a wording defect, we also inherit default arguments from the 6080fca6ea1SDimitry Andric // constructor. 6090fca6ea1SDimitry Andric ExprResult NewDefArg; 6100fca6ea1SDimitry Andric if (OldParam->hasDefaultArg()) { 6110fca6ea1SDimitry Andric // We don't care what the value is (we won't use it); just create a 6120fca6ea1SDimitry Andric // placeholder to indicate there is a default argument. 6130fca6ea1SDimitry Andric QualType ParamTy = NewDI->getType(); 6140fca6ea1SDimitry Andric NewDefArg = new (SemaRef.Context) 6150fca6ea1SDimitry Andric OpaqueValueExpr(OldParam->getDefaultArgRange().getBegin(), 6160fca6ea1SDimitry Andric ParamTy.getNonLValueExprType(SemaRef.Context), 6170fca6ea1SDimitry Andric ParamTy->isLValueReferenceType() ? VK_LValue 6180fca6ea1SDimitry Andric : ParamTy->isRValueReferenceType() ? VK_XValue 6190fca6ea1SDimitry Andric : VK_PRValue); 6200fca6ea1SDimitry Andric } 6210fca6ea1SDimitry Andric // Handle arrays and functions decay. 6220fca6ea1SDimitry Andric auto NewType = NewDI->getType(); 6230fca6ea1SDimitry Andric if (NewType->isArrayType() || NewType->isFunctionType()) 6240fca6ea1SDimitry Andric NewType = SemaRef.Context.getDecayedType(NewType); 6250fca6ea1SDimitry Andric 6260fca6ea1SDimitry Andric ParmVarDecl *NewParam = ParmVarDecl::Create( 6270fca6ea1SDimitry Andric SemaRef.Context, DC, OldParam->getInnerLocStart(), 6280fca6ea1SDimitry Andric OldParam->getLocation(), OldParam->getIdentifier(), NewType, NewDI, 6290fca6ea1SDimitry Andric OldParam->getStorageClass(), NewDefArg.get()); 6300fca6ea1SDimitry Andric NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(), 6310fca6ea1SDimitry Andric OldParam->getFunctionScopeIndex()); 6320fca6ea1SDimitry Andric SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam); 6330fca6ea1SDimitry Andric return NewParam; 6340fca6ea1SDimitry Andric } 6350fca6ea1SDimitry Andric }; 6360fca6ea1SDimitry Andric 6370fca6ea1SDimitry Andric unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { 6380fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 6390fca6ea1SDimitry Andric return TTP->getDepth(); 6400fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 6410fca6ea1SDimitry Andric return TTP->getDepth(); 6420fca6ea1SDimitry Andric if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) 6430fca6ea1SDimitry Andric return NTTP->getDepth(); 6440fca6ea1SDimitry Andric llvm_unreachable("Unhandled template parameter types"); 6450fca6ea1SDimitry Andric } 6460fca6ea1SDimitry Andric 6470fca6ea1SDimitry Andric unsigned getTemplateParameterIndex(NamedDecl *TemplateParam) { 6480fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 6490fca6ea1SDimitry Andric return TTP->getIndex(); 6500fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 6510fca6ea1SDimitry Andric return TTP->getIndex(); 6520fca6ea1SDimitry Andric if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) 6530fca6ea1SDimitry Andric return NTTP->getIndex(); 6540fca6ea1SDimitry Andric llvm_unreachable("Unhandled template parameter types"); 6550fca6ea1SDimitry Andric } 6560fca6ea1SDimitry Andric 6570fca6ea1SDimitry Andric // Find all template parameters that appear in the given DeducedArgs. 6580fca6ea1SDimitry Andric // Return the indices of the template parameters in the TemplateParams. 6590fca6ea1SDimitry Andric SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( 6600fca6ea1SDimitry Andric const TemplateParameterList *TemplateParamsList, 6610fca6ea1SDimitry Andric ArrayRef<TemplateArgument> DeducedArgs) { 6620fca6ea1SDimitry Andric struct TemplateParamsReferencedFinder 6630fca6ea1SDimitry Andric : public RecursiveASTVisitor<TemplateParamsReferencedFinder> { 6640fca6ea1SDimitry Andric const TemplateParameterList *TemplateParamList; 6650fca6ea1SDimitry Andric llvm::BitVector ReferencedTemplateParams; 6660fca6ea1SDimitry Andric 6670fca6ea1SDimitry Andric TemplateParamsReferencedFinder( 6680fca6ea1SDimitry Andric const TemplateParameterList *TemplateParamList) 6690fca6ea1SDimitry Andric : TemplateParamList(TemplateParamList), 6700fca6ea1SDimitry Andric ReferencedTemplateParams(TemplateParamList->size()) {} 6710fca6ea1SDimitry Andric 6720fca6ea1SDimitry Andric bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { 6730fca6ea1SDimitry Andric // We use the index and depth to retrieve the corresponding template 6740fca6ea1SDimitry Andric // parameter from the parameter list, which is more robost. 6750fca6ea1SDimitry Andric Mark(TTP->getDepth(), TTP->getIndex()); 6760fca6ea1SDimitry Andric return true; 6770fca6ea1SDimitry Andric } 6780fca6ea1SDimitry Andric 6790fca6ea1SDimitry Andric bool VisitDeclRefExpr(DeclRefExpr *DRE) { 6800fca6ea1SDimitry Andric MarkAppeared(DRE->getFoundDecl()); 6810fca6ea1SDimitry Andric return true; 6820fca6ea1SDimitry Andric } 6830fca6ea1SDimitry Andric 6840fca6ea1SDimitry Andric bool TraverseTemplateName(TemplateName Template) { 6850fca6ea1SDimitry Andric if (auto *TD = Template.getAsTemplateDecl()) 6860fca6ea1SDimitry Andric MarkAppeared(TD); 6870fca6ea1SDimitry Andric return RecursiveASTVisitor::TraverseTemplateName(Template); 6880fca6ea1SDimitry Andric } 6890fca6ea1SDimitry Andric 6900fca6ea1SDimitry Andric void MarkAppeared(NamedDecl *ND) { 6910fca6ea1SDimitry Andric if (llvm::isa<NonTypeTemplateParmDecl, TemplateTypeParmDecl, 6920fca6ea1SDimitry Andric TemplateTemplateParmDecl>(ND)) 6930fca6ea1SDimitry Andric Mark(getTemplateParameterDepth(ND), getTemplateParameterIndex(ND)); 6940fca6ea1SDimitry Andric } 6950fca6ea1SDimitry Andric void Mark(unsigned Depth, unsigned Index) { 6960fca6ea1SDimitry Andric if (Index < TemplateParamList->size() && 6970fca6ea1SDimitry Andric TemplateParamList->getParam(Index)->getTemplateDepth() == Depth) 6980fca6ea1SDimitry Andric ReferencedTemplateParams.set(Index); 6990fca6ea1SDimitry Andric } 7000fca6ea1SDimitry Andric }; 7010fca6ea1SDimitry Andric TemplateParamsReferencedFinder Finder(TemplateParamsList); 7020fca6ea1SDimitry Andric Finder.TraverseTemplateArguments(DeducedArgs); 7030fca6ea1SDimitry Andric 7040fca6ea1SDimitry Andric SmallVector<unsigned> Results; 7050fca6ea1SDimitry Andric for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) { 7060fca6ea1SDimitry Andric if (Finder.ReferencedTemplateParams[Index]) 7070fca6ea1SDimitry Andric Results.push_back(Index); 7080fca6ea1SDimitry Andric } 7090fca6ea1SDimitry Andric return Results; 7100fca6ea1SDimitry Andric } 7110fca6ea1SDimitry Andric 7120fca6ea1SDimitry Andric bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { 7130fca6ea1SDimitry Andric // Check whether we've already declared deduction guides for this template. 7140fca6ea1SDimitry Andric // FIXME: Consider storing a flag on the template to indicate this. 7150fca6ea1SDimitry Andric assert(Name.getNameKind() == 7160fca6ea1SDimitry Andric DeclarationName::NameKind::CXXDeductionGuideName && 7170fca6ea1SDimitry Andric "name must be a deduction guide name"); 7180fca6ea1SDimitry Andric auto Existing = DC->lookup(Name); 7190fca6ea1SDimitry Andric for (auto *D : Existing) 7200fca6ea1SDimitry Andric if (D->isImplicit()) 7210fca6ea1SDimitry Andric return true; 7220fca6ea1SDimitry Andric return false; 7230fca6ea1SDimitry Andric } 7240fca6ea1SDimitry Andric 7250fca6ea1SDimitry Andric NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, 7260fca6ea1SDimitry Andric NamedDecl *TemplateParam, 7270fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, 7280fca6ea1SDimitry Andric unsigned NewIndex, unsigned NewDepth) { 7290fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 7300fca6ea1SDimitry Andric return transformTemplateTypeParam(SemaRef, DC, TTP, Args, NewDepth, 7310fca6ea1SDimitry Andric NewIndex); 7320fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 7330fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth); 7340fca6ea1SDimitry Andric if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) 7350fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth); 7360fca6ea1SDimitry Andric llvm_unreachable("Unhandled template parameter types"); 7370fca6ea1SDimitry Andric } 7380fca6ea1SDimitry Andric 7390fca6ea1SDimitry Andric // Build the associated constraints for the alias deduction guides. 7400fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p3.3: 7410fca6ea1SDimitry Andric // The associated constraints ([temp.constr.decl]) are the conjunction of the 7420fca6ea1SDimitry Andric // associated constraints of g and a constraint that is satisfied if and only 7430fca6ea1SDimitry Andric // if the arguments of A are deducible (see below) from the return type. 7440fca6ea1SDimitry Andric // 7450fca6ea1SDimitry Andric // The return result is expected to be the require-clause for the synthesized 7460fca6ea1SDimitry Andric // alias deduction guide. 7470fca6ea1SDimitry Andric Expr * 7480fca6ea1SDimitry Andric buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, 7490fca6ea1SDimitry Andric TypeAliasTemplateDecl *AliasTemplate, 7500fca6ea1SDimitry Andric ArrayRef<DeducedTemplateArgument> DeduceResults, 7510fca6ea1SDimitry Andric unsigned FirstUndeducedParamIdx, Expr *IsDeducible) { 7520fca6ea1SDimitry Andric Expr *RC = F->getTemplateParameters()->getRequiresClause(); 7530fca6ea1SDimitry Andric if (!RC) 7540fca6ea1SDimitry Andric return IsDeducible; 7550fca6ea1SDimitry Andric 7560fca6ea1SDimitry Andric ASTContext &Context = SemaRef.Context; 7570fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 7580fca6ea1SDimitry Andric 7590fca6ea1SDimitry Andric // In the clang AST, constraint nodes are deliberately not instantiated unless 7600fca6ea1SDimitry Andric // they are actively being evaluated. Consequently, occurrences of template 7610fca6ea1SDimitry Andric // parameters in the require-clause expression have a subtle "depth" 7620fca6ea1SDimitry Andric // difference compared to normal occurrences in places, such as function 7630fca6ea1SDimitry Andric // parameters. When transforming the require-clause, we must take this 7640fca6ea1SDimitry Andric // distinction into account: 7650fca6ea1SDimitry Andric // 7660fca6ea1SDimitry Andric // 1) In the transformed require-clause, occurrences of template parameters 7670fca6ea1SDimitry Andric // must use the "uninstantiated" depth; 7680fca6ea1SDimitry Andric // 2) When substituting on the require-clause expr of the underlying 7690fca6ea1SDimitry Andric // deduction guide, we must use the entire set of template argument lists; 7700fca6ea1SDimitry Andric // 7710fca6ea1SDimitry Andric // It's important to note that we're performing this transformation on an 7720fca6ea1SDimitry Andric // *instantiated* AliasTemplate. 7730fca6ea1SDimitry Andric 7740fca6ea1SDimitry Andric // For 1), if the alias template is nested within a class template, we 7750fca6ea1SDimitry Andric // calcualte the 'uninstantiated' depth by adding the substitution level back. 7760fca6ea1SDimitry Andric unsigned AdjustDepth = 0; 7770fca6ea1SDimitry Andric if (auto *PrimaryTemplate = 7780fca6ea1SDimitry Andric AliasTemplate->getInstantiatedFromMemberTemplate()) 7790fca6ea1SDimitry Andric AdjustDepth = PrimaryTemplate->getTemplateDepth(); 7800fca6ea1SDimitry Andric 7810fca6ea1SDimitry Andric // We rebuild all template parameters with the uninstantiated depth, and 7820fca6ea1SDimitry Andric // build template arguments refer to them. 7830fca6ea1SDimitry Andric SmallVector<TemplateArgument> AdjustedAliasTemplateArgs; 7840fca6ea1SDimitry Andric 7850fca6ea1SDimitry Andric for (auto *TP : *AliasTemplate->getTemplateParameters()) { 7860fca6ea1SDimitry Andric // Rebuild any internal references to earlier parameters and reindex 7870fca6ea1SDimitry Andric // as we go. 7880fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 7890fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 7900fca6ea1SDimitry Andric Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs); 7910fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 7920fca6ea1SDimitry Andric SemaRef, AliasTemplate->getDeclContext(), TP, Args, 7930fca6ea1SDimitry Andric /*NewIndex=*/AdjustedAliasTemplateArgs.size(), 7940fca6ea1SDimitry Andric getTemplateParameterDepth(TP) + AdjustDepth); 7950fca6ea1SDimitry Andric 7960fca6ea1SDimitry Andric TemplateArgument NewTemplateArgument = 7970fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 7980fca6ea1SDimitry Andric AdjustedAliasTemplateArgs.push_back(NewTemplateArgument); 7990fca6ea1SDimitry Andric } 8000fca6ea1SDimitry Andric // Template arguments used to transform the template arguments in 8010fca6ea1SDimitry Andric // DeducedResults. 8020fca6ea1SDimitry Andric SmallVector<TemplateArgument> TemplateArgsForBuildingRC( 8030fca6ea1SDimitry Andric F->getTemplateParameters()->size()); 8040fca6ea1SDimitry Andric // Transform the transformed template args 8050fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 8060fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 8070fca6ea1SDimitry Andric Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs); 8080fca6ea1SDimitry Andric 8090fca6ea1SDimitry Andric for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { 8100fca6ea1SDimitry Andric const auto &D = DeduceResults[Index]; 8110fca6ea1SDimitry Andric if (D.isNull()) { // non-deduced template parameters of f 8120fca6ea1SDimitry Andric NamedDecl *TP = F->getTemplateParameters()->getParam(Index); 8130fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 8140fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 8150fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TemplateArgsForBuildingRC); 8160fca6ea1SDimitry Andric // Rebuild the template parameter with updated depth and index. 8170fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 8180fca6ea1SDimitry Andric SemaRef, F->getDeclContext(), TP, Args, 8190fca6ea1SDimitry Andric /*NewIndex=*/FirstUndeducedParamIdx, 8200fca6ea1SDimitry Andric getTemplateParameterDepth(TP) + AdjustDepth); 8210fca6ea1SDimitry Andric FirstUndeducedParamIdx += 1; 8220fca6ea1SDimitry Andric assert(TemplateArgsForBuildingRC[Index].isNull()); 8230fca6ea1SDimitry Andric TemplateArgsForBuildingRC[Index] = 8240fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 8250fca6ea1SDimitry Andric continue; 8260fca6ea1SDimitry Andric } 8270fca6ea1SDimitry Andric TemplateArgumentLoc Input = 8280fca6ea1SDimitry Andric SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); 8290fca6ea1SDimitry Andric TemplateArgumentLoc Output; 8300fca6ea1SDimitry Andric if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) { 8310fca6ea1SDimitry Andric assert(TemplateArgsForBuildingRC[Index].isNull() && 8320fca6ea1SDimitry Andric "InstantiatedArgs must be null before setting"); 8330fca6ea1SDimitry Andric TemplateArgsForBuildingRC[Index] = Output.getArgument(); 8340fca6ea1SDimitry Andric } 8350fca6ea1SDimitry Andric } 8360fca6ea1SDimitry Andric 8370fca6ea1SDimitry Andric // A list of template arguments for transforming the require-clause of F. 8380fca6ea1SDimitry Andric // It must contain the entire set of template argument lists. 8390fca6ea1SDimitry Andric MultiLevelTemplateArgumentList ArgsForBuildingRC; 8400fca6ea1SDimitry Andric ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); 8410fca6ea1SDimitry Andric ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC); 8420fca6ea1SDimitry Andric // For 2), if the underlying deduction guide F is nested in a class template, 8430fca6ea1SDimitry Andric // we need the entire template argument list, as the constraint AST in the 8440fca6ea1SDimitry Andric // require-clause of F remains completely uninstantiated. 8450fca6ea1SDimitry Andric // 8460fca6ea1SDimitry Andric // For example: 8470fca6ea1SDimitry Andric // template <typename T> // depth 0 8480fca6ea1SDimitry Andric // struct Outer { 8490fca6ea1SDimitry Andric // template <typename U> 8500fca6ea1SDimitry Andric // struct Foo { Foo(U); }; 8510fca6ea1SDimitry Andric // 8520fca6ea1SDimitry Andric // template <typename U> // depth 1 8530fca6ea1SDimitry Andric // requires C<U> 8540fca6ea1SDimitry Andric // Foo(U) -> Foo<int>; 8550fca6ea1SDimitry Andric // }; 8560fca6ea1SDimitry Andric // template <typename U> 8570fca6ea1SDimitry Andric // using AFoo = Outer<int>::Foo<U>; 8580fca6ea1SDimitry Andric // 8590fca6ea1SDimitry Andric // In this scenario, the deduction guide for `Foo` inside `Outer<int>`: 8600fca6ea1SDimitry Andric // - The occurrence of U in the require-expression is [depth:1, index:0] 8610fca6ea1SDimitry Andric // - The occurrence of U in the function parameter is [depth:0, index:0] 8620fca6ea1SDimitry Andric // - The template parameter of U is [depth:0, index:0] 8630fca6ea1SDimitry Andric // 8640fca6ea1SDimitry Andric // We add the outer template arguments which is [int] to the multi-level arg 8650fca6ea1SDimitry Andric // list to ensure that the occurrence U in `C<U>` will be replaced with int 8660fca6ea1SDimitry Andric // during the substitution. 8670fca6ea1SDimitry Andric // 8680fca6ea1SDimitry Andric // NOTE: The underlying deduction guide F is instantiated -- either from an 8690fca6ea1SDimitry Andric // explicitly-written deduction guide member, or from a constructor. 8700fca6ea1SDimitry Andric // getInstantiatedFromMemberTemplate() can only handle the former case, so we 8710fca6ea1SDimitry Andric // check the DeclContext kind. 8720fca6ea1SDimitry Andric if (F->getLexicalDeclContext()->getDeclKind() == 8730fca6ea1SDimitry Andric clang::Decl::ClassTemplateSpecialization) { 8740fca6ea1SDimitry Andric auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs( 8750fca6ea1SDimitry Andric F, F->getLexicalDeclContext(), 8760fca6ea1SDimitry Andric /*Final=*/false, /*Innermost=*/std::nullopt, 8770fca6ea1SDimitry Andric /*RelativeToPrimary=*/true, 8780fca6ea1SDimitry Andric /*Pattern=*/nullptr, 8790fca6ea1SDimitry Andric /*ForConstraintInstantiation=*/true); 8800fca6ea1SDimitry Andric for (auto It : OuterLevelArgs) 8810fca6ea1SDimitry Andric ArgsForBuildingRC.addOuterTemplateArguments(It.Args); 8820fca6ea1SDimitry Andric } 8830fca6ea1SDimitry Andric 8840fca6ea1SDimitry Andric ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); 8850fca6ea1SDimitry Andric if (E.isInvalid()) 8860fca6ea1SDimitry Andric return nullptr; 8870fca6ea1SDimitry Andric 8880fca6ea1SDimitry Andric auto Conjunction = 8890fca6ea1SDimitry Andric SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, 8900fca6ea1SDimitry Andric BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible); 8910fca6ea1SDimitry Andric if (Conjunction.isInvalid()) 8920fca6ea1SDimitry Andric return nullptr; 8930fca6ea1SDimitry Andric return Conjunction.getAs<Expr>(); 8940fca6ea1SDimitry Andric } 8950fca6ea1SDimitry Andric // Build the is_deducible constraint for the alias deduction guides. 8960fca6ea1SDimitry Andric // [over.match.class.deduct]p3.3: 8970fca6ea1SDimitry Andric // ... and a constraint that is satisfied if and only if the arguments 8980fca6ea1SDimitry Andric // of A are deducible (see below) from the return type. 8990fca6ea1SDimitry Andric Expr *buildIsDeducibleConstraint(Sema &SemaRef, 9000fca6ea1SDimitry Andric TypeAliasTemplateDecl *AliasTemplate, 9010fca6ea1SDimitry Andric QualType ReturnType, 9020fca6ea1SDimitry Andric SmallVector<NamedDecl *> TemplateParams) { 9030fca6ea1SDimitry Andric ASTContext &Context = SemaRef.Context; 9040fca6ea1SDimitry Andric // Constraint AST nodes must use uninstantiated depth. 9050fca6ea1SDimitry Andric if (auto *PrimaryTemplate = 9060fca6ea1SDimitry Andric AliasTemplate->getInstantiatedFromMemberTemplate(); 9070fca6ea1SDimitry Andric PrimaryTemplate && TemplateParams.size() > 0) { 9080fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 9090fca6ea1SDimitry Andric 9100fca6ea1SDimitry Andric // Adjust the depth for TemplateParams. 9110fca6ea1SDimitry Andric unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth(); 9120fca6ea1SDimitry Andric SmallVector<TemplateArgument> TransformedTemplateArgs; 9130fca6ea1SDimitry Andric for (auto *TP : TemplateParams) { 9140fca6ea1SDimitry Andric // Rebuild any internal references to earlier parameters and reindex 9150fca6ea1SDimitry Andric // as we go. 9160fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 9170fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 9180fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedTemplateArgs); 9190fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 9200fca6ea1SDimitry Andric SemaRef, AliasTemplate->getDeclContext(), TP, Args, 9210fca6ea1SDimitry Andric /*NewIndex=*/TransformedTemplateArgs.size(), 9220fca6ea1SDimitry Andric getTemplateParameterDepth(TP) + AdjustDepth); 9230fca6ea1SDimitry Andric 9240fca6ea1SDimitry Andric TemplateArgument NewTemplateArgument = 9250fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 9260fca6ea1SDimitry Andric TransformedTemplateArgs.push_back(NewTemplateArgument); 9270fca6ea1SDimitry Andric } 9280fca6ea1SDimitry Andric // Transformed the ReturnType to restore the uninstantiated depth. 9290fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 9300fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 9310fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedTemplateArgs); 9320fca6ea1SDimitry Andric ReturnType = SemaRef.SubstType( 9330fca6ea1SDimitry Andric ReturnType, Args, AliasTemplate->getLocation(), 9340fca6ea1SDimitry Andric Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate)); 9350fca6ea1SDimitry Andric }; 9360fca6ea1SDimitry Andric 9370fca6ea1SDimitry Andric SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = { 9380fca6ea1SDimitry Andric Context.getTrivialTypeSourceInfo( 9390fca6ea1SDimitry Andric Context.getDeducedTemplateSpecializationType( 9400fca6ea1SDimitry Andric TemplateName(AliasTemplate), /*DeducedType=*/QualType(), 9410fca6ea1SDimitry Andric /*IsDependent=*/true)), // template specialization type whose 9420fca6ea1SDimitry Andric // arguments will be deduced. 9430fca6ea1SDimitry Andric Context.getTrivialTypeSourceInfo( 9440fca6ea1SDimitry Andric ReturnType), // type from which template arguments are deduced. 9450fca6ea1SDimitry Andric }; 9460fca6ea1SDimitry Andric return TypeTraitExpr::Create( 9470fca6ea1SDimitry Andric Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(), 9480fca6ea1SDimitry Andric TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs, 9490fca6ea1SDimitry Andric AliasTemplate->getLocation(), /*Value*/ false); 9500fca6ea1SDimitry Andric } 9510fca6ea1SDimitry Andric 9520fca6ea1SDimitry Andric std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>> 9530fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { 9540fca6ea1SDimitry Andric // Unwrap the sugared ElaboratedType. 9550fca6ea1SDimitry Andric auto RhsType = AliasTemplate->getTemplatedDecl() 9560fca6ea1SDimitry Andric ->getUnderlyingType() 9570fca6ea1SDimitry Andric .getSingleStepDesugaredType(SemaRef.Context); 9580fca6ea1SDimitry Andric TemplateDecl *Template = nullptr; 9590fca6ea1SDimitry Andric llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs; 9600fca6ea1SDimitry Andric if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) { 9610fca6ea1SDimitry Andric // Cases where the RHS of the alias is dependent. e.g. 9620fca6ea1SDimitry Andric // template<typename T> 9630fca6ea1SDimitry Andric // using AliasFoo1 = Foo<T>; // a class/type alias template specialization 9640fca6ea1SDimitry Andric Template = TST->getTemplateName().getAsTemplateDecl(); 9650fca6ea1SDimitry Andric AliasRhsTemplateArgs = TST->template_arguments(); 9660fca6ea1SDimitry Andric } else if (const auto *RT = RhsType->getAs<RecordType>()) { 9670fca6ea1SDimitry Andric // Cases where template arguments in the RHS of the alias are not 9680fca6ea1SDimitry Andric // dependent. e.g. 9690fca6ea1SDimitry Andric // using AliasFoo = Foo<bool>; 9700fca6ea1SDimitry Andric if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>( 9710fca6ea1SDimitry Andric RT->getAsCXXRecordDecl())) { 9720fca6ea1SDimitry Andric Template = CTSD->getSpecializedTemplate(); 9730fca6ea1SDimitry Andric AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray(); 9740fca6ea1SDimitry Andric } 9750fca6ea1SDimitry Andric } else { 9760fca6ea1SDimitry Andric assert(false && "unhandled RHS type of the alias"); 9770fca6ea1SDimitry Andric } 9780fca6ea1SDimitry Andric return {Template, AliasRhsTemplateArgs}; 9790fca6ea1SDimitry Andric } 9800fca6ea1SDimitry Andric 9810fca6ea1SDimitry Andric // Build deduction guides for a type alias template from the given underlying 9820fca6ea1SDimitry Andric // deduction guide F. 9830fca6ea1SDimitry Andric FunctionTemplateDecl * 9840fca6ea1SDimitry Andric BuildDeductionGuideForTypeAlias(Sema &SemaRef, 9850fca6ea1SDimitry Andric TypeAliasTemplateDecl *AliasTemplate, 9860fca6ea1SDimitry Andric FunctionTemplateDecl *F, SourceLocation Loc) { 9870fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 9880fca6ea1SDimitry Andric Sema::InstantiatingTemplate BuildingDeductionGuides( 9890fca6ea1SDimitry Andric SemaRef, AliasTemplate->getLocation(), F, 9900fca6ea1SDimitry Andric Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); 9910fca6ea1SDimitry Andric if (BuildingDeductionGuides.isInvalid()) 9920fca6ea1SDimitry Andric return nullptr; 9930fca6ea1SDimitry Andric 9940fca6ea1SDimitry Andric auto &Context = SemaRef.Context; 9950fca6ea1SDimitry Andric auto [Template, AliasRhsTemplateArgs] = 9960fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); 9970fca6ea1SDimitry Andric 9980fca6ea1SDimitry Andric auto RType = F->getTemplatedDecl()->getReturnType(); 9990fca6ea1SDimitry Andric // The (trailing) return type of the deduction guide. 10000fca6ea1SDimitry Andric const TemplateSpecializationType *FReturnType = 10010fca6ea1SDimitry Andric RType->getAs<TemplateSpecializationType>(); 10020fca6ea1SDimitry Andric if (const auto *InjectedCNT = RType->getAs<InjectedClassNameType>()) 10030fca6ea1SDimitry Andric // implicitly-generated deduction guide. 10040fca6ea1SDimitry Andric FReturnType = InjectedCNT->getInjectedTST(); 10050fca6ea1SDimitry Andric else if (const auto *ET = RType->getAs<ElaboratedType>()) 10060fca6ea1SDimitry Andric // explicit deduction guide. 10070fca6ea1SDimitry Andric FReturnType = ET->getNamedType()->getAs<TemplateSpecializationType>(); 10080fca6ea1SDimitry Andric assert(FReturnType && "expected to see a return type"); 10090fca6ea1SDimitry Andric // Deduce template arguments of the deduction guide f from the RHS of 10100fca6ea1SDimitry Andric // the alias. 10110fca6ea1SDimitry Andric // 10120fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p3: ...For each function or function 10130fca6ea1SDimitry Andric // template f in the guides of the template named by the 10140fca6ea1SDimitry Andric // simple-template-id of the defining-type-id, the template arguments 10150fca6ea1SDimitry Andric // of the return type of f are deduced from the defining-type-id of A 10160fca6ea1SDimitry Andric // according to the process in [temp.deduct.type] with the exception 10170fca6ea1SDimitry Andric // that deduction does not fail if not all template arguments are 10180fca6ea1SDimitry Andric // deduced. 10190fca6ea1SDimitry Andric // 10200fca6ea1SDimitry Andric // 10210fca6ea1SDimitry Andric // template<typename X, typename Y> 10220fca6ea1SDimitry Andric // f(X, Y) -> f<Y, X>; 10230fca6ea1SDimitry Andric // 10240fca6ea1SDimitry Andric // template<typename U> 10250fca6ea1SDimitry Andric // using alias = f<int, U>; 10260fca6ea1SDimitry Andric // 10270fca6ea1SDimitry Andric // The RHS of alias is f<int, U>, we deduced the template arguments of 10280fca6ea1SDimitry Andric // the return type of the deduction guide from it: Y->int, X->U 10290fca6ea1SDimitry Andric sema::TemplateDeductionInfo TDeduceInfo(Loc); 10300fca6ea1SDimitry Andric // Must initialize n elements, this is required by DeduceTemplateArguments. 10310fca6ea1SDimitry Andric SmallVector<DeducedTemplateArgument> DeduceResults( 10320fca6ea1SDimitry Andric F->getTemplateParameters()->size()); 10330fca6ea1SDimitry Andric 10340fca6ea1SDimitry Andric // FIXME: DeduceTemplateArguments stops immediately at the first 10350fca6ea1SDimitry Andric // non-deducible template argument. However, this doesn't seem to casue 10360fca6ea1SDimitry Andric // issues for practice cases, we probably need to extend it to continue 10370fca6ea1SDimitry Andric // performing deduction for rest of arguments to align with the C++ 10380fca6ea1SDimitry Andric // standard. 10390fca6ea1SDimitry Andric SemaRef.DeduceTemplateArguments( 10400fca6ea1SDimitry Andric F->getTemplateParameters(), FReturnType->template_arguments(), 10410fca6ea1SDimitry Andric AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, 10420fca6ea1SDimitry Andric /*NumberOfArgumentsMustMatch=*/false); 10430fca6ea1SDimitry Andric 10440fca6ea1SDimitry Andric SmallVector<TemplateArgument> DeducedArgs; 10450fca6ea1SDimitry Andric SmallVector<unsigned> NonDeducedTemplateParamsInFIndex; 10460fca6ea1SDimitry Andric // !!NOTE: DeduceResults respects the sequence of template parameters of 10470fca6ea1SDimitry Andric // the deduction guide f. 10480fca6ea1SDimitry Andric for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { 10490fca6ea1SDimitry Andric if (const auto &D = DeduceResults[Index]; !D.isNull()) // Deduced 10500fca6ea1SDimitry Andric DeducedArgs.push_back(D); 10510fca6ea1SDimitry Andric else 10520fca6ea1SDimitry Andric NonDeducedTemplateParamsInFIndex.push_back(Index); 10530fca6ea1SDimitry Andric } 10540fca6ea1SDimitry Andric auto DeducedAliasTemplateParams = 10550fca6ea1SDimitry Andric TemplateParamsReferencedInTemplateArgumentList( 10560fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters(), DeducedArgs); 10570fca6ea1SDimitry Andric // All template arguments null by default. 10580fca6ea1SDimitry Andric SmallVector<TemplateArgument> TemplateArgsForBuildingFPrime( 10590fca6ea1SDimitry Andric F->getTemplateParameters()->size()); 10600fca6ea1SDimitry Andric 10610fca6ea1SDimitry Andric // Create a template parameter list for the synthesized deduction guide f'. 10620fca6ea1SDimitry Andric // 10630fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p3.2: 10640fca6ea1SDimitry Andric // If f is a function template, f' is a function template whose template 10650fca6ea1SDimitry Andric // parameter list consists of all the template parameters of A 10660fca6ea1SDimitry Andric // (including their default template arguments) that appear in the above 10670fca6ea1SDimitry Andric // deductions or (recursively) in their default template arguments 10680fca6ea1SDimitry Andric SmallVector<NamedDecl *> FPrimeTemplateParams; 10690fca6ea1SDimitry Andric // Store template arguments that refer to the newly-created template 10700fca6ea1SDimitry Andric // parameters, used for building `TemplateArgsForBuildingFPrime`. 10710fca6ea1SDimitry Andric SmallVector<TemplateArgument, 16> TransformedDeducedAliasArgs( 10720fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->size()); 10730fca6ea1SDimitry Andric 10740fca6ea1SDimitry Andric for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) { 10750fca6ea1SDimitry Andric auto *TP = 10760fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx); 10770fca6ea1SDimitry Andric // Rebuild any internal references to earlier parameters and reindex as 10780fca6ea1SDimitry Andric // we go. 10790fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 10800fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 10810fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); 10820fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 10830fca6ea1SDimitry Andric SemaRef, AliasTemplate->getDeclContext(), TP, Args, 10840fca6ea1SDimitry Andric /*NewIndex=*/FPrimeTemplateParams.size(), 10850fca6ea1SDimitry Andric getTemplateParameterDepth(TP)); 10860fca6ea1SDimitry Andric FPrimeTemplateParams.push_back(NewParam); 10870fca6ea1SDimitry Andric 10880fca6ea1SDimitry Andric TemplateArgument NewTemplateArgument = 10890fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 10900fca6ea1SDimitry Andric TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument; 10910fca6ea1SDimitry Andric } 10920fca6ea1SDimitry Andric unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size(); 10930fca6ea1SDimitry Andric // ...followed by the template parameters of f that were not deduced 10940fca6ea1SDimitry Andric // (including their default template arguments) 10950fca6ea1SDimitry Andric for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) { 10960fca6ea1SDimitry Andric auto *TP = F->getTemplateParameters()->getParam(FTemplateParamIdx); 10970fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 10980fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 10990fca6ea1SDimitry Andric // We take a shortcut here, it is ok to reuse the 11000fca6ea1SDimitry Andric // TemplateArgsForBuildingFPrime. 11010fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); 11020fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 11030fca6ea1SDimitry Andric SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(), 11040fca6ea1SDimitry Andric getTemplateParameterDepth(TP)); 11050fca6ea1SDimitry Andric FPrimeTemplateParams.push_back(NewParam); 11060fca6ea1SDimitry Andric 11070fca6ea1SDimitry Andric assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() && 11080fca6ea1SDimitry Andric "The argument must be null before setting"); 11090fca6ea1SDimitry Andric TemplateArgsForBuildingFPrime[FTemplateParamIdx] = 11100fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 11110fca6ea1SDimitry Andric } 11120fca6ea1SDimitry Andric 11130fca6ea1SDimitry Andric // To form a deduction guide f' from f, we leverage clang's instantiation 11140fca6ea1SDimitry Andric // mechanism, we construct a template argument list where the template 11150fca6ea1SDimitry Andric // arguments refer to the newly-created template parameters of f', and 11160fca6ea1SDimitry Andric // then apply instantiation on this template argument list to instantiate 11170fca6ea1SDimitry Andric // f, this ensures all template parameter occurrences are updated 11180fca6ea1SDimitry Andric // correctly. 11190fca6ea1SDimitry Andric // 11200fca6ea1SDimitry Andric // The template argument list is formed from the `DeducedArgs`, two parts: 11210fca6ea1SDimitry Andric // 1) appeared template parameters of alias: transfrom the deduced 11220fca6ea1SDimitry Andric // template argument; 11230fca6ea1SDimitry Andric // 2) non-deduced template parameters of f: rebuild a 11240fca6ea1SDimitry Andric // template argument; 11250fca6ea1SDimitry Andric // 11260fca6ea1SDimitry Andric // 2) has been built already (when rebuilding the new template 11270fca6ea1SDimitry Andric // parameters), we now perform 1). 11280fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 11290fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 11300fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); 11310fca6ea1SDimitry Andric for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { 11320fca6ea1SDimitry Andric const auto &D = DeduceResults[Index]; 11330fca6ea1SDimitry Andric if (D.isNull()) { 11340fca6ea1SDimitry Andric // 2): Non-deduced template parameter has been built already. 11350fca6ea1SDimitry Andric assert(!TemplateArgsForBuildingFPrime[Index].isNull() && 11360fca6ea1SDimitry Andric "template arguments for non-deduced template parameters should " 11370fca6ea1SDimitry Andric "be been set!"); 11380fca6ea1SDimitry Andric continue; 11390fca6ea1SDimitry Andric } 11400fca6ea1SDimitry Andric TemplateArgumentLoc Input = 11410fca6ea1SDimitry Andric SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); 11420fca6ea1SDimitry Andric TemplateArgumentLoc Output; 11430fca6ea1SDimitry Andric if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) { 11440fca6ea1SDimitry Andric assert(TemplateArgsForBuildingFPrime[Index].isNull() && 11450fca6ea1SDimitry Andric "InstantiatedArgs must be null before setting"); 11460fca6ea1SDimitry Andric TemplateArgsForBuildingFPrime[Index] = Output.getArgument(); 11470fca6ea1SDimitry Andric } 11480fca6ea1SDimitry Andric } 11490fca6ea1SDimitry Andric 11500fca6ea1SDimitry Andric auto *TemplateArgListForBuildingFPrime = 11510fca6ea1SDimitry Andric TemplateArgumentList::CreateCopy(Context, TemplateArgsForBuildingFPrime); 11520fca6ea1SDimitry Andric // Form the f' by substituting the template arguments into f. 11530fca6ea1SDimitry Andric if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration( 11540fca6ea1SDimitry Andric F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), 11550fca6ea1SDimitry Andric Sema::CodeSynthesisContext::BuildingDeductionGuides)) { 11560fca6ea1SDimitry Andric auto *GG = cast<CXXDeductionGuideDecl>(FPrime); 11570fca6ea1SDimitry Andric 11580fca6ea1SDimitry Andric Expr *IsDeducible = buildIsDeducibleConstraint( 11590fca6ea1SDimitry Andric SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams); 11600fca6ea1SDimitry Andric Expr *RequiresClause = 11610fca6ea1SDimitry Andric buildAssociatedConstraints(SemaRef, F, AliasTemplate, DeduceResults, 11620fca6ea1SDimitry Andric FirstUndeducedParamIdx, IsDeducible); 11630fca6ea1SDimitry Andric 11640fca6ea1SDimitry Andric auto *FPrimeTemplateParamList = TemplateParameterList::Create( 11650fca6ea1SDimitry Andric Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), 11660fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->getLAngleLoc(), 11670fca6ea1SDimitry Andric FPrimeTemplateParams, 11680fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->getRAngleLoc(), 11690fca6ea1SDimitry Andric /*RequiresClause=*/RequiresClause); 11700fca6ea1SDimitry Andric auto *Result = cast<FunctionTemplateDecl>(buildDeductionGuide( 11710fca6ea1SDimitry Andric SemaRef, AliasTemplate, FPrimeTemplateParamList, 11720fca6ea1SDimitry Andric GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), 11730fca6ea1SDimitry Andric GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(), 11740fca6ea1SDimitry Andric AliasTemplate->getLocation(), AliasTemplate->getEndLoc(), 11750fca6ea1SDimitry Andric F->isImplicit())); 11760fca6ea1SDimitry Andric cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl()) 11770fca6ea1SDimitry Andric ->setDeductionCandidateKind(GG->getDeductionCandidateKind()); 11780fca6ea1SDimitry Andric return Result; 11790fca6ea1SDimitry Andric } 11800fca6ea1SDimitry Andric return nullptr; 11810fca6ea1SDimitry Andric } 11820fca6ea1SDimitry Andric 11830fca6ea1SDimitry Andric void DeclareImplicitDeductionGuidesForTypeAlias( 11840fca6ea1SDimitry Andric Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) { 11850fca6ea1SDimitry Andric if (AliasTemplate->isInvalidDecl()) 11860fca6ea1SDimitry Andric return; 11870fca6ea1SDimitry Andric auto &Context = SemaRef.Context; 11880fca6ea1SDimitry Andric // FIXME: if there is an explicit deduction guide after the first use of the 11890fca6ea1SDimitry Andric // type alias usage, we will not cover this explicit deduction guide. fix this 11900fca6ea1SDimitry Andric // case. 11910fca6ea1SDimitry Andric if (hasDeclaredDeductionGuides( 11920fca6ea1SDimitry Andric Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate), 11930fca6ea1SDimitry Andric AliasTemplate->getDeclContext())) 11940fca6ea1SDimitry Andric return; 11950fca6ea1SDimitry Andric auto [Template, AliasRhsTemplateArgs] = 11960fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); 11970fca6ea1SDimitry Andric if (!Template) 11980fca6ea1SDimitry Andric return; 11990fca6ea1SDimitry Andric DeclarationNameInfo NameInfo( 12000fca6ea1SDimitry Andric Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc); 12010fca6ea1SDimitry Andric LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName); 12020fca6ea1SDimitry Andric SemaRef.LookupQualifiedName(Guides, Template->getDeclContext()); 12030fca6ea1SDimitry Andric Guides.suppressDiagnostics(); 12040fca6ea1SDimitry Andric 12050fca6ea1SDimitry Andric for (auto *G : Guides) { 12060fca6ea1SDimitry Andric if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(G)) { 12070fca6ea1SDimitry Andric // The deduction guide is a non-template function decl, we just clone it. 12080fca6ea1SDimitry Andric auto *FunctionType = 12090fca6ea1SDimitry Andric SemaRef.Context.getTrivialTypeSourceInfo(DG->getType()); 12100fca6ea1SDimitry Andric FunctionProtoTypeLoc FPTL = 12110fca6ea1SDimitry Andric FunctionType->getTypeLoc().castAs<FunctionProtoTypeLoc>(); 12120fca6ea1SDimitry Andric 12130fca6ea1SDimitry Andric // Clone the parameters. 12140fca6ea1SDimitry Andric for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) { 12150fca6ea1SDimitry Andric const auto *P = DG->getParamDecl(I); 12160fca6ea1SDimitry Andric auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(P->getType()); 12170fca6ea1SDimitry Andric ParmVarDecl *NewParam = ParmVarDecl::Create( 12180fca6ea1SDimitry Andric SemaRef.Context, G->getDeclContext(), 12190fca6ea1SDimitry Andric DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr, 12200fca6ea1SDimitry Andric TSI->getType(), TSI, SC_None, nullptr); 12210fca6ea1SDimitry Andric NewParam->setScopeInfo(0, I); 12220fca6ea1SDimitry Andric FPTL.setParam(I, NewParam); 12230fca6ea1SDimitry Andric } 12240fca6ea1SDimitry Andric auto *Transformed = cast<FunctionDecl>(buildDeductionGuide( 12250fca6ea1SDimitry Andric SemaRef, AliasTemplate, /*TemplateParams=*/nullptr, 12260fca6ea1SDimitry Andric /*Constructor=*/nullptr, DG->getExplicitSpecifier(), FunctionType, 12270fca6ea1SDimitry Andric AliasTemplate->getBeginLoc(), AliasTemplate->getLocation(), 12280fca6ea1SDimitry Andric AliasTemplate->getEndLoc(), DG->isImplicit())); 12290fca6ea1SDimitry Andric 12300fca6ea1SDimitry Andric // FIXME: Here the synthesized deduction guide is not a templated 12310fca6ea1SDimitry Andric // function. Per [dcl.decl]p4, the requires-clause shall be present only 12320fca6ea1SDimitry Andric // if the declarator declares a templated function, a bug in standard? 12330fca6ea1SDimitry Andric auto *Constraint = buildIsDeducibleConstraint( 12340fca6ea1SDimitry Andric SemaRef, AliasTemplate, Transformed->getReturnType(), {}); 12350fca6ea1SDimitry Andric if (auto *RC = DG->getTrailingRequiresClause()) { 12360fca6ea1SDimitry Andric auto Conjunction = 12370fca6ea1SDimitry Andric SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, 12380fca6ea1SDimitry Andric BinaryOperatorKind::BO_LAnd, RC, Constraint); 12390fca6ea1SDimitry Andric if (!Conjunction.isInvalid()) 12400fca6ea1SDimitry Andric Constraint = Conjunction.getAs<Expr>(); 12410fca6ea1SDimitry Andric } 12420fca6ea1SDimitry Andric Transformed->setTrailingRequiresClause(Constraint); 12430fca6ea1SDimitry Andric } 12440fca6ea1SDimitry Andric FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G); 12450fca6ea1SDimitry Andric if (!F) 12460fca6ea1SDimitry Andric continue; 12470fca6ea1SDimitry Andric // The **aggregate** deduction guides are handled in a different code path 12480fca6ea1SDimitry Andric // (DeclareAggregateDeductionGuideFromInitList), which involves the tricky 12490fca6ea1SDimitry Andric // cache. 12500fca6ea1SDimitry Andric if (cast<CXXDeductionGuideDecl>(F->getTemplatedDecl()) 12510fca6ea1SDimitry Andric ->getDeductionCandidateKind() == DeductionCandidate::Aggregate) 12520fca6ea1SDimitry Andric continue; 12530fca6ea1SDimitry Andric 12540fca6ea1SDimitry Andric BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc); 12550fca6ea1SDimitry Andric } 12560fca6ea1SDimitry Andric } 12570fca6ea1SDimitry Andric 12580fca6ea1SDimitry Andric // Build an aggregate deduction guide for a type alias template. 12590fca6ea1SDimitry Andric FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias( 12600fca6ea1SDimitry Andric Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, 12610fca6ea1SDimitry Andric MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) { 12620fca6ea1SDimitry Andric TemplateDecl *RHSTemplate = 12630fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first; 12640fca6ea1SDimitry Andric if (!RHSTemplate) 12650fca6ea1SDimitry Andric return nullptr; 1266*d686ce93SDimitry Andric 1267*d686ce93SDimitry Andric llvm::SmallVector<TypedefNameDecl *> TypedefDecls; 1268*d686ce93SDimitry Andric llvm::SmallVector<QualType> NewParamTypes; 1269*d686ce93SDimitry Andric ExtractTypeForDeductionGuide TypeAliasTransformer(SemaRef, TypedefDecls); 1270*d686ce93SDimitry Andric for (QualType P : ParamTypes) { 1271*d686ce93SDimitry Andric QualType Type = TypeAliasTransformer.TransformType(P); 1272*d686ce93SDimitry Andric if (Type.isNull()) 1273*d686ce93SDimitry Andric return nullptr; 1274*d686ce93SDimitry Andric NewParamTypes.push_back(Type); 1275*d686ce93SDimitry Andric } 1276*d686ce93SDimitry Andric 12770fca6ea1SDimitry Andric auto *RHSDeductionGuide = SemaRef.DeclareAggregateDeductionGuideFromInitList( 1278*d686ce93SDimitry Andric RHSTemplate, NewParamTypes, Loc); 12790fca6ea1SDimitry Andric if (!RHSDeductionGuide) 12800fca6ea1SDimitry Andric return nullptr; 1281*d686ce93SDimitry Andric 1282*d686ce93SDimitry Andric for (TypedefNameDecl *TD : TypedefDecls) 1283*d686ce93SDimitry Andric TD->setDeclContext(RHSDeductionGuide->getTemplatedDecl()); 1284*d686ce93SDimitry Andric 12850fca6ea1SDimitry Andric return BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, 12860fca6ea1SDimitry Andric RHSDeductionGuide, Loc); 12870fca6ea1SDimitry Andric } 12880fca6ea1SDimitry Andric 12890fca6ea1SDimitry Andric } // namespace 12900fca6ea1SDimitry Andric 12910fca6ea1SDimitry Andric FunctionTemplateDecl *Sema::DeclareAggregateDeductionGuideFromInitList( 12920fca6ea1SDimitry Andric TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes, 12930fca6ea1SDimitry Andric SourceLocation Loc) { 12940fca6ea1SDimitry Andric llvm::FoldingSetNodeID ID; 12950fca6ea1SDimitry Andric ID.AddPointer(Template); 12960fca6ea1SDimitry Andric for (auto &T : ParamTypes) 12970fca6ea1SDimitry Andric T.getCanonicalType().Profile(ID); 12980fca6ea1SDimitry Andric unsigned Hash = ID.ComputeHash(); 12990fca6ea1SDimitry Andric 13000fca6ea1SDimitry Andric auto Found = AggregateDeductionCandidates.find(Hash); 13010fca6ea1SDimitry Andric if (Found != AggregateDeductionCandidates.end()) { 13020fca6ea1SDimitry Andric CXXDeductionGuideDecl *GD = Found->getSecond(); 13030fca6ea1SDimitry Andric return GD->getDescribedFunctionTemplate(); 13040fca6ea1SDimitry Andric } 13050fca6ea1SDimitry Andric 13060fca6ea1SDimitry Andric if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { 13070fca6ea1SDimitry Andric if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias( 13080fca6ea1SDimitry Andric *this, AliasTemplate, ParamTypes, Loc)) { 13090fca6ea1SDimitry Andric auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); 13100fca6ea1SDimitry Andric GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); 13110fca6ea1SDimitry Andric AggregateDeductionCandidates[Hash] = GD; 13120fca6ea1SDimitry Andric return FTD; 13130fca6ea1SDimitry Andric } 13140fca6ea1SDimitry Andric } 13150fca6ea1SDimitry Andric 13160fca6ea1SDimitry Andric if (CXXRecordDecl *DefRecord = 13170fca6ea1SDimitry Andric cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { 13180fca6ea1SDimitry Andric if (TemplateDecl *DescribedTemplate = 13190fca6ea1SDimitry Andric DefRecord->getDescribedClassTemplate()) 13200fca6ea1SDimitry Andric Template = DescribedTemplate; 13210fca6ea1SDimitry Andric } 13220fca6ea1SDimitry Andric 13230fca6ea1SDimitry Andric DeclContext *DC = Template->getDeclContext(); 13240fca6ea1SDimitry Andric if (DC->isDependentContext()) 13250fca6ea1SDimitry Andric return nullptr; 13260fca6ea1SDimitry Andric 13270fca6ea1SDimitry Andric ConvertConstructorToDeductionGuideTransform Transform( 13280fca6ea1SDimitry Andric *this, cast<ClassTemplateDecl>(Template)); 13290fca6ea1SDimitry Andric if (!isCompleteType(Loc, Transform.DeducedType)) 13300fca6ea1SDimitry Andric return nullptr; 13310fca6ea1SDimitry Andric 13320fca6ea1SDimitry Andric // In case we were expanding a pack when we attempted to declare deduction 13330fca6ea1SDimitry Andric // guides, turn off pack expansion for everything we're about to do. 13340fca6ea1SDimitry Andric ArgumentPackSubstitutionIndexRAII SubstIndex(*this, 13350fca6ea1SDimitry Andric /*NewSubstitutionIndex=*/-1); 13360fca6ea1SDimitry Andric // Create a template instantiation record to track the "instantiation" of 13370fca6ea1SDimitry Andric // constructors into deduction guides. 13380fca6ea1SDimitry Andric InstantiatingTemplate BuildingDeductionGuides( 13390fca6ea1SDimitry Andric *this, Loc, Template, 13400fca6ea1SDimitry Andric Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); 13410fca6ea1SDimitry Andric if (BuildingDeductionGuides.isInvalid()) 13420fca6ea1SDimitry Andric return nullptr; 13430fca6ea1SDimitry Andric 13440fca6ea1SDimitry Andric ClassTemplateDecl *Pattern = 13450fca6ea1SDimitry Andric Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; 13460fca6ea1SDimitry Andric ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); 13470fca6ea1SDimitry Andric 13480fca6ea1SDimitry Andric auto *FTD = cast<FunctionTemplateDecl>( 13490fca6ea1SDimitry Andric Transform.buildSimpleDeductionGuide(ParamTypes)); 13500fca6ea1SDimitry Andric SavedContext.pop(); 13510fca6ea1SDimitry Andric auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); 13520fca6ea1SDimitry Andric GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); 13530fca6ea1SDimitry Andric AggregateDeductionCandidates[Hash] = GD; 13540fca6ea1SDimitry Andric return FTD; 13550fca6ea1SDimitry Andric } 13560fca6ea1SDimitry Andric 13570fca6ea1SDimitry Andric void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, 13580fca6ea1SDimitry Andric SourceLocation Loc) { 13590fca6ea1SDimitry Andric if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { 13600fca6ea1SDimitry Andric DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc); 13610fca6ea1SDimitry Andric return; 13620fca6ea1SDimitry Andric } 13630fca6ea1SDimitry Andric if (CXXRecordDecl *DefRecord = 13640fca6ea1SDimitry Andric cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { 13650fca6ea1SDimitry Andric if (TemplateDecl *DescribedTemplate = 13660fca6ea1SDimitry Andric DefRecord->getDescribedClassTemplate()) 13670fca6ea1SDimitry Andric Template = DescribedTemplate; 13680fca6ea1SDimitry Andric } 13690fca6ea1SDimitry Andric 13700fca6ea1SDimitry Andric DeclContext *DC = Template->getDeclContext(); 13710fca6ea1SDimitry Andric if (DC->isDependentContext()) 13720fca6ea1SDimitry Andric return; 13730fca6ea1SDimitry Andric 13740fca6ea1SDimitry Andric ConvertConstructorToDeductionGuideTransform Transform( 13750fca6ea1SDimitry Andric *this, cast<ClassTemplateDecl>(Template)); 13760fca6ea1SDimitry Andric if (!isCompleteType(Loc, Transform.DeducedType)) 13770fca6ea1SDimitry Andric return; 13780fca6ea1SDimitry Andric 13790fca6ea1SDimitry Andric if (hasDeclaredDeductionGuides(Transform.DeductionGuideName, DC)) 13800fca6ea1SDimitry Andric return; 13810fca6ea1SDimitry Andric 13820fca6ea1SDimitry Andric // In case we were expanding a pack when we attempted to declare deduction 13830fca6ea1SDimitry Andric // guides, turn off pack expansion for everything we're about to do. 13840fca6ea1SDimitry Andric ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); 13850fca6ea1SDimitry Andric // Create a template instantiation record to track the "instantiation" of 13860fca6ea1SDimitry Andric // constructors into deduction guides. 13870fca6ea1SDimitry Andric InstantiatingTemplate BuildingDeductionGuides( 13880fca6ea1SDimitry Andric *this, Loc, Template, 13890fca6ea1SDimitry Andric Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); 13900fca6ea1SDimitry Andric if (BuildingDeductionGuides.isInvalid()) 13910fca6ea1SDimitry Andric return; 13920fca6ea1SDimitry Andric 13930fca6ea1SDimitry Andric // Convert declared constructors into deduction guide templates. 13940fca6ea1SDimitry Andric // FIXME: Skip constructors for which deduction must necessarily fail (those 13950fca6ea1SDimitry Andric // for which some class template parameter without a default argument never 13960fca6ea1SDimitry Andric // appears in a deduced context). 13970fca6ea1SDimitry Andric ClassTemplateDecl *Pattern = 13980fca6ea1SDimitry Andric Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; 13990fca6ea1SDimitry Andric ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); 14000fca6ea1SDimitry Andric llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors; 14010fca6ea1SDimitry Andric bool AddedAny = false; 14020fca6ea1SDimitry Andric for (NamedDecl *D : LookupConstructors(Pattern->getTemplatedDecl())) { 14030fca6ea1SDimitry Andric D = D->getUnderlyingDecl(); 14040fca6ea1SDimitry Andric if (D->isInvalidDecl() || D->isImplicit()) 14050fca6ea1SDimitry Andric continue; 14060fca6ea1SDimitry Andric 14070fca6ea1SDimitry Andric D = cast<NamedDecl>(D->getCanonicalDecl()); 14080fca6ea1SDimitry Andric 14090fca6ea1SDimitry Andric // Within C++20 modules, we may have multiple same constructors in 14100fca6ea1SDimitry Andric // multiple same RecordDecls. And it doesn't make sense to create 14110fca6ea1SDimitry Andric // duplicated deduction guides for the duplicated constructors. 14120fca6ea1SDimitry Andric if (ProcessedCtors.count(D)) 14130fca6ea1SDimitry Andric continue; 14140fca6ea1SDimitry Andric 14150fca6ea1SDimitry Andric auto *FTD = dyn_cast<FunctionTemplateDecl>(D); 14160fca6ea1SDimitry Andric auto *CD = 14170fca6ea1SDimitry Andric dyn_cast_or_null<CXXConstructorDecl>(FTD ? FTD->getTemplatedDecl() : D); 14180fca6ea1SDimitry Andric // Class-scope explicit specializations (MS extension) do not result in 14190fca6ea1SDimitry Andric // deduction guides. 14200fca6ea1SDimitry Andric if (!CD || (!FTD && CD->isFunctionTemplateSpecialization())) 14210fca6ea1SDimitry Andric continue; 14220fca6ea1SDimitry Andric 14230fca6ea1SDimitry Andric // Cannot make a deduction guide when unparsed arguments are present. 14240fca6ea1SDimitry Andric if (llvm::any_of(CD->parameters(), [](ParmVarDecl *P) { 14250fca6ea1SDimitry Andric return !P || P->hasUnparsedDefaultArg(); 14260fca6ea1SDimitry Andric })) 14270fca6ea1SDimitry Andric continue; 14280fca6ea1SDimitry Andric 14290fca6ea1SDimitry Andric ProcessedCtors.insert(D); 14300fca6ea1SDimitry Andric Transform.transformConstructor(FTD, CD); 14310fca6ea1SDimitry Andric AddedAny = true; 14320fca6ea1SDimitry Andric } 14330fca6ea1SDimitry Andric 14340fca6ea1SDimitry Andric // C++17 [over.match.class.deduct] 14350fca6ea1SDimitry Andric // -- If C is not defined or does not declare any constructors, an 14360fca6ea1SDimitry Andric // additional function template derived as above from a hypothetical 14370fca6ea1SDimitry Andric // constructor C(). 14380fca6ea1SDimitry Andric if (!AddedAny) 14390fca6ea1SDimitry Andric Transform.buildSimpleDeductionGuide(std::nullopt); 14400fca6ea1SDimitry Andric 14410fca6ea1SDimitry Andric // -- An additional function template derived as above from a hypothetical 14420fca6ea1SDimitry Andric // constructor C(C), called the copy deduction candidate. 14430fca6ea1SDimitry Andric cast<CXXDeductionGuideDecl>( 14440fca6ea1SDimitry Andric cast<FunctionTemplateDecl>( 14450fca6ea1SDimitry Andric Transform.buildSimpleDeductionGuide(Transform.DeducedType)) 14460fca6ea1SDimitry Andric ->getTemplatedDecl()) 14470fca6ea1SDimitry Andric ->setDeductionCandidateKind(DeductionCandidate::Copy); 14480fca6ea1SDimitry Andric 14490fca6ea1SDimitry Andric SavedContext.pop(); 14500fca6ea1SDimitry Andric } 1451