1*0fca6ea1SDimitry Andric //===- SemaTemplateDeductionGude.cpp - Template Argument Deduction---------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file implements deduction guides for C++ class template argument 10*0fca6ea1SDimitry Andric // deduction. 11*0fca6ea1SDimitry Andric // 12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #include "TreeTransform.h" 15*0fca6ea1SDimitry Andric #include "TypeLocBuilder.h" 16*0fca6ea1SDimitry Andric #include "clang/AST/ASTConsumer.h" 17*0fca6ea1SDimitry Andric #include "clang/AST/ASTContext.h" 18*0fca6ea1SDimitry Andric #include "clang/AST/Decl.h" 19*0fca6ea1SDimitry Andric #include "clang/AST/DeclBase.h" 20*0fca6ea1SDimitry Andric #include "clang/AST/DeclCXX.h" 21*0fca6ea1SDimitry Andric #include "clang/AST/DeclFriend.h" 22*0fca6ea1SDimitry Andric #include "clang/AST/DeclTemplate.h" 23*0fca6ea1SDimitry Andric #include "clang/AST/DeclarationName.h" 24*0fca6ea1SDimitry Andric #include "clang/AST/Expr.h" 25*0fca6ea1SDimitry Andric #include "clang/AST/ExprCXX.h" 26*0fca6ea1SDimitry Andric #include "clang/AST/OperationKinds.h" 27*0fca6ea1SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 28*0fca6ea1SDimitry Andric #include "clang/AST/TemplateBase.h" 29*0fca6ea1SDimitry Andric #include "clang/AST/TemplateName.h" 30*0fca6ea1SDimitry Andric #include "clang/AST/Type.h" 31*0fca6ea1SDimitry Andric #include "clang/AST/TypeLoc.h" 32*0fca6ea1SDimitry Andric #include "clang/Basic/LLVM.h" 33*0fca6ea1SDimitry Andric #include "clang/Basic/SourceLocation.h" 34*0fca6ea1SDimitry Andric #include "clang/Basic/Specifiers.h" 35*0fca6ea1SDimitry Andric #include "clang/Basic/TypeTraits.h" 36*0fca6ea1SDimitry Andric #include "clang/Sema/DeclSpec.h" 37*0fca6ea1SDimitry Andric #include "clang/Sema/Initialization.h" 38*0fca6ea1SDimitry Andric #include "clang/Sema/Lookup.h" 39*0fca6ea1SDimitry Andric #include "clang/Sema/Overload.h" 40*0fca6ea1SDimitry Andric #include "clang/Sema/Ownership.h" 41*0fca6ea1SDimitry Andric #include "clang/Sema/Scope.h" 42*0fca6ea1SDimitry Andric #include "clang/Sema/Template.h" 43*0fca6ea1SDimitry Andric #include "clang/Sema/TemplateDeduction.h" 44*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h" 45*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseSet.h" 46*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 47*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallVector.h" 48*0fca6ea1SDimitry Andric #include "llvm/Support/Casting.h" 49*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 50*0fca6ea1SDimitry Andric #include <cassert> 51*0fca6ea1SDimitry Andric #include <optional> 52*0fca6ea1SDimitry Andric #include <utility> 53*0fca6ea1SDimitry Andric 54*0fca6ea1SDimitry Andric using namespace clang; 55*0fca6ea1SDimitry Andric using namespace sema; 56*0fca6ea1SDimitry Andric 57*0fca6ea1SDimitry Andric namespace { 58*0fca6ea1SDimitry Andric /// Tree transform to "extract" a transformed type from a class template's 59*0fca6ea1SDimitry Andric /// constructor to a deduction guide. 60*0fca6ea1SDimitry Andric class ExtractTypeForDeductionGuide 61*0fca6ea1SDimitry Andric : public TreeTransform<ExtractTypeForDeductionGuide> { 62*0fca6ea1SDimitry Andric llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs; 63*0fca6ea1SDimitry Andric ClassTemplateDecl *NestedPattern; 64*0fca6ea1SDimitry Andric const MultiLevelTemplateArgumentList *OuterInstantiationArgs; 65*0fca6ea1SDimitry Andric std::optional<TemplateDeclInstantiator> TypedefNameInstantiator; 66*0fca6ea1SDimitry Andric 67*0fca6ea1SDimitry Andric public: 68*0fca6ea1SDimitry Andric typedef TreeTransform<ExtractTypeForDeductionGuide> Base; 69*0fca6ea1SDimitry Andric ExtractTypeForDeductionGuide( 70*0fca6ea1SDimitry Andric Sema &SemaRef, 71*0fca6ea1SDimitry Andric llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs, 72*0fca6ea1SDimitry Andric ClassTemplateDecl *NestedPattern, 73*0fca6ea1SDimitry Andric const MultiLevelTemplateArgumentList *OuterInstantiationArgs) 74*0fca6ea1SDimitry Andric : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs), 75*0fca6ea1SDimitry Andric NestedPattern(NestedPattern), 76*0fca6ea1SDimitry Andric OuterInstantiationArgs(OuterInstantiationArgs) { 77*0fca6ea1SDimitry Andric if (OuterInstantiationArgs) 78*0fca6ea1SDimitry Andric TypedefNameInstantiator.emplace( 79*0fca6ea1SDimitry Andric SemaRef, SemaRef.getASTContext().getTranslationUnitDecl(), 80*0fca6ea1SDimitry Andric *OuterInstantiationArgs); 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric /// Returns true if it's safe to substitute \p Typedef with 86*0fca6ea1SDimitry Andric /// \p OuterInstantiationArgs. 87*0fca6ea1SDimitry Andric bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) { 88*0fca6ea1SDimitry Andric if (!NestedPattern) 89*0fca6ea1SDimitry Andric return false; 90*0fca6ea1SDimitry Andric 91*0fca6ea1SDimitry Andric static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) { 92*0fca6ea1SDimitry Andric if (DC->Equals(TargetDC)) 93*0fca6ea1SDimitry Andric return true; 94*0fca6ea1SDimitry Andric while (DC->isRecord()) { 95*0fca6ea1SDimitry Andric if (DC->Equals(TargetDC)) 96*0fca6ea1SDimitry Andric return true; 97*0fca6ea1SDimitry Andric DC = DC->getParent(); 98*0fca6ea1SDimitry Andric } 99*0fca6ea1SDimitry Andric return false; 100*0fca6ea1SDimitry Andric }; 101*0fca6ea1SDimitry Andric 102*0fca6ea1SDimitry Andric if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl())) 103*0fca6ea1SDimitry Andric return true; 104*0fca6ea1SDimitry Andric if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext())) 105*0fca6ea1SDimitry Andric return true; 106*0fca6ea1SDimitry Andric return false; 107*0fca6ea1SDimitry Andric } 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric QualType 110*0fca6ea1SDimitry Andric RebuildTemplateSpecializationType(TemplateName Template, 111*0fca6ea1SDimitry Andric SourceLocation TemplateNameLoc, 112*0fca6ea1SDimitry Andric TemplateArgumentListInfo &TemplateArgs) { 113*0fca6ea1SDimitry Andric if (!OuterInstantiationArgs || 114*0fca6ea1SDimitry Andric !isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) 115*0fca6ea1SDimitry Andric return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, 116*0fca6ea1SDimitry Andric TemplateArgs); 117*0fca6ea1SDimitry Andric 118*0fca6ea1SDimitry Andric auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); 119*0fca6ea1SDimitry Andric auto *Pattern = TATD; 120*0fca6ea1SDimitry Andric while (Pattern->getInstantiatedFromMemberTemplate()) 121*0fca6ea1SDimitry Andric Pattern = Pattern->getInstantiatedFromMemberTemplate(); 122*0fca6ea1SDimitry Andric if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl())) 123*0fca6ea1SDimitry Andric return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, 124*0fca6ea1SDimitry Andric TemplateArgs); 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric Decl *NewD = 127*0fca6ea1SDimitry Andric TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD); 128*0fca6ea1SDimitry Andric if (!NewD) 129*0fca6ea1SDimitry Andric return QualType(); 130*0fca6ea1SDimitry Andric 131*0fca6ea1SDimitry Andric auto *NewTATD = cast<TypeAliasTemplateDecl>(NewD); 132*0fca6ea1SDimitry Andric MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl()); 133*0fca6ea1SDimitry Andric 134*0fca6ea1SDimitry Andric return Base::RebuildTemplateSpecializationType( 135*0fca6ea1SDimitry Andric TemplateName(NewTATD), TemplateNameLoc, TemplateArgs); 136*0fca6ea1SDimitry Andric } 137*0fca6ea1SDimitry Andric 138*0fca6ea1SDimitry Andric QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { 139*0fca6ea1SDimitry Andric ASTContext &Context = SemaRef.getASTContext(); 140*0fca6ea1SDimitry Andric TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); 141*0fca6ea1SDimitry Andric TypedefNameDecl *Decl = OrigDecl; 142*0fca6ea1SDimitry Andric // Transform the underlying type of the typedef and clone the Decl only if 143*0fca6ea1SDimitry Andric // the typedef has a dependent context. 144*0fca6ea1SDimitry Andric bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext(); 145*0fca6ea1SDimitry Andric 146*0fca6ea1SDimitry Andric // A typedef/alias Decl within the NestedPattern may reference the outer 147*0fca6ea1SDimitry Andric // template parameters. They're substituted with corresponding instantiation 148*0fca6ea1SDimitry Andric // arguments here and in RebuildTemplateSpecializationType() above. 149*0fca6ea1SDimitry Andric // Otherwise, we would have a CTAD guide with "dangling" template 150*0fca6ea1SDimitry Andric // parameters. 151*0fca6ea1SDimitry Andric // For example, 152*0fca6ea1SDimitry Andric // template <class T> struct Outer { 153*0fca6ea1SDimitry Andric // using Alias = S<T>; 154*0fca6ea1SDimitry Andric // template <class U> struct Inner { 155*0fca6ea1SDimitry Andric // Inner(Alias); 156*0fca6ea1SDimitry Andric // }; 157*0fca6ea1SDimitry Andric // }; 158*0fca6ea1SDimitry Andric if (OuterInstantiationArgs && InDependentContext && 159*0fca6ea1SDimitry Andric TL.getTypePtr()->isInstantiationDependentType()) { 160*0fca6ea1SDimitry Andric Decl = cast_if_present<TypedefNameDecl>( 161*0fca6ea1SDimitry Andric TypedefNameInstantiator->InstantiateTypedefNameDecl( 162*0fca6ea1SDimitry Andric OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl))); 163*0fca6ea1SDimitry Andric if (!Decl) 164*0fca6ea1SDimitry Andric return QualType(); 165*0fca6ea1SDimitry Andric MaterializedTypedefs.push_back(Decl); 166*0fca6ea1SDimitry Andric } else if (InDependentContext) { 167*0fca6ea1SDimitry Andric TypeLocBuilder InnerTLB; 168*0fca6ea1SDimitry Andric QualType Transformed = 169*0fca6ea1SDimitry Andric TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); 170*0fca6ea1SDimitry Andric TypeSourceInfo *TSI = InnerTLB.getTypeSourceInfo(Context, Transformed); 171*0fca6ea1SDimitry Andric if (isa<TypeAliasDecl>(OrigDecl)) 172*0fca6ea1SDimitry Andric Decl = TypeAliasDecl::Create( 173*0fca6ea1SDimitry Andric Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), 174*0fca6ea1SDimitry Andric OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); 175*0fca6ea1SDimitry Andric else { 176*0fca6ea1SDimitry Andric assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef"); 177*0fca6ea1SDimitry Andric Decl = TypedefDecl::Create( 178*0fca6ea1SDimitry Andric Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), 179*0fca6ea1SDimitry Andric OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); 180*0fca6ea1SDimitry Andric } 181*0fca6ea1SDimitry Andric MaterializedTypedefs.push_back(Decl); 182*0fca6ea1SDimitry Andric } 183*0fca6ea1SDimitry Andric 184*0fca6ea1SDimitry Andric QualType TDTy = Context.getTypedefType(Decl); 185*0fca6ea1SDimitry Andric TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy); 186*0fca6ea1SDimitry Andric TypedefTL.setNameLoc(TL.getNameLoc()); 187*0fca6ea1SDimitry Andric 188*0fca6ea1SDimitry Andric return TDTy; 189*0fca6ea1SDimitry Andric } 190*0fca6ea1SDimitry Andric }; 191*0fca6ea1SDimitry Andric 192*0fca6ea1SDimitry Andric // Build a deduction guide using the provided information. 193*0fca6ea1SDimitry Andric // 194*0fca6ea1SDimitry Andric // A deduction guide can be either a template or a non-template function 195*0fca6ea1SDimitry Andric // declaration. If \p TemplateParams is null, a non-template function 196*0fca6ea1SDimitry Andric // declaration will be created. 197*0fca6ea1SDimitry Andric NamedDecl *buildDeductionGuide( 198*0fca6ea1SDimitry Andric Sema &SemaRef, TemplateDecl *OriginalTemplate, 199*0fca6ea1SDimitry Andric TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor, 200*0fca6ea1SDimitry Andric ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart, 201*0fca6ea1SDimitry Andric SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit, 202*0fca6ea1SDimitry Andric llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}) { 203*0fca6ea1SDimitry Andric DeclContext *DC = OriginalTemplate->getDeclContext(); 204*0fca6ea1SDimitry Andric auto DeductionGuideName = 205*0fca6ea1SDimitry Andric SemaRef.Context.DeclarationNames.getCXXDeductionGuideName( 206*0fca6ea1SDimitry Andric OriginalTemplate); 207*0fca6ea1SDimitry Andric 208*0fca6ea1SDimitry Andric DeclarationNameInfo Name(DeductionGuideName, Loc); 209*0fca6ea1SDimitry Andric ArrayRef<ParmVarDecl *> Params = 210*0fca6ea1SDimitry Andric TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(); 211*0fca6ea1SDimitry Andric 212*0fca6ea1SDimitry Andric // Build the implicit deduction guide template. 213*0fca6ea1SDimitry Andric auto *Guide = 214*0fca6ea1SDimitry Andric CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name, 215*0fca6ea1SDimitry Andric TInfo->getType(), TInfo, LocEnd, Ctor); 216*0fca6ea1SDimitry Andric Guide->setImplicit(IsImplicit); 217*0fca6ea1SDimitry Andric Guide->setParams(Params); 218*0fca6ea1SDimitry Andric 219*0fca6ea1SDimitry Andric for (auto *Param : Params) 220*0fca6ea1SDimitry Andric Param->setDeclContext(Guide); 221*0fca6ea1SDimitry Andric for (auto *TD : MaterializedTypedefs) 222*0fca6ea1SDimitry Andric TD->setDeclContext(Guide); 223*0fca6ea1SDimitry Andric if (isa<CXXRecordDecl>(DC)) 224*0fca6ea1SDimitry Andric Guide->setAccess(AS_public); 225*0fca6ea1SDimitry Andric 226*0fca6ea1SDimitry Andric if (!TemplateParams) { 227*0fca6ea1SDimitry Andric DC->addDecl(Guide); 228*0fca6ea1SDimitry Andric return Guide; 229*0fca6ea1SDimitry Andric } 230*0fca6ea1SDimitry Andric 231*0fca6ea1SDimitry Andric auto *GuideTemplate = FunctionTemplateDecl::Create( 232*0fca6ea1SDimitry Andric SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide); 233*0fca6ea1SDimitry Andric GuideTemplate->setImplicit(IsImplicit); 234*0fca6ea1SDimitry Andric Guide->setDescribedFunctionTemplate(GuideTemplate); 235*0fca6ea1SDimitry Andric 236*0fca6ea1SDimitry Andric if (isa<CXXRecordDecl>(DC)) 237*0fca6ea1SDimitry Andric GuideTemplate->setAccess(AS_public); 238*0fca6ea1SDimitry Andric 239*0fca6ea1SDimitry Andric DC->addDecl(GuideTemplate); 240*0fca6ea1SDimitry Andric return GuideTemplate; 241*0fca6ea1SDimitry Andric } 242*0fca6ea1SDimitry Andric 243*0fca6ea1SDimitry Andric // Transform a given template type parameter `TTP`. 244*0fca6ea1SDimitry Andric TemplateTypeParmDecl * 245*0fca6ea1SDimitry Andric transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC, 246*0fca6ea1SDimitry Andric TemplateTypeParmDecl *TTP, 247*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, 248*0fca6ea1SDimitry Andric unsigned NewDepth, unsigned NewIndex) { 249*0fca6ea1SDimitry Andric // TemplateTypeParmDecl's index cannot be changed after creation, so 250*0fca6ea1SDimitry Andric // substitute it directly. 251*0fca6ea1SDimitry Andric auto *NewTTP = TemplateTypeParmDecl::Create( 252*0fca6ea1SDimitry Andric SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth, 253*0fca6ea1SDimitry Andric NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(), 254*0fca6ea1SDimitry Andric TTP->isParameterPack(), TTP->hasTypeConstraint(), 255*0fca6ea1SDimitry Andric TTP->isExpandedParameterPack() 256*0fca6ea1SDimitry Andric ? std::optional<unsigned>(TTP->getNumExpansionParameters()) 257*0fca6ea1SDimitry Andric : std::nullopt); 258*0fca6ea1SDimitry Andric if (const auto *TC = TTP->getTypeConstraint()) 259*0fca6ea1SDimitry Andric SemaRef.SubstTypeConstraint(NewTTP, TC, Args, 260*0fca6ea1SDimitry Andric /*EvaluateConstraint=*/true); 261*0fca6ea1SDimitry Andric if (TTP->hasDefaultArgument()) { 262*0fca6ea1SDimitry Andric TemplateArgumentLoc InstantiatedDefaultArg; 263*0fca6ea1SDimitry Andric if (!SemaRef.SubstTemplateArgument( 264*0fca6ea1SDimitry Andric TTP->getDefaultArgument(), Args, InstantiatedDefaultArg, 265*0fca6ea1SDimitry Andric TTP->getDefaultArgumentLoc(), TTP->getDeclName())) 266*0fca6ea1SDimitry Andric NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg); 267*0fca6ea1SDimitry Andric } 268*0fca6ea1SDimitry Andric SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP); 269*0fca6ea1SDimitry Andric return NewTTP; 270*0fca6ea1SDimitry Andric } 271*0fca6ea1SDimitry Andric // Similar to above, but for non-type template or template template parameters. 272*0fca6ea1SDimitry Andric template <typename NonTypeTemplateOrTemplateTemplateParmDecl> 273*0fca6ea1SDimitry Andric NonTypeTemplateOrTemplateTemplateParmDecl * 274*0fca6ea1SDimitry Andric transformTemplateParam(Sema &SemaRef, DeclContext *DC, 275*0fca6ea1SDimitry Andric NonTypeTemplateOrTemplateTemplateParmDecl *OldParam, 276*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, unsigned NewIndex, 277*0fca6ea1SDimitry Andric unsigned NewDepth) { 278*0fca6ea1SDimitry Andric // Ask the template instantiator to do the heavy lifting for us, then adjust 279*0fca6ea1SDimitry Andric // the index of the parameter once it's done. 280*0fca6ea1SDimitry Andric auto *NewParam = cast<NonTypeTemplateOrTemplateTemplateParmDecl>( 281*0fca6ea1SDimitry Andric SemaRef.SubstDecl(OldParam, DC, Args)); 282*0fca6ea1SDimitry Andric NewParam->setPosition(NewIndex); 283*0fca6ea1SDimitry Andric NewParam->setDepth(NewDepth); 284*0fca6ea1SDimitry Andric return NewParam; 285*0fca6ea1SDimitry Andric } 286*0fca6ea1SDimitry Andric 287*0fca6ea1SDimitry Andric /// Transform to convert portions of a constructor declaration into the 288*0fca6ea1SDimitry Andric /// corresponding deduction guide, per C++1z [over.match.class.deduct]p1. 289*0fca6ea1SDimitry Andric struct ConvertConstructorToDeductionGuideTransform { 290*0fca6ea1SDimitry Andric ConvertConstructorToDeductionGuideTransform(Sema &S, 291*0fca6ea1SDimitry Andric ClassTemplateDecl *Template) 292*0fca6ea1SDimitry Andric : SemaRef(S), Template(Template) { 293*0fca6ea1SDimitry Andric // If the template is nested, then we need to use the original 294*0fca6ea1SDimitry Andric // pattern to iterate over the constructors. 295*0fca6ea1SDimitry Andric ClassTemplateDecl *Pattern = Template; 296*0fca6ea1SDimitry Andric while (Pattern->getInstantiatedFromMemberTemplate()) { 297*0fca6ea1SDimitry Andric if (Pattern->isMemberSpecialization()) 298*0fca6ea1SDimitry Andric break; 299*0fca6ea1SDimitry Andric Pattern = Pattern->getInstantiatedFromMemberTemplate(); 300*0fca6ea1SDimitry Andric NestedPattern = Pattern; 301*0fca6ea1SDimitry Andric } 302*0fca6ea1SDimitry Andric 303*0fca6ea1SDimitry Andric if (NestedPattern) 304*0fca6ea1SDimitry Andric OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template); 305*0fca6ea1SDimitry Andric } 306*0fca6ea1SDimitry Andric 307*0fca6ea1SDimitry Andric Sema &SemaRef; 308*0fca6ea1SDimitry Andric ClassTemplateDecl *Template; 309*0fca6ea1SDimitry Andric ClassTemplateDecl *NestedPattern = nullptr; 310*0fca6ea1SDimitry Andric 311*0fca6ea1SDimitry Andric DeclContext *DC = Template->getDeclContext(); 312*0fca6ea1SDimitry Andric CXXRecordDecl *Primary = Template->getTemplatedDecl(); 313*0fca6ea1SDimitry Andric DeclarationName DeductionGuideName = 314*0fca6ea1SDimitry Andric SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template); 315*0fca6ea1SDimitry Andric 316*0fca6ea1SDimitry Andric QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary); 317*0fca6ea1SDimitry Andric 318*0fca6ea1SDimitry Andric // Index adjustment to apply to convert depth-1 template parameters into 319*0fca6ea1SDimitry Andric // depth-0 template parameters. 320*0fca6ea1SDimitry Andric unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size(); 321*0fca6ea1SDimitry Andric 322*0fca6ea1SDimitry Andric // Instantiation arguments for the outermost depth-1 templates 323*0fca6ea1SDimitry Andric // when the template is nested 324*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList OuterInstantiationArgs; 325*0fca6ea1SDimitry Andric 326*0fca6ea1SDimitry Andric /// Transform a constructor declaration into a deduction guide. 327*0fca6ea1SDimitry Andric NamedDecl *transformConstructor(FunctionTemplateDecl *FTD, 328*0fca6ea1SDimitry Andric CXXConstructorDecl *CD) { 329*0fca6ea1SDimitry Andric SmallVector<TemplateArgument, 16> SubstArgs; 330*0fca6ea1SDimitry Andric 331*0fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 332*0fca6ea1SDimitry Andric 333*0fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p1: 334*0fca6ea1SDimitry Andric // -- For each constructor of the class template designated by the 335*0fca6ea1SDimitry Andric // template-name, a function template with the following properties: 336*0fca6ea1SDimitry Andric 337*0fca6ea1SDimitry Andric // -- The template parameters are the template parameters of the class 338*0fca6ea1SDimitry Andric // template followed by the template parameters (including default 339*0fca6ea1SDimitry Andric // template arguments) of the constructor, if any. 340*0fca6ea1SDimitry Andric TemplateParameterList *TemplateParams = 341*0fca6ea1SDimitry Andric SemaRef.GetTemplateParameterList(Template); 342*0fca6ea1SDimitry Andric if (FTD) { 343*0fca6ea1SDimitry Andric TemplateParameterList *InnerParams = FTD->getTemplateParameters(); 344*0fca6ea1SDimitry Andric SmallVector<NamedDecl *, 16> AllParams; 345*0fca6ea1SDimitry Andric SmallVector<TemplateArgument, 16> Depth1Args; 346*0fca6ea1SDimitry Andric AllParams.reserve(TemplateParams->size() + InnerParams->size()); 347*0fca6ea1SDimitry Andric AllParams.insert(AllParams.begin(), TemplateParams->begin(), 348*0fca6ea1SDimitry Andric TemplateParams->end()); 349*0fca6ea1SDimitry Andric SubstArgs.reserve(InnerParams->size()); 350*0fca6ea1SDimitry Andric Depth1Args.reserve(InnerParams->size()); 351*0fca6ea1SDimitry Andric 352*0fca6ea1SDimitry Andric // Later template parameters could refer to earlier ones, so build up 353*0fca6ea1SDimitry Andric // a list of substituted template arguments as we go. 354*0fca6ea1SDimitry Andric for (NamedDecl *Param : *InnerParams) { 355*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 356*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 357*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(Depth1Args); 358*0fca6ea1SDimitry Andric Args.addOuterRetainedLevel(); 359*0fca6ea1SDimitry Andric if (NestedPattern) 360*0fca6ea1SDimitry Andric Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); 361*0fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter(Param, Args); 362*0fca6ea1SDimitry Andric if (!NewParam) 363*0fca6ea1SDimitry Andric return nullptr; 364*0fca6ea1SDimitry Andric // Constraints require that we substitute depth-1 arguments 365*0fca6ea1SDimitry Andric // to match depths when substituted for evaluation later 366*0fca6ea1SDimitry Andric Depth1Args.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); 367*0fca6ea1SDimitry Andric 368*0fca6ea1SDimitry Andric if (NestedPattern) { 369*0fca6ea1SDimitry Andric TemplateDeclInstantiator Instantiator(SemaRef, DC, 370*0fca6ea1SDimitry Andric OuterInstantiationArgs); 371*0fca6ea1SDimitry Andric Instantiator.setEvaluateConstraints(false); 372*0fca6ea1SDimitry Andric SemaRef.runWithSufficientStackSpace(NewParam->getLocation(), [&] { 373*0fca6ea1SDimitry Andric NewParam = cast<NamedDecl>(Instantiator.Visit(NewParam)); 374*0fca6ea1SDimitry Andric }); 375*0fca6ea1SDimitry Andric } 376*0fca6ea1SDimitry Andric 377*0fca6ea1SDimitry Andric assert(NewParam->getTemplateDepth() == 0 && 378*0fca6ea1SDimitry Andric "Unexpected template parameter depth"); 379*0fca6ea1SDimitry Andric 380*0fca6ea1SDimitry Andric AllParams.push_back(NewParam); 381*0fca6ea1SDimitry Andric SubstArgs.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); 382*0fca6ea1SDimitry Andric } 383*0fca6ea1SDimitry Andric 384*0fca6ea1SDimitry Andric // Substitute new template parameters into requires-clause if present. 385*0fca6ea1SDimitry Andric Expr *RequiresClause = nullptr; 386*0fca6ea1SDimitry Andric if (Expr *InnerRC = InnerParams->getRequiresClause()) { 387*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 388*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 389*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(Depth1Args); 390*0fca6ea1SDimitry Andric Args.addOuterRetainedLevel(); 391*0fca6ea1SDimitry Andric if (NestedPattern) 392*0fca6ea1SDimitry Andric Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); 393*0fca6ea1SDimitry Andric ExprResult E = SemaRef.SubstExpr(InnerRC, Args); 394*0fca6ea1SDimitry Andric if (E.isInvalid()) 395*0fca6ea1SDimitry Andric return nullptr; 396*0fca6ea1SDimitry Andric RequiresClause = E.getAs<Expr>(); 397*0fca6ea1SDimitry Andric } 398*0fca6ea1SDimitry Andric 399*0fca6ea1SDimitry Andric TemplateParams = TemplateParameterList::Create( 400*0fca6ea1SDimitry Andric SemaRef.Context, InnerParams->getTemplateLoc(), 401*0fca6ea1SDimitry Andric InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(), 402*0fca6ea1SDimitry Andric RequiresClause); 403*0fca6ea1SDimitry Andric } 404*0fca6ea1SDimitry Andric 405*0fca6ea1SDimitry Andric // If we built a new template-parameter-list, track that we need to 406*0fca6ea1SDimitry Andric // substitute references to the old parameters into references to the 407*0fca6ea1SDimitry Andric // new ones. 408*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 409*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 410*0fca6ea1SDimitry Andric if (FTD) { 411*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(SubstArgs); 412*0fca6ea1SDimitry Andric Args.addOuterRetainedLevel(); 413*0fca6ea1SDimitry Andric } 414*0fca6ea1SDimitry Andric 415*0fca6ea1SDimitry Andric FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo() 416*0fca6ea1SDimitry Andric ->getTypeLoc() 417*0fca6ea1SDimitry Andric .getAsAdjusted<FunctionProtoTypeLoc>(); 418*0fca6ea1SDimitry Andric assert(FPTL && "no prototype for constructor declaration"); 419*0fca6ea1SDimitry Andric 420*0fca6ea1SDimitry Andric // Transform the type of the function, adjusting the return type and 421*0fca6ea1SDimitry Andric // replacing references to the old parameters with references to the 422*0fca6ea1SDimitry Andric // new ones. 423*0fca6ea1SDimitry Andric TypeLocBuilder TLB; 424*0fca6ea1SDimitry Andric SmallVector<ParmVarDecl *, 8> Params; 425*0fca6ea1SDimitry Andric SmallVector<TypedefNameDecl *, 4> MaterializedTypedefs; 426*0fca6ea1SDimitry Andric QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args, 427*0fca6ea1SDimitry Andric MaterializedTypedefs); 428*0fca6ea1SDimitry Andric if (NewType.isNull()) 429*0fca6ea1SDimitry Andric return nullptr; 430*0fca6ea1SDimitry Andric TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); 431*0fca6ea1SDimitry Andric 432*0fca6ea1SDimitry Andric return buildDeductionGuide( 433*0fca6ea1SDimitry Andric SemaRef, Template, TemplateParams, CD, CD->getExplicitSpecifier(), 434*0fca6ea1SDimitry Andric NewTInfo, CD->getBeginLoc(), CD->getLocation(), CD->getEndLoc(), 435*0fca6ea1SDimitry Andric /*IsImplicit=*/true, MaterializedTypedefs); 436*0fca6ea1SDimitry Andric } 437*0fca6ea1SDimitry Andric 438*0fca6ea1SDimitry Andric /// Build a deduction guide with the specified parameter types. 439*0fca6ea1SDimitry Andric NamedDecl *buildSimpleDeductionGuide(MutableArrayRef<QualType> ParamTypes) { 440*0fca6ea1SDimitry Andric SourceLocation Loc = Template->getLocation(); 441*0fca6ea1SDimitry Andric 442*0fca6ea1SDimitry Andric // Build the requested type. 443*0fca6ea1SDimitry Andric FunctionProtoType::ExtProtoInfo EPI; 444*0fca6ea1SDimitry Andric EPI.HasTrailingReturn = true; 445*0fca6ea1SDimitry Andric QualType Result = SemaRef.BuildFunctionType(DeducedType, ParamTypes, Loc, 446*0fca6ea1SDimitry Andric DeductionGuideName, EPI); 447*0fca6ea1SDimitry Andric TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(Result, Loc); 448*0fca6ea1SDimitry Andric if (NestedPattern) 449*0fca6ea1SDimitry Andric TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc, 450*0fca6ea1SDimitry Andric DeductionGuideName); 451*0fca6ea1SDimitry Andric 452*0fca6ea1SDimitry Andric if (!TSI) 453*0fca6ea1SDimitry Andric return nullptr; 454*0fca6ea1SDimitry Andric 455*0fca6ea1SDimitry Andric FunctionProtoTypeLoc FPTL = 456*0fca6ea1SDimitry Andric TSI->getTypeLoc().castAs<FunctionProtoTypeLoc>(); 457*0fca6ea1SDimitry Andric 458*0fca6ea1SDimitry Andric // Build the parameters, needed during deduction / substitution. 459*0fca6ea1SDimitry Andric SmallVector<ParmVarDecl *, 4> Params; 460*0fca6ea1SDimitry Andric for (auto T : ParamTypes) { 461*0fca6ea1SDimitry Andric auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T, Loc); 462*0fca6ea1SDimitry Andric if (NestedPattern) 463*0fca6ea1SDimitry Andric TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc, 464*0fca6ea1SDimitry Andric DeclarationName()); 465*0fca6ea1SDimitry Andric if (!TSI) 466*0fca6ea1SDimitry Andric return nullptr; 467*0fca6ea1SDimitry Andric 468*0fca6ea1SDimitry Andric ParmVarDecl *NewParam = 469*0fca6ea1SDimitry Andric ParmVarDecl::Create(SemaRef.Context, DC, Loc, Loc, nullptr, 470*0fca6ea1SDimitry Andric TSI->getType(), TSI, SC_None, nullptr); 471*0fca6ea1SDimitry Andric NewParam->setScopeInfo(0, Params.size()); 472*0fca6ea1SDimitry Andric FPTL.setParam(Params.size(), NewParam); 473*0fca6ea1SDimitry Andric Params.push_back(NewParam); 474*0fca6ea1SDimitry Andric } 475*0fca6ea1SDimitry Andric 476*0fca6ea1SDimitry Andric return buildDeductionGuide( 477*0fca6ea1SDimitry Andric SemaRef, Template, SemaRef.GetTemplateParameterList(Template), nullptr, 478*0fca6ea1SDimitry Andric ExplicitSpecifier(), TSI, Loc, Loc, Loc, /*IsImplicit=*/true); 479*0fca6ea1SDimitry Andric } 480*0fca6ea1SDimitry Andric 481*0fca6ea1SDimitry Andric private: 482*0fca6ea1SDimitry Andric /// Transform a constructor template parameter into a deduction guide template 483*0fca6ea1SDimitry Andric /// parameter, rebuilding any internal references to earlier parameters and 484*0fca6ea1SDimitry Andric /// renumbering as we go. 485*0fca6ea1SDimitry Andric NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam, 486*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args) { 487*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 488*0fca6ea1SDimitry Andric return transformTemplateTypeParam( 489*0fca6ea1SDimitry Andric SemaRef, DC, TTP, Args, TTP->getDepth() - 1, 490*0fca6ea1SDimitry Andric Depth1IndexAdjustment + TTP->getIndex()); 491*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 492*0fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, TTP, Args, 493*0fca6ea1SDimitry Andric Depth1IndexAdjustment + TTP->getIndex(), 494*0fca6ea1SDimitry Andric TTP->getDepth() - 1); 495*0fca6ea1SDimitry Andric auto *NTTP = cast<NonTypeTemplateParmDecl>(TemplateParam); 496*0fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, NTTP, Args, 497*0fca6ea1SDimitry Andric Depth1IndexAdjustment + NTTP->getIndex(), 498*0fca6ea1SDimitry Andric NTTP->getDepth() - 1); 499*0fca6ea1SDimitry Andric } 500*0fca6ea1SDimitry Andric 501*0fca6ea1SDimitry Andric QualType transformFunctionProtoType( 502*0fca6ea1SDimitry Andric TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, 503*0fca6ea1SDimitry Andric SmallVectorImpl<ParmVarDecl *> &Params, 504*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, 505*0fca6ea1SDimitry Andric SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) { 506*0fca6ea1SDimitry Andric SmallVector<QualType, 4> ParamTypes; 507*0fca6ea1SDimitry Andric const FunctionProtoType *T = TL.getTypePtr(); 508*0fca6ea1SDimitry Andric 509*0fca6ea1SDimitry Andric // -- The types of the function parameters are those of the constructor. 510*0fca6ea1SDimitry Andric for (auto *OldParam : TL.getParams()) { 511*0fca6ea1SDimitry Andric ParmVarDecl *NewParam = OldParam; 512*0fca6ea1SDimitry Andric // Given 513*0fca6ea1SDimitry Andric // template <class T> struct C { 514*0fca6ea1SDimitry Andric // template <class U> struct D { 515*0fca6ea1SDimitry Andric // template <class V> D(U, V); 516*0fca6ea1SDimitry Andric // }; 517*0fca6ea1SDimitry Andric // }; 518*0fca6ea1SDimitry Andric // First, transform all the references to template parameters that are 519*0fca6ea1SDimitry Andric // defined outside of the surrounding class template. That is T in the 520*0fca6ea1SDimitry Andric // above example. 521*0fca6ea1SDimitry Andric if (NestedPattern) { 522*0fca6ea1SDimitry Andric NewParam = transformFunctionTypeParam( 523*0fca6ea1SDimitry Andric NewParam, OuterInstantiationArgs, MaterializedTypedefs, 524*0fca6ea1SDimitry Andric /*TransformingOuterPatterns=*/true); 525*0fca6ea1SDimitry Andric if (!NewParam) 526*0fca6ea1SDimitry Andric return QualType(); 527*0fca6ea1SDimitry Andric } 528*0fca6ea1SDimitry Andric // Then, transform all the references to template parameters that are 529*0fca6ea1SDimitry Andric // defined at the class template and the constructor. In this example, 530*0fca6ea1SDimitry Andric // they're U and V, respectively. 531*0fca6ea1SDimitry Andric NewParam = 532*0fca6ea1SDimitry Andric transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs, 533*0fca6ea1SDimitry Andric /*TransformingOuterPatterns=*/false); 534*0fca6ea1SDimitry Andric if (!NewParam) 535*0fca6ea1SDimitry Andric return QualType(); 536*0fca6ea1SDimitry Andric ParamTypes.push_back(NewParam->getType()); 537*0fca6ea1SDimitry Andric Params.push_back(NewParam); 538*0fca6ea1SDimitry Andric } 539*0fca6ea1SDimitry Andric 540*0fca6ea1SDimitry Andric // -- The return type is the class template specialization designated by 541*0fca6ea1SDimitry Andric // the template-name and template arguments corresponding to the 542*0fca6ea1SDimitry Andric // template parameters obtained from the class template. 543*0fca6ea1SDimitry Andric // 544*0fca6ea1SDimitry Andric // We use the injected-class-name type of the primary template instead. 545*0fca6ea1SDimitry Andric // This has the convenient property that it is different from any type that 546*0fca6ea1SDimitry Andric // the user can write in a deduction-guide (because they cannot enter the 547*0fca6ea1SDimitry Andric // context of the template), so implicit deduction guides can never collide 548*0fca6ea1SDimitry Andric // with explicit ones. 549*0fca6ea1SDimitry Andric QualType ReturnType = DeducedType; 550*0fca6ea1SDimitry Andric TLB.pushTypeSpec(ReturnType).setNameLoc(Primary->getLocation()); 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric // Resolving a wording defect, we also inherit the variadicness of the 553*0fca6ea1SDimitry Andric // constructor. 554*0fca6ea1SDimitry Andric FunctionProtoType::ExtProtoInfo EPI; 555*0fca6ea1SDimitry Andric EPI.Variadic = T->isVariadic(); 556*0fca6ea1SDimitry Andric EPI.HasTrailingReturn = true; 557*0fca6ea1SDimitry Andric 558*0fca6ea1SDimitry Andric QualType Result = SemaRef.BuildFunctionType( 559*0fca6ea1SDimitry Andric ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI); 560*0fca6ea1SDimitry Andric if (Result.isNull()) 561*0fca6ea1SDimitry Andric return QualType(); 562*0fca6ea1SDimitry Andric 563*0fca6ea1SDimitry Andric FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); 564*0fca6ea1SDimitry Andric NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); 565*0fca6ea1SDimitry Andric NewTL.setLParenLoc(TL.getLParenLoc()); 566*0fca6ea1SDimitry Andric NewTL.setRParenLoc(TL.getRParenLoc()); 567*0fca6ea1SDimitry Andric NewTL.setExceptionSpecRange(SourceRange()); 568*0fca6ea1SDimitry Andric NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); 569*0fca6ea1SDimitry Andric for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I) 570*0fca6ea1SDimitry Andric NewTL.setParam(I, Params[I]); 571*0fca6ea1SDimitry Andric 572*0fca6ea1SDimitry Andric return Result; 573*0fca6ea1SDimitry Andric } 574*0fca6ea1SDimitry Andric 575*0fca6ea1SDimitry Andric ParmVarDecl *transformFunctionTypeParam( 576*0fca6ea1SDimitry Andric ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args, 577*0fca6ea1SDimitry Andric llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs, 578*0fca6ea1SDimitry Andric bool TransformingOuterPatterns) { 579*0fca6ea1SDimitry Andric TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); 580*0fca6ea1SDimitry Andric TypeSourceInfo *NewDI; 581*0fca6ea1SDimitry Andric if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { 582*0fca6ea1SDimitry Andric // Expand out the one and only element in each inner pack. 583*0fca6ea1SDimitry Andric Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0); 584*0fca6ea1SDimitry Andric NewDI = 585*0fca6ea1SDimitry Andric SemaRef.SubstType(PackTL.getPatternLoc(), Args, 586*0fca6ea1SDimitry Andric OldParam->getLocation(), OldParam->getDeclName()); 587*0fca6ea1SDimitry Andric if (!NewDI) 588*0fca6ea1SDimitry Andric return nullptr; 589*0fca6ea1SDimitry Andric NewDI = 590*0fca6ea1SDimitry Andric SemaRef.CheckPackExpansion(NewDI, PackTL.getEllipsisLoc(), 591*0fca6ea1SDimitry Andric PackTL.getTypePtr()->getNumExpansions()); 592*0fca6ea1SDimitry Andric } else 593*0fca6ea1SDimitry Andric NewDI = SemaRef.SubstType(OldDI, Args, OldParam->getLocation(), 594*0fca6ea1SDimitry Andric OldParam->getDeclName()); 595*0fca6ea1SDimitry Andric if (!NewDI) 596*0fca6ea1SDimitry Andric return nullptr; 597*0fca6ea1SDimitry Andric 598*0fca6ea1SDimitry Andric // Extract the type. This (for instance) replaces references to typedef 599*0fca6ea1SDimitry Andric // members of the current instantiations with the definitions of those 600*0fca6ea1SDimitry Andric // typedefs, avoiding triggering instantiation of the deduced type during 601*0fca6ea1SDimitry Andric // deduction. 602*0fca6ea1SDimitry Andric NewDI = ExtractTypeForDeductionGuide( 603*0fca6ea1SDimitry Andric SemaRef, MaterializedTypedefs, NestedPattern, 604*0fca6ea1SDimitry Andric TransformingOuterPatterns ? &Args : nullptr) 605*0fca6ea1SDimitry Andric .transform(NewDI); 606*0fca6ea1SDimitry Andric 607*0fca6ea1SDimitry Andric // Resolving a wording defect, we also inherit default arguments from the 608*0fca6ea1SDimitry Andric // constructor. 609*0fca6ea1SDimitry Andric ExprResult NewDefArg; 610*0fca6ea1SDimitry Andric if (OldParam->hasDefaultArg()) { 611*0fca6ea1SDimitry Andric // We don't care what the value is (we won't use it); just create a 612*0fca6ea1SDimitry Andric // placeholder to indicate there is a default argument. 613*0fca6ea1SDimitry Andric QualType ParamTy = NewDI->getType(); 614*0fca6ea1SDimitry Andric NewDefArg = new (SemaRef.Context) 615*0fca6ea1SDimitry Andric OpaqueValueExpr(OldParam->getDefaultArgRange().getBegin(), 616*0fca6ea1SDimitry Andric ParamTy.getNonLValueExprType(SemaRef.Context), 617*0fca6ea1SDimitry Andric ParamTy->isLValueReferenceType() ? VK_LValue 618*0fca6ea1SDimitry Andric : ParamTy->isRValueReferenceType() ? VK_XValue 619*0fca6ea1SDimitry Andric : VK_PRValue); 620*0fca6ea1SDimitry Andric } 621*0fca6ea1SDimitry Andric // Handle arrays and functions decay. 622*0fca6ea1SDimitry Andric auto NewType = NewDI->getType(); 623*0fca6ea1SDimitry Andric if (NewType->isArrayType() || NewType->isFunctionType()) 624*0fca6ea1SDimitry Andric NewType = SemaRef.Context.getDecayedType(NewType); 625*0fca6ea1SDimitry Andric 626*0fca6ea1SDimitry Andric ParmVarDecl *NewParam = ParmVarDecl::Create( 627*0fca6ea1SDimitry Andric SemaRef.Context, DC, OldParam->getInnerLocStart(), 628*0fca6ea1SDimitry Andric OldParam->getLocation(), OldParam->getIdentifier(), NewType, NewDI, 629*0fca6ea1SDimitry Andric OldParam->getStorageClass(), NewDefArg.get()); 630*0fca6ea1SDimitry Andric NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(), 631*0fca6ea1SDimitry Andric OldParam->getFunctionScopeIndex()); 632*0fca6ea1SDimitry Andric SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam); 633*0fca6ea1SDimitry Andric return NewParam; 634*0fca6ea1SDimitry Andric } 635*0fca6ea1SDimitry Andric }; 636*0fca6ea1SDimitry Andric 637*0fca6ea1SDimitry Andric unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { 638*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 639*0fca6ea1SDimitry Andric return TTP->getDepth(); 640*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 641*0fca6ea1SDimitry Andric return TTP->getDepth(); 642*0fca6ea1SDimitry Andric if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) 643*0fca6ea1SDimitry Andric return NTTP->getDepth(); 644*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled template parameter types"); 645*0fca6ea1SDimitry Andric } 646*0fca6ea1SDimitry Andric 647*0fca6ea1SDimitry Andric unsigned getTemplateParameterIndex(NamedDecl *TemplateParam) { 648*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 649*0fca6ea1SDimitry Andric return TTP->getIndex(); 650*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 651*0fca6ea1SDimitry Andric return TTP->getIndex(); 652*0fca6ea1SDimitry Andric if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) 653*0fca6ea1SDimitry Andric return NTTP->getIndex(); 654*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled template parameter types"); 655*0fca6ea1SDimitry Andric } 656*0fca6ea1SDimitry Andric 657*0fca6ea1SDimitry Andric // Find all template parameters that appear in the given DeducedArgs. 658*0fca6ea1SDimitry Andric // Return the indices of the template parameters in the TemplateParams. 659*0fca6ea1SDimitry Andric SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( 660*0fca6ea1SDimitry Andric const TemplateParameterList *TemplateParamsList, 661*0fca6ea1SDimitry Andric ArrayRef<TemplateArgument> DeducedArgs) { 662*0fca6ea1SDimitry Andric struct TemplateParamsReferencedFinder 663*0fca6ea1SDimitry Andric : public RecursiveASTVisitor<TemplateParamsReferencedFinder> { 664*0fca6ea1SDimitry Andric const TemplateParameterList *TemplateParamList; 665*0fca6ea1SDimitry Andric llvm::BitVector ReferencedTemplateParams; 666*0fca6ea1SDimitry Andric 667*0fca6ea1SDimitry Andric TemplateParamsReferencedFinder( 668*0fca6ea1SDimitry Andric const TemplateParameterList *TemplateParamList) 669*0fca6ea1SDimitry Andric : TemplateParamList(TemplateParamList), 670*0fca6ea1SDimitry Andric ReferencedTemplateParams(TemplateParamList->size()) {} 671*0fca6ea1SDimitry Andric 672*0fca6ea1SDimitry Andric bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { 673*0fca6ea1SDimitry Andric // We use the index and depth to retrieve the corresponding template 674*0fca6ea1SDimitry Andric // parameter from the parameter list, which is more robost. 675*0fca6ea1SDimitry Andric Mark(TTP->getDepth(), TTP->getIndex()); 676*0fca6ea1SDimitry Andric return true; 677*0fca6ea1SDimitry Andric } 678*0fca6ea1SDimitry Andric 679*0fca6ea1SDimitry Andric bool VisitDeclRefExpr(DeclRefExpr *DRE) { 680*0fca6ea1SDimitry Andric MarkAppeared(DRE->getFoundDecl()); 681*0fca6ea1SDimitry Andric return true; 682*0fca6ea1SDimitry Andric } 683*0fca6ea1SDimitry Andric 684*0fca6ea1SDimitry Andric bool TraverseTemplateName(TemplateName Template) { 685*0fca6ea1SDimitry Andric if (auto *TD = Template.getAsTemplateDecl()) 686*0fca6ea1SDimitry Andric MarkAppeared(TD); 687*0fca6ea1SDimitry Andric return RecursiveASTVisitor::TraverseTemplateName(Template); 688*0fca6ea1SDimitry Andric } 689*0fca6ea1SDimitry Andric 690*0fca6ea1SDimitry Andric void MarkAppeared(NamedDecl *ND) { 691*0fca6ea1SDimitry Andric if (llvm::isa<NonTypeTemplateParmDecl, TemplateTypeParmDecl, 692*0fca6ea1SDimitry Andric TemplateTemplateParmDecl>(ND)) 693*0fca6ea1SDimitry Andric Mark(getTemplateParameterDepth(ND), getTemplateParameterIndex(ND)); 694*0fca6ea1SDimitry Andric } 695*0fca6ea1SDimitry Andric void Mark(unsigned Depth, unsigned Index) { 696*0fca6ea1SDimitry Andric if (Index < TemplateParamList->size() && 697*0fca6ea1SDimitry Andric TemplateParamList->getParam(Index)->getTemplateDepth() == Depth) 698*0fca6ea1SDimitry Andric ReferencedTemplateParams.set(Index); 699*0fca6ea1SDimitry Andric } 700*0fca6ea1SDimitry Andric }; 701*0fca6ea1SDimitry Andric TemplateParamsReferencedFinder Finder(TemplateParamsList); 702*0fca6ea1SDimitry Andric Finder.TraverseTemplateArguments(DeducedArgs); 703*0fca6ea1SDimitry Andric 704*0fca6ea1SDimitry Andric SmallVector<unsigned> Results; 705*0fca6ea1SDimitry Andric for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) { 706*0fca6ea1SDimitry Andric if (Finder.ReferencedTemplateParams[Index]) 707*0fca6ea1SDimitry Andric Results.push_back(Index); 708*0fca6ea1SDimitry Andric } 709*0fca6ea1SDimitry Andric return Results; 710*0fca6ea1SDimitry Andric } 711*0fca6ea1SDimitry Andric 712*0fca6ea1SDimitry Andric bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { 713*0fca6ea1SDimitry Andric // Check whether we've already declared deduction guides for this template. 714*0fca6ea1SDimitry Andric // FIXME: Consider storing a flag on the template to indicate this. 715*0fca6ea1SDimitry Andric assert(Name.getNameKind() == 716*0fca6ea1SDimitry Andric DeclarationName::NameKind::CXXDeductionGuideName && 717*0fca6ea1SDimitry Andric "name must be a deduction guide name"); 718*0fca6ea1SDimitry Andric auto Existing = DC->lookup(Name); 719*0fca6ea1SDimitry Andric for (auto *D : Existing) 720*0fca6ea1SDimitry Andric if (D->isImplicit()) 721*0fca6ea1SDimitry Andric return true; 722*0fca6ea1SDimitry Andric return false; 723*0fca6ea1SDimitry Andric } 724*0fca6ea1SDimitry Andric 725*0fca6ea1SDimitry Andric NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, 726*0fca6ea1SDimitry Andric NamedDecl *TemplateParam, 727*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList &Args, 728*0fca6ea1SDimitry Andric unsigned NewIndex, unsigned NewDepth) { 729*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) 730*0fca6ea1SDimitry Andric return transformTemplateTypeParam(SemaRef, DC, TTP, Args, NewDepth, 731*0fca6ea1SDimitry Andric NewIndex); 732*0fca6ea1SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) 733*0fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, NewDepth); 734*0fca6ea1SDimitry Andric if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) 735*0fca6ea1SDimitry Andric return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, NewDepth); 736*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled template parameter types"); 737*0fca6ea1SDimitry Andric } 738*0fca6ea1SDimitry Andric 739*0fca6ea1SDimitry Andric // Build the associated constraints for the alias deduction guides. 740*0fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p3.3: 741*0fca6ea1SDimitry Andric // The associated constraints ([temp.constr.decl]) are the conjunction of the 742*0fca6ea1SDimitry Andric // associated constraints of g and a constraint that is satisfied if and only 743*0fca6ea1SDimitry Andric // if the arguments of A are deducible (see below) from the return type. 744*0fca6ea1SDimitry Andric // 745*0fca6ea1SDimitry Andric // The return result is expected to be the require-clause for the synthesized 746*0fca6ea1SDimitry Andric // alias deduction guide. 747*0fca6ea1SDimitry Andric Expr * 748*0fca6ea1SDimitry Andric buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, 749*0fca6ea1SDimitry Andric TypeAliasTemplateDecl *AliasTemplate, 750*0fca6ea1SDimitry Andric ArrayRef<DeducedTemplateArgument> DeduceResults, 751*0fca6ea1SDimitry Andric unsigned FirstUndeducedParamIdx, Expr *IsDeducible) { 752*0fca6ea1SDimitry Andric Expr *RC = F->getTemplateParameters()->getRequiresClause(); 753*0fca6ea1SDimitry Andric if (!RC) 754*0fca6ea1SDimitry Andric return IsDeducible; 755*0fca6ea1SDimitry Andric 756*0fca6ea1SDimitry Andric ASTContext &Context = SemaRef.Context; 757*0fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 758*0fca6ea1SDimitry Andric 759*0fca6ea1SDimitry Andric // In the clang AST, constraint nodes are deliberately not instantiated unless 760*0fca6ea1SDimitry Andric // they are actively being evaluated. Consequently, occurrences of template 761*0fca6ea1SDimitry Andric // parameters in the require-clause expression have a subtle "depth" 762*0fca6ea1SDimitry Andric // difference compared to normal occurrences in places, such as function 763*0fca6ea1SDimitry Andric // parameters. When transforming the require-clause, we must take this 764*0fca6ea1SDimitry Andric // distinction into account: 765*0fca6ea1SDimitry Andric // 766*0fca6ea1SDimitry Andric // 1) In the transformed require-clause, occurrences of template parameters 767*0fca6ea1SDimitry Andric // must use the "uninstantiated" depth; 768*0fca6ea1SDimitry Andric // 2) When substituting on the require-clause expr of the underlying 769*0fca6ea1SDimitry Andric // deduction guide, we must use the entire set of template argument lists; 770*0fca6ea1SDimitry Andric // 771*0fca6ea1SDimitry Andric // It's important to note that we're performing this transformation on an 772*0fca6ea1SDimitry Andric // *instantiated* AliasTemplate. 773*0fca6ea1SDimitry Andric 774*0fca6ea1SDimitry Andric // For 1), if the alias template is nested within a class template, we 775*0fca6ea1SDimitry Andric // calcualte the 'uninstantiated' depth by adding the substitution level back. 776*0fca6ea1SDimitry Andric unsigned AdjustDepth = 0; 777*0fca6ea1SDimitry Andric if (auto *PrimaryTemplate = 778*0fca6ea1SDimitry Andric AliasTemplate->getInstantiatedFromMemberTemplate()) 779*0fca6ea1SDimitry Andric AdjustDepth = PrimaryTemplate->getTemplateDepth(); 780*0fca6ea1SDimitry Andric 781*0fca6ea1SDimitry Andric // We rebuild all template parameters with the uninstantiated depth, and 782*0fca6ea1SDimitry Andric // build template arguments refer to them. 783*0fca6ea1SDimitry Andric SmallVector<TemplateArgument> AdjustedAliasTemplateArgs; 784*0fca6ea1SDimitry Andric 785*0fca6ea1SDimitry Andric for (auto *TP : *AliasTemplate->getTemplateParameters()) { 786*0fca6ea1SDimitry Andric // Rebuild any internal references to earlier parameters and reindex 787*0fca6ea1SDimitry Andric // as we go. 788*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 789*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 790*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs); 791*0fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 792*0fca6ea1SDimitry Andric SemaRef, AliasTemplate->getDeclContext(), TP, Args, 793*0fca6ea1SDimitry Andric /*NewIndex=*/AdjustedAliasTemplateArgs.size(), 794*0fca6ea1SDimitry Andric getTemplateParameterDepth(TP) + AdjustDepth); 795*0fca6ea1SDimitry Andric 796*0fca6ea1SDimitry Andric TemplateArgument NewTemplateArgument = 797*0fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 798*0fca6ea1SDimitry Andric AdjustedAliasTemplateArgs.push_back(NewTemplateArgument); 799*0fca6ea1SDimitry Andric } 800*0fca6ea1SDimitry Andric // Template arguments used to transform the template arguments in 801*0fca6ea1SDimitry Andric // DeducedResults. 802*0fca6ea1SDimitry Andric SmallVector<TemplateArgument> TemplateArgsForBuildingRC( 803*0fca6ea1SDimitry Andric F->getTemplateParameters()->size()); 804*0fca6ea1SDimitry Andric // Transform the transformed template args 805*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 806*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 807*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(AdjustedAliasTemplateArgs); 808*0fca6ea1SDimitry Andric 809*0fca6ea1SDimitry Andric for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { 810*0fca6ea1SDimitry Andric const auto &D = DeduceResults[Index]; 811*0fca6ea1SDimitry Andric if (D.isNull()) { // non-deduced template parameters of f 812*0fca6ea1SDimitry Andric NamedDecl *TP = F->getTemplateParameters()->getParam(Index); 813*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 814*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 815*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TemplateArgsForBuildingRC); 816*0fca6ea1SDimitry Andric // Rebuild the template parameter with updated depth and index. 817*0fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 818*0fca6ea1SDimitry Andric SemaRef, F->getDeclContext(), TP, Args, 819*0fca6ea1SDimitry Andric /*NewIndex=*/FirstUndeducedParamIdx, 820*0fca6ea1SDimitry Andric getTemplateParameterDepth(TP) + AdjustDepth); 821*0fca6ea1SDimitry Andric FirstUndeducedParamIdx += 1; 822*0fca6ea1SDimitry Andric assert(TemplateArgsForBuildingRC[Index].isNull()); 823*0fca6ea1SDimitry Andric TemplateArgsForBuildingRC[Index] = 824*0fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 825*0fca6ea1SDimitry Andric continue; 826*0fca6ea1SDimitry Andric } 827*0fca6ea1SDimitry Andric TemplateArgumentLoc Input = 828*0fca6ea1SDimitry Andric SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); 829*0fca6ea1SDimitry Andric TemplateArgumentLoc Output; 830*0fca6ea1SDimitry Andric if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) { 831*0fca6ea1SDimitry Andric assert(TemplateArgsForBuildingRC[Index].isNull() && 832*0fca6ea1SDimitry Andric "InstantiatedArgs must be null before setting"); 833*0fca6ea1SDimitry Andric TemplateArgsForBuildingRC[Index] = Output.getArgument(); 834*0fca6ea1SDimitry Andric } 835*0fca6ea1SDimitry Andric } 836*0fca6ea1SDimitry Andric 837*0fca6ea1SDimitry Andric // A list of template arguments for transforming the require-clause of F. 838*0fca6ea1SDimitry Andric // It must contain the entire set of template argument lists. 839*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList ArgsForBuildingRC; 840*0fca6ea1SDimitry Andric ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); 841*0fca6ea1SDimitry Andric ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC); 842*0fca6ea1SDimitry Andric // For 2), if the underlying deduction guide F is nested in a class template, 843*0fca6ea1SDimitry Andric // we need the entire template argument list, as the constraint AST in the 844*0fca6ea1SDimitry Andric // require-clause of F remains completely uninstantiated. 845*0fca6ea1SDimitry Andric // 846*0fca6ea1SDimitry Andric // For example: 847*0fca6ea1SDimitry Andric // template <typename T> // depth 0 848*0fca6ea1SDimitry Andric // struct Outer { 849*0fca6ea1SDimitry Andric // template <typename U> 850*0fca6ea1SDimitry Andric // struct Foo { Foo(U); }; 851*0fca6ea1SDimitry Andric // 852*0fca6ea1SDimitry Andric // template <typename U> // depth 1 853*0fca6ea1SDimitry Andric // requires C<U> 854*0fca6ea1SDimitry Andric // Foo(U) -> Foo<int>; 855*0fca6ea1SDimitry Andric // }; 856*0fca6ea1SDimitry Andric // template <typename U> 857*0fca6ea1SDimitry Andric // using AFoo = Outer<int>::Foo<U>; 858*0fca6ea1SDimitry Andric // 859*0fca6ea1SDimitry Andric // In this scenario, the deduction guide for `Foo` inside `Outer<int>`: 860*0fca6ea1SDimitry Andric // - The occurrence of U in the require-expression is [depth:1, index:0] 861*0fca6ea1SDimitry Andric // - The occurrence of U in the function parameter is [depth:0, index:0] 862*0fca6ea1SDimitry Andric // - The template parameter of U is [depth:0, index:0] 863*0fca6ea1SDimitry Andric // 864*0fca6ea1SDimitry Andric // We add the outer template arguments which is [int] to the multi-level arg 865*0fca6ea1SDimitry Andric // list to ensure that the occurrence U in `C<U>` will be replaced with int 866*0fca6ea1SDimitry Andric // during the substitution. 867*0fca6ea1SDimitry Andric // 868*0fca6ea1SDimitry Andric // NOTE: The underlying deduction guide F is instantiated -- either from an 869*0fca6ea1SDimitry Andric // explicitly-written deduction guide member, or from a constructor. 870*0fca6ea1SDimitry Andric // getInstantiatedFromMemberTemplate() can only handle the former case, so we 871*0fca6ea1SDimitry Andric // check the DeclContext kind. 872*0fca6ea1SDimitry Andric if (F->getLexicalDeclContext()->getDeclKind() == 873*0fca6ea1SDimitry Andric clang::Decl::ClassTemplateSpecialization) { 874*0fca6ea1SDimitry Andric auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs( 875*0fca6ea1SDimitry Andric F, F->getLexicalDeclContext(), 876*0fca6ea1SDimitry Andric /*Final=*/false, /*Innermost=*/std::nullopt, 877*0fca6ea1SDimitry Andric /*RelativeToPrimary=*/true, 878*0fca6ea1SDimitry Andric /*Pattern=*/nullptr, 879*0fca6ea1SDimitry Andric /*ForConstraintInstantiation=*/true); 880*0fca6ea1SDimitry Andric for (auto It : OuterLevelArgs) 881*0fca6ea1SDimitry Andric ArgsForBuildingRC.addOuterTemplateArguments(It.Args); 882*0fca6ea1SDimitry Andric } 883*0fca6ea1SDimitry Andric 884*0fca6ea1SDimitry Andric ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); 885*0fca6ea1SDimitry Andric if (E.isInvalid()) 886*0fca6ea1SDimitry Andric return nullptr; 887*0fca6ea1SDimitry Andric 888*0fca6ea1SDimitry Andric auto Conjunction = 889*0fca6ea1SDimitry Andric SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, 890*0fca6ea1SDimitry Andric BinaryOperatorKind::BO_LAnd, E.get(), IsDeducible); 891*0fca6ea1SDimitry Andric if (Conjunction.isInvalid()) 892*0fca6ea1SDimitry Andric return nullptr; 893*0fca6ea1SDimitry Andric return Conjunction.getAs<Expr>(); 894*0fca6ea1SDimitry Andric } 895*0fca6ea1SDimitry Andric // Build the is_deducible constraint for the alias deduction guides. 896*0fca6ea1SDimitry Andric // [over.match.class.deduct]p3.3: 897*0fca6ea1SDimitry Andric // ... and a constraint that is satisfied if and only if the arguments 898*0fca6ea1SDimitry Andric // of A are deducible (see below) from the return type. 899*0fca6ea1SDimitry Andric Expr *buildIsDeducibleConstraint(Sema &SemaRef, 900*0fca6ea1SDimitry Andric TypeAliasTemplateDecl *AliasTemplate, 901*0fca6ea1SDimitry Andric QualType ReturnType, 902*0fca6ea1SDimitry Andric SmallVector<NamedDecl *> TemplateParams) { 903*0fca6ea1SDimitry Andric ASTContext &Context = SemaRef.Context; 904*0fca6ea1SDimitry Andric // Constraint AST nodes must use uninstantiated depth. 905*0fca6ea1SDimitry Andric if (auto *PrimaryTemplate = 906*0fca6ea1SDimitry Andric AliasTemplate->getInstantiatedFromMemberTemplate(); 907*0fca6ea1SDimitry Andric PrimaryTemplate && TemplateParams.size() > 0) { 908*0fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 909*0fca6ea1SDimitry Andric 910*0fca6ea1SDimitry Andric // Adjust the depth for TemplateParams. 911*0fca6ea1SDimitry Andric unsigned AdjustDepth = PrimaryTemplate->getTemplateDepth(); 912*0fca6ea1SDimitry Andric SmallVector<TemplateArgument> TransformedTemplateArgs; 913*0fca6ea1SDimitry Andric for (auto *TP : TemplateParams) { 914*0fca6ea1SDimitry Andric // Rebuild any internal references to earlier parameters and reindex 915*0fca6ea1SDimitry Andric // as we go. 916*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 917*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 918*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedTemplateArgs); 919*0fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 920*0fca6ea1SDimitry Andric SemaRef, AliasTemplate->getDeclContext(), TP, Args, 921*0fca6ea1SDimitry Andric /*NewIndex=*/TransformedTemplateArgs.size(), 922*0fca6ea1SDimitry Andric getTemplateParameterDepth(TP) + AdjustDepth); 923*0fca6ea1SDimitry Andric 924*0fca6ea1SDimitry Andric TemplateArgument NewTemplateArgument = 925*0fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 926*0fca6ea1SDimitry Andric TransformedTemplateArgs.push_back(NewTemplateArgument); 927*0fca6ea1SDimitry Andric } 928*0fca6ea1SDimitry Andric // Transformed the ReturnType to restore the uninstantiated depth. 929*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 930*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 931*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedTemplateArgs); 932*0fca6ea1SDimitry Andric ReturnType = SemaRef.SubstType( 933*0fca6ea1SDimitry Andric ReturnType, Args, AliasTemplate->getLocation(), 934*0fca6ea1SDimitry Andric Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate)); 935*0fca6ea1SDimitry Andric }; 936*0fca6ea1SDimitry Andric 937*0fca6ea1SDimitry Andric SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = { 938*0fca6ea1SDimitry Andric Context.getTrivialTypeSourceInfo( 939*0fca6ea1SDimitry Andric Context.getDeducedTemplateSpecializationType( 940*0fca6ea1SDimitry Andric TemplateName(AliasTemplate), /*DeducedType=*/QualType(), 941*0fca6ea1SDimitry Andric /*IsDependent=*/true)), // template specialization type whose 942*0fca6ea1SDimitry Andric // arguments will be deduced. 943*0fca6ea1SDimitry Andric Context.getTrivialTypeSourceInfo( 944*0fca6ea1SDimitry Andric ReturnType), // type from which template arguments are deduced. 945*0fca6ea1SDimitry Andric }; 946*0fca6ea1SDimitry Andric return TypeTraitExpr::Create( 947*0fca6ea1SDimitry Andric Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(), 948*0fca6ea1SDimitry Andric TypeTrait::BTT_IsDeducible, IsDeducibleTypeTraitArgs, 949*0fca6ea1SDimitry Andric AliasTemplate->getLocation(), /*Value*/ false); 950*0fca6ea1SDimitry Andric } 951*0fca6ea1SDimitry Andric 952*0fca6ea1SDimitry Andric std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>> 953*0fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { 954*0fca6ea1SDimitry Andric // Unwrap the sugared ElaboratedType. 955*0fca6ea1SDimitry Andric auto RhsType = AliasTemplate->getTemplatedDecl() 956*0fca6ea1SDimitry Andric ->getUnderlyingType() 957*0fca6ea1SDimitry Andric .getSingleStepDesugaredType(SemaRef.Context); 958*0fca6ea1SDimitry Andric TemplateDecl *Template = nullptr; 959*0fca6ea1SDimitry Andric llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs; 960*0fca6ea1SDimitry Andric if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) { 961*0fca6ea1SDimitry Andric // Cases where the RHS of the alias is dependent. e.g. 962*0fca6ea1SDimitry Andric // template<typename T> 963*0fca6ea1SDimitry Andric // using AliasFoo1 = Foo<T>; // a class/type alias template specialization 964*0fca6ea1SDimitry Andric Template = TST->getTemplateName().getAsTemplateDecl(); 965*0fca6ea1SDimitry Andric AliasRhsTemplateArgs = TST->template_arguments(); 966*0fca6ea1SDimitry Andric } else if (const auto *RT = RhsType->getAs<RecordType>()) { 967*0fca6ea1SDimitry Andric // Cases where template arguments in the RHS of the alias are not 968*0fca6ea1SDimitry Andric // dependent. e.g. 969*0fca6ea1SDimitry Andric // using AliasFoo = Foo<bool>; 970*0fca6ea1SDimitry Andric if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>( 971*0fca6ea1SDimitry Andric RT->getAsCXXRecordDecl())) { 972*0fca6ea1SDimitry Andric Template = CTSD->getSpecializedTemplate(); 973*0fca6ea1SDimitry Andric AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray(); 974*0fca6ea1SDimitry Andric } 975*0fca6ea1SDimitry Andric } else { 976*0fca6ea1SDimitry Andric assert(false && "unhandled RHS type of the alias"); 977*0fca6ea1SDimitry Andric } 978*0fca6ea1SDimitry Andric return {Template, AliasRhsTemplateArgs}; 979*0fca6ea1SDimitry Andric } 980*0fca6ea1SDimitry Andric 981*0fca6ea1SDimitry Andric // Build deduction guides for a type alias template from the given underlying 982*0fca6ea1SDimitry Andric // deduction guide F. 983*0fca6ea1SDimitry Andric FunctionTemplateDecl * 984*0fca6ea1SDimitry Andric BuildDeductionGuideForTypeAlias(Sema &SemaRef, 985*0fca6ea1SDimitry Andric TypeAliasTemplateDecl *AliasTemplate, 986*0fca6ea1SDimitry Andric FunctionTemplateDecl *F, SourceLocation Loc) { 987*0fca6ea1SDimitry Andric LocalInstantiationScope Scope(SemaRef); 988*0fca6ea1SDimitry Andric Sema::InstantiatingTemplate BuildingDeductionGuides( 989*0fca6ea1SDimitry Andric SemaRef, AliasTemplate->getLocation(), F, 990*0fca6ea1SDimitry Andric Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); 991*0fca6ea1SDimitry Andric if (BuildingDeductionGuides.isInvalid()) 992*0fca6ea1SDimitry Andric return nullptr; 993*0fca6ea1SDimitry Andric 994*0fca6ea1SDimitry Andric auto &Context = SemaRef.Context; 995*0fca6ea1SDimitry Andric auto [Template, AliasRhsTemplateArgs] = 996*0fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); 997*0fca6ea1SDimitry Andric 998*0fca6ea1SDimitry Andric auto RType = F->getTemplatedDecl()->getReturnType(); 999*0fca6ea1SDimitry Andric // The (trailing) return type of the deduction guide. 1000*0fca6ea1SDimitry Andric const TemplateSpecializationType *FReturnType = 1001*0fca6ea1SDimitry Andric RType->getAs<TemplateSpecializationType>(); 1002*0fca6ea1SDimitry Andric if (const auto *InjectedCNT = RType->getAs<InjectedClassNameType>()) 1003*0fca6ea1SDimitry Andric // implicitly-generated deduction guide. 1004*0fca6ea1SDimitry Andric FReturnType = InjectedCNT->getInjectedTST(); 1005*0fca6ea1SDimitry Andric else if (const auto *ET = RType->getAs<ElaboratedType>()) 1006*0fca6ea1SDimitry Andric // explicit deduction guide. 1007*0fca6ea1SDimitry Andric FReturnType = ET->getNamedType()->getAs<TemplateSpecializationType>(); 1008*0fca6ea1SDimitry Andric assert(FReturnType && "expected to see a return type"); 1009*0fca6ea1SDimitry Andric // Deduce template arguments of the deduction guide f from the RHS of 1010*0fca6ea1SDimitry Andric // the alias. 1011*0fca6ea1SDimitry Andric // 1012*0fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p3: ...For each function or function 1013*0fca6ea1SDimitry Andric // template f in the guides of the template named by the 1014*0fca6ea1SDimitry Andric // simple-template-id of the defining-type-id, the template arguments 1015*0fca6ea1SDimitry Andric // of the return type of f are deduced from the defining-type-id of A 1016*0fca6ea1SDimitry Andric // according to the process in [temp.deduct.type] with the exception 1017*0fca6ea1SDimitry Andric // that deduction does not fail if not all template arguments are 1018*0fca6ea1SDimitry Andric // deduced. 1019*0fca6ea1SDimitry Andric // 1020*0fca6ea1SDimitry Andric // 1021*0fca6ea1SDimitry Andric // template<typename X, typename Y> 1022*0fca6ea1SDimitry Andric // f(X, Y) -> f<Y, X>; 1023*0fca6ea1SDimitry Andric // 1024*0fca6ea1SDimitry Andric // template<typename U> 1025*0fca6ea1SDimitry Andric // using alias = f<int, U>; 1026*0fca6ea1SDimitry Andric // 1027*0fca6ea1SDimitry Andric // The RHS of alias is f<int, U>, we deduced the template arguments of 1028*0fca6ea1SDimitry Andric // the return type of the deduction guide from it: Y->int, X->U 1029*0fca6ea1SDimitry Andric sema::TemplateDeductionInfo TDeduceInfo(Loc); 1030*0fca6ea1SDimitry Andric // Must initialize n elements, this is required by DeduceTemplateArguments. 1031*0fca6ea1SDimitry Andric SmallVector<DeducedTemplateArgument> DeduceResults( 1032*0fca6ea1SDimitry Andric F->getTemplateParameters()->size()); 1033*0fca6ea1SDimitry Andric 1034*0fca6ea1SDimitry Andric // FIXME: DeduceTemplateArguments stops immediately at the first 1035*0fca6ea1SDimitry Andric // non-deducible template argument. However, this doesn't seem to casue 1036*0fca6ea1SDimitry Andric // issues for practice cases, we probably need to extend it to continue 1037*0fca6ea1SDimitry Andric // performing deduction for rest of arguments to align with the C++ 1038*0fca6ea1SDimitry Andric // standard. 1039*0fca6ea1SDimitry Andric SemaRef.DeduceTemplateArguments( 1040*0fca6ea1SDimitry Andric F->getTemplateParameters(), FReturnType->template_arguments(), 1041*0fca6ea1SDimitry Andric AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, 1042*0fca6ea1SDimitry Andric /*NumberOfArgumentsMustMatch=*/false); 1043*0fca6ea1SDimitry Andric 1044*0fca6ea1SDimitry Andric SmallVector<TemplateArgument> DeducedArgs; 1045*0fca6ea1SDimitry Andric SmallVector<unsigned> NonDeducedTemplateParamsInFIndex; 1046*0fca6ea1SDimitry Andric // !!NOTE: DeduceResults respects the sequence of template parameters of 1047*0fca6ea1SDimitry Andric // the deduction guide f. 1048*0fca6ea1SDimitry Andric for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { 1049*0fca6ea1SDimitry Andric if (const auto &D = DeduceResults[Index]; !D.isNull()) // Deduced 1050*0fca6ea1SDimitry Andric DeducedArgs.push_back(D); 1051*0fca6ea1SDimitry Andric else 1052*0fca6ea1SDimitry Andric NonDeducedTemplateParamsInFIndex.push_back(Index); 1053*0fca6ea1SDimitry Andric } 1054*0fca6ea1SDimitry Andric auto DeducedAliasTemplateParams = 1055*0fca6ea1SDimitry Andric TemplateParamsReferencedInTemplateArgumentList( 1056*0fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters(), DeducedArgs); 1057*0fca6ea1SDimitry Andric // All template arguments null by default. 1058*0fca6ea1SDimitry Andric SmallVector<TemplateArgument> TemplateArgsForBuildingFPrime( 1059*0fca6ea1SDimitry Andric F->getTemplateParameters()->size()); 1060*0fca6ea1SDimitry Andric 1061*0fca6ea1SDimitry Andric // Create a template parameter list for the synthesized deduction guide f'. 1062*0fca6ea1SDimitry Andric // 1063*0fca6ea1SDimitry Andric // C++ [over.match.class.deduct]p3.2: 1064*0fca6ea1SDimitry Andric // If f is a function template, f' is a function template whose template 1065*0fca6ea1SDimitry Andric // parameter list consists of all the template parameters of A 1066*0fca6ea1SDimitry Andric // (including their default template arguments) that appear in the above 1067*0fca6ea1SDimitry Andric // deductions or (recursively) in their default template arguments 1068*0fca6ea1SDimitry Andric SmallVector<NamedDecl *> FPrimeTemplateParams; 1069*0fca6ea1SDimitry Andric // Store template arguments that refer to the newly-created template 1070*0fca6ea1SDimitry Andric // parameters, used for building `TemplateArgsForBuildingFPrime`. 1071*0fca6ea1SDimitry Andric SmallVector<TemplateArgument, 16> TransformedDeducedAliasArgs( 1072*0fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->size()); 1073*0fca6ea1SDimitry Andric 1074*0fca6ea1SDimitry Andric for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) { 1075*0fca6ea1SDimitry Andric auto *TP = 1076*0fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx); 1077*0fca6ea1SDimitry Andric // Rebuild any internal references to earlier parameters and reindex as 1078*0fca6ea1SDimitry Andric // we go. 1079*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 1080*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 1081*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); 1082*0fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 1083*0fca6ea1SDimitry Andric SemaRef, AliasTemplate->getDeclContext(), TP, Args, 1084*0fca6ea1SDimitry Andric /*NewIndex=*/FPrimeTemplateParams.size(), 1085*0fca6ea1SDimitry Andric getTemplateParameterDepth(TP)); 1086*0fca6ea1SDimitry Andric FPrimeTemplateParams.push_back(NewParam); 1087*0fca6ea1SDimitry Andric 1088*0fca6ea1SDimitry Andric TemplateArgument NewTemplateArgument = 1089*0fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 1090*0fca6ea1SDimitry Andric TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument; 1091*0fca6ea1SDimitry Andric } 1092*0fca6ea1SDimitry Andric unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size(); 1093*0fca6ea1SDimitry Andric // ...followed by the template parameters of f that were not deduced 1094*0fca6ea1SDimitry Andric // (including their default template arguments) 1095*0fca6ea1SDimitry Andric for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) { 1096*0fca6ea1SDimitry Andric auto *TP = F->getTemplateParameters()->getParam(FTemplateParamIdx); 1097*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 1098*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 1099*0fca6ea1SDimitry Andric // We take a shortcut here, it is ok to reuse the 1100*0fca6ea1SDimitry Andric // TemplateArgsForBuildingFPrime. 1101*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); 1102*0fca6ea1SDimitry Andric NamedDecl *NewParam = transformTemplateParameter( 1103*0fca6ea1SDimitry Andric SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size(), 1104*0fca6ea1SDimitry Andric getTemplateParameterDepth(TP)); 1105*0fca6ea1SDimitry Andric FPrimeTemplateParams.push_back(NewParam); 1106*0fca6ea1SDimitry Andric 1107*0fca6ea1SDimitry Andric assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() && 1108*0fca6ea1SDimitry Andric "The argument must be null before setting"); 1109*0fca6ea1SDimitry Andric TemplateArgsForBuildingFPrime[FTemplateParamIdx] = 1110*0fca6ea1SDimitry Andric Context.getInjectedTemplateArg(NewParam); 1111*0fca6ea1SDimitry Andric } 1112*0fca6ea1SDimitry Andric 1113*0fca6ea1SDimitry Andric // To form a deduction guide f' from f, we leverage clang's instantiation 1114*0fca6ea1SDimitry Andric // mechanism, we construct a template argument list where the template 1115*0fca6ea1SDimitry Andric // arguments refer to the newly-created template parameters of f', and 1116*0fca6ea1SDimitry Andric // then apply instantiation on this template argument list to instantiate 1117*0fca6ea1SDimitry Andric // f, this ensures all template parameter occurrences are updated 1118*0fca6ea1SDimitry Andric // correctly. 1119*0fca6ea1SDimitry Andric // 1120*0fca6ea1SDimitry Andric // The template argument list is formed from the `DeducedArgs`, two parts: 1121*0fca6ea1SDimitry Andric // 1) appeared template parameters of alias: transfrom the deduced 1122*0fca6ea1SDimitry Andric // template argument; 1123*0fca6ea1SDimitry Andric // 2) non-deduced template parameters of f: rebuild a 1124*0fca6ea1SDimitry Andric // template argument; 1125*0fca6ea1SDimitry Andric // 1126*0fca6ea1SDimitry Andric // 2) has been built already (when rebuilding the new template 1127*0fca6ea1SDimitry Andric // parameters), we now perform 1). 1128*0fca6ea1SDimitry Andric MultiLevelTemplateArgumentList Args; 1129*0fca6ea1SDimitry Andric Args.setKind(TemplateSubstitutionKind::Rewrite); 1130*0fca6ea1SDimitry Andric Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); 1131*0fca6ea1SDimitry Andric for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { 1132*0fca6ea1SDimitry Andric const auto &D = DeduceResults[Index]; 1133*0fca6ea1SDimitry Andric if (D.isNull()) { 1134*0fca6ea1SDimitry Andric // 2): Non-deduced template parameter has been built already. 1135*0fca6ea1SDimitry Andric assert(!TemplateArgsForBuildingFPrime[Index].isNull() && 1136*0fca6ea1SDimitry Andric "template arguments for non-deduced template parameters should " 1137*0fca6ea1SDimitry Andric "be been set!"); 1138*0fca6ea1SDimitry Andric continue; 1139*0fca6ea1SDimitry Andric } 1140*0fca6ea1SDimitry Andric TemplateArgumentLoc Input = 1141*0fca6ea1SDimitry Andric SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); 1142*0fca6ea1SDimitry Andric TemplateArgumentLoc Output; 1143*0fca6ea1SDimitry Andric if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) { 1144*0fca6ea1SDimitry Andric assert(TemplateArgsForBuildingFPrime[Index].isNull() && 1145*0fca6ea1SDimitry Andric "InstantiatedArgs must be null before setting"); 1146*0fca6ea1SDimitry Andric TemplateArgsForBuildingFPrime[Index] = Output.getArgument(); 1147*0fca6ea1SDimitry Andric } 1148*0fca6ea1SDimitry Andric } 1149*0fca6ea1SDimitry Andric 1150*0fca6ea1SDimitry Andric auto *TemplateArgListForBuildingFPrime = 1151*0fca6ea1SDimitry Andric TemplateArgumentList::CreateCopy(Context, TemplateArgsForBuildingFPrime); 1152*0fca6ea1SDimitry Andric // Form the f' by substituting the template arguments into f. 1153*0fca6ea1SDimitry Andric if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration( 1154*0fca6ea1SDimitry Andric F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), 1155*0fca6ea1SDimitry Andric Sema::CodeSynthesisContext::BuildingDeductionGuides)) { 1156*0fca6ea1SDimitry Andric auto *GG = cast<CXXDeductionGuideDecl>(FPrime); 1157*0fca6ea1SDimitry Andric 1158*0fca6ea1SDimitry Andric Expr *IsDeducible = buildIsDeducibleConstraint( 1159*0fca6ea1SDimitry Andric SemaRef, AliasTemplate, FPrime->getReturnType(), FPrimeTemplateParams); 1160*0fca6ea1SDimitry Andric Expr *RequiresClause = 1161*0fca6ea1SDimitry Andric buildAssociatedConstraints(SemaRef, F, AliasTemplate, DeduceResults, 1162*0fca6ea1SDimitry Andric FirstUndeducedParamIdx, IsDeducible); 1163*0fca6ea1SDimitry Andric 1164*0fca6ea1SDimitry Andric auto *FPrimeTemplateParamList = TemplateParameterList::Create( 1165*0fca6ea1SDimitry Andric Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), 1166*0fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->getLAngleLoc(), 1167*0fca6ea1SDimitry Andric FPrimeTemplateParams, 1168*0fca6ea1SDimitry Andric AliasTemplate->getTemplateParameters()->getRAngleLoc(), 1169*0fca6ea1SDimitry Andric /*RequiresClause=*/RequiresClause); 1170*0fca6ea1SDimitry Andric auto *Result = cast<FunctionTemplateDecl>(buildDeductionGuide( 1171*0fca6ea1SDimitry Andric SemaRef, AliasTemplate, FPrimeTemplateParamList, 1172*0fca6ea1SDimitry Andric GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), 1173*0fca6ea1SDimitry Andric GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(), 1174*0fca6ea1SDimitry Andric AliasTemplate->getLocation(), AliasTemplate->getEndLoc(), 1175*0fca6ea1SDimitry Andric F->isImplicit())); 1176*0fca6ea1SDimitry Andric cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl()) 1177*0fca6ea1SDimitry Andric ->setDeductionCandidateKind(GG->getDeductionCandidateKind()); 1178*0fca6ea1SDimitry Andric return Result; 1179*0fca6ea1SDimitry Andric } 1180*0fca6ea1SDimitry Andric return nullptr; 1181*0fca6ea1SDimitry Andric } 1182*0fca6ea1SDimitry Andric 1183*0fca6ea1SDimitry Andric void DeclareImplicitDeductionGuidesForTypeAlias( 1184*0fca6ea1SDimitry Andric Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) { 1185*0fca6ea1SDimitry Andric if (AliasTemplate->isInvalidDecl()) 1186*0fca6ea1SDimitry Andric return; 1187*0fca6ea1SDimitry Andric auto &Context = SemaRef.Context; 1188*0fca6ea1SDimitry Andric // FIXME: if there is an explicit deduction guide after the first use of the 1189*0fca6ea1SDimitry Andric // type alias usage, we will not cover this explicit deduction guide. fix this 1190*0fca6ea1SDimitry Andric // case. 1191*0fca6ea1SDimitry Andric if (hasDeclaredDeductionGuides( 1192*0fca6ea1SDimitry Andric Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate), 1193*0fca6ea1SDimitry Andric AliasTemplate->getDeclContext())) 1194*0fca6ea1SDimitry Andric return; 1195*0fca6ea1SDimitry Andric auto [Template, AliasRhsTemplateArgs] = 1196*0fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); 1197*0fca6ea1SDimitry Andric if (!Template) 1198*0fca6ea1SDimitry Andric return; 1199*0fca6ea1SDimitry Andric DeclarationNameInfo NameInfo( 1200*0fca6ea1SDimitry Andric Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc); 1201*0fca6ea1SDimitry Andric LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName); 1202*0fca6ea1SDimitry Andric SemaRef.LookupQualifiedName(Guides, Template->getDeclContext()); 1203*0fca6ea1SDimitry Andric Guides.suppressDiagnostics(); 1204*0fca6ea1SDimitry Andric 1205*0fca6ea1SDimitry Andric for (auto *G : Guides) { 1206*0fca6ea1SDimitry Andric if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(G)) { 1207*0fca6ea1SDimitry Andric // The deduction guide is a non-template function decl, we just clone it. 1208*0fca6ea1SDimitry Andric auto *FunctionType = 1209*0fca6ea1SDimitry Andric SemaRef.Context.getTrivialTypeSourceInfo(DG->getType()); 1210*0fca6ea1SDimitry Andric FunctionProtoTypeLoc FPTL = 1211*0fca6ea1SDimitry Andric FunctionType->getTypeLoc().castAs<FunctionProtoTypeLoc>(); 1212*0fca6ea1SDimitry Andric 1213*0fca6ea1SDimitry Andric // Clone the parameters. 1214*0fca6ea1SDimitry Andric for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) { 1215*0fca6ea1SDimitry Andric const auto *P = DG->getParamDecl(I); 1216*0fca6ea1SDimitry Andric auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(P->getType()); 1217*0fca6ea1SDimitry Andric ParmVarDecl *NewParam = ParmVarDecl::Create( 1218*0fca6ea1SDimitry Andric SemaRef.Context, G->getDeclContext(), 1219*0fca6ea1SDimitry Andric DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr, 1220*0fca6ea1SDimitry Andric TSI->getType(), TSI, SC_None, nullptr); 1221*0fca6ea1SDimitry Andric NewParam->setScopeInfo(0, I); 1222*0fca6ea1SDimitry Andric FPTL.setParam(I, NewParam); 1223*0fca6ea1SDimitry Andric } 1224*0fca6ea1SDimitry Andric auto *Transformed = cast<FunctionDecl>(buildDeductionGuide( 1225*0fca6ea1SDimitry Andric SemaRef, AliasTemplate, /*TemplateParams=*/nullptr, 1226*0fca6ea1SDimitry Andric /*Constructor=*/nullptr, DG->getExplicitSpecifier(), FunctionType, 1227*0fca6ea1SDimitry Andric AliasTemplate->getBeginLoc(), AliasTemplate->getLocation(), 1228*0fca6ea1SDimitry Andric AliasTemplate->getEndLoc(), DG->isImplicit())); 1229*0fca6ea1SDimitry Andric 1230*0fca6ea1SDimitry Andric // FIXME: Here the synthesized deduction guide is not a templated 1231*0fca6ea1SDimitry Andric // function. Per [dcl.decl]p4, the requires-clause shall be present only 1232*0fca6ea1SDimitry Andric // if the declarator declares a templated function, a bug in standard? 1233*0fca6ea1SDimitry Andric auto *Constraint = buildIsDeducibleConstraint( 1234*0fca6ea1SDimitry Andric SemaRef, AliasTemplate, Transformed->getReturnType(), {}); 1235*0fca6ea1SDimitry Andric if (auto *RC = DG->getTrailingRequiresClause()) { 1236*0fca6ea1SDimitry Andric auto Conjunction = 1237*0fca6ea1SDimitry Andric SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, 1238*0fca6ea1SDimitry Andric BinaryOperatorKind::BO_LAnd, RC, Constraint); 1239*0fca6ea1SDimitry Andric if (!Conjunction.isInvalid()) 1240*0fca6ea1SDimitry Andric Constraint = Conjunction.getAs<Expr>(); 1241*0fca6ea1SDimitry Andric } 1242*0fca6ea1SDimitry Andric Transformed->setTrailingRequiresClause(Constraint); 1243*0fca6ea1SDimitry Andric } 1244*0fca6ea1SDimitry Andric FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G); 1245*0fca6ea1SDimitry Andric if (!F) 1246*0fca6ea1SDimitry Andric continue; 1247*0fca6ea1SDimitry Andric // The **aggregate** deduction guides are handled in a different code path 1248*0fca6ea1SDimitry Andric // (DeclareAggregateDeductionGuideFromInitList), which involves the tricky 1249*0fca6ea1SDimitry Andric // cache. 1250*0fca6ea1SDimitry Andric if (cast<CXXDeductionGuideDecl>(F->getTemplatedDecl()) 1251*0fca6ea1SDimitry Andric ->getDeductionCandidateKind() == DeductionCandidate::Aggregate) 1252*0fca6ea1SDimitry Andric continue; 1253*0fca6ea1SDimitry Andric 1254*0fca6ea1SDimitry Andric BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc); 1255*0fca6ea1SDimitry Andric } 1256*0fca6ea1SDimitry Andric } 1257*0fca6ea1SDimitry Andric 1258*0fca6ea1SDimitry Andric // Build an aggregate deduction guide for a type alias template. 1259*0fca6ea1SDimitry Andric FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias( 1260*0fca6ea1SDimitry Andric Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, 1261*0fca6ea1SDimitry Andric MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) { 1262*0fca6ea1SDimitry Andric TemplateDecl *RHSTemplate = 1263*0fca6ea1SDimitry Andric getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first; 1264*0fca6ea1SDimitry Andric if (!RHSTemplate) 1265*0fca6ea1SDimitry Andric return nullptr; 1266*0fca6ea1SDimitry Andric auto *RHSDeductionGuide = SemaRef.DeclareAggregateDeductionGuideFromInitList( 1267*0fca6ea1SDimitry Andric RHSTemplate, ParamTypes, Loc); 1268*0fca6ea1SDimitry Andric if (!RHSDeductionGuide) 1269*0fca6ea1SDimitry Andric return nullptr; 1270*0fca6ea1SDimitry Andric return BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, 1271*0fca6ea1SDimitry Andric RHSDeductionGuide, Loc); 1272*0fca6ea1SDimitry Andric } 1273*0fca6ea1SDimitry Andric 1274*0fca6ea1SDimitry Andric } // namespace 1275*0fca6ea1SDimitry Andric 1276*0fca6ea1SDimitry Andric FunctionTemplateDecl *Sema::DeclareAggregateDeductionGuideFromInitList( 1277*0fca6ea1SDimitry Andric TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes, 1278*0fca6ea1SDimitry Andric SourceLocation Loc) { 1279*0fca6ea1SDimitry Andric llvm::FoldingSetNodeID ID; 1280*0fca6ea1SDimitry Andric ID.AddPointer(Template); 1281*0fca6ea1SDimitry Andric for (auto &T : ParamTypes) 1282*0fca6ea1SDimitry Andric T.getCanonicalType().Profile(ID); 1283*0fca6ea1SDimitry Andric unsigned Hash = ID.ComputeHash(); 1284*0fca6ea1SDimitry Andric 1285*0fca6ea1SDimitry Andric auto Found = AggregateDeductionCandidates.find(Hash); 1286*0fca6ea1SDimitry Andric if (Found != AggregateDeductionCandidates.end()) { 1287*0fca6ea1SDimitry Andric CXXDeductionGuideDecl *GD = Found->getSecond(); 1288*0fca6ea1SDimitry Andric return GD->getDescribedFunctionTemplate(); 1289*0fca6ea1SDimitry Andric } 1290*0fca6ea1SDimitry Andric 1291*0fca6ea1SDimitry Andric if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { 1292*0fca6ea1SDimitry Andric if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias( 1293*0fca6ea1SDimitry Andric *this, AliasTemplate, ParamTypes, Loc)) { 1294*0fca6ea1SDimitry Andric auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); 1295*0fca6ea1SDimitry Andric GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); 1296*0fca6ea1SDimitry Andric AggregateDeductionCandidates[Hash] = GD; 1297*0fca6ea1SDimitry Andric return FTD; 1298*0fca6ea1SDimitry Andric } 1299*0fca6ea1SDimitry Andric } 1300*0fca6ea1SDimitry Andric 1301*0fca6ea1SDimitry Andric if (CXXRecordDecl *DefRecord = 1302*0fca6ea1SDimitry Andric cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { 1303*0fca6ea1SDimitry Andric if (TemplateDecl *DescribedTemplate = 1304*0fca6ea1SDimitry Andric DefRecord->getDescribedClassTemplate()) 1305*0fca6ea1SDimitry Andric Template = DescribedTemplate; 1306*0fca6ea1SDimitry Andric } 1307*0fca6ea1SDimitry Andric 1308*0fca6ea1SDimitry Andric DeclContext *DC = Template->getDeclContext(); 1309*0fca6ea1SDimitry Andric if (DC->isDependentContext()) 1310*0fca6ea1SDimitry Andric return nullptr; 1311*0fca6ea1SDimitry Andric 1312*0fca6ea1SDimitry Andric ConvertConstructorToDeductionGuideTransform Transform( 1313*0fca6ea1SDimitry Andric *this, cast<ClassTemplateDecl>(Template)); 1314*0fca6ea1SDimitry Andric if (!isCompleteType(Loc, Transform.DeducedType)) 1315*0fca6ea1SDimitry Andric return nullptr; 1316*0fca6ea1SDimitry Andric 1317*0fca6ea1SDimitry Andric // In case we were expanding a pack when we attempted to declare deduction 1318*0fca6ea1SDimitry Andric // guides, turn off pack expansion for everything we're about to do. 1319*0fca6ea1SDimitry Andric ArgumentPackSubstitutionIndexRAII SubstIndex(*this, 1320*0fca6ea1SDimitry Andric /*NewSubstitutionIndex=*/-1); 1321*0fca6ea1SDimitry Andric // Create a template instantiation record to track the "instantiation" of 1322*0fca6ea1SDimitry Andric // constructors into deduction guides. 1323*0fca6ea1SDimitry Andric InstantiatingTemplate BuildingDeductionGuides( 1324*0fca6ea1SDimitry Andric *this, Loc, Template, 1325*0fca6ea1SDimitry Andric Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); 1326*0fca6ea1SDimitry Andric if (BuildingDeductionGuides.isInvalid()) 1327*0fca6ea1SDimitry Andric return nullptr; 1328*0fca6ea1SDimitry Andric 1329*0fca6ea1SDimitry Andric ClassTemplateDecl *Pattern = 1330*0fca6ea1SDimitry Andric Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; 1331*0fca6ea1SDimitry Andric ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); 1332*0fca6ea1SDimitry Andric 1333*0fca6ea1SDimitry Andric auto *FTD = cast<FunctionTemplateDecl>( 1334*0fca6ea1SDimitry Andric Transform.buildSimpleDeductionGuide(ParamTypes)); 1335*0fca6ea1SDimitry Andric SavedContext.pop(); 1336*0fca6ea1SDimitry Andric auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); 1337*0fca6ea1SDimitry Andric GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); 1338*0fca6ea1SDimitry Andric AggregateDeductionCandidates[Hash] = GD; 1339*0fca6ea1SDimitry Andric return FTD; 1340*0fca6ea1SDimitry Andric } 1341*0fca6ea1SDimitry Andric 1342*0fca6ea1SDimitry Andric void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, 1343*0fca6ea1SDimitry Andric SourceLocation Loc) { 1344*0fca6ea1SDimitry Andric if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { 1345*0fca6ea1SDimitry Andric DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc); 1346*0fca6ea1SDimitry Andric return; 1347*0fca6ea1SDimitry Andric } 1348*0fca6ea1SDimitry Andric if (CXXRecordDecl *DefRecord = 1349*0fca6ea1SDimitry Andric cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { 1350*0fca6ea1SDimitry Andric if (TemplateDecl *DescribedTemplate = 1351*0fca6ea1SDimitry Andric DefRecord->getDescribedClassTemplate()) 1352*0fca6ea1SDimitry Andric Template = DescribedTemplate; 1353*0fca6ea1SDimitry Andric } 1354*0fca6ea1SDimitry Andric 1355*0fca6ea1SDimitry Andric DeclContext *DC = Template->getDeclContext(); 1356*0fca6ea1SDimitry Andric if (DC->isDependentContext()) 1357*0fca6ea1SDimitry Andric return; 1358*0fca6ea1SDimitry Andric 1359*0fca6ea1SDimitry Andric ConvertConstructorToDeductionGuideTransform Transform( 1360*0fca6ea1SDimitry Andric *this, cast<ClassTemplateDecl>(Template)); 1361*0fca6ea1SDimitry Andric if (!isCompleteType(Loc, Transform.DeducedType)) 1362*0fca6ea1SDimitry Andric return; 1363*0fca6ea1SDimitry Andric 1364*0fca6ea1SDimitry Andric if (hasDeclaredDeductionGuides(Transform.DeductionGuideName, DC)) 1365*0fca6ea1SDimitry Andric return; 1366*0fca6ea1SDimitry Andric 1367*0fca6ea1SDimitry Andric // In case we were expanding a pack when we attempted to declare deduction 1368*0fca6ea1SDimitry Andric // guides, turn off pack expansion for everything we're about to do. 1369*0fca6ea1SDimitry Andric ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); 1370*0fca6ea1SDimitry Andric // Create a template instantiation record to track the "instantiation" of 1371*0fca6ea1SDimitry Andric // constructors into deduction guides. 1372*0fca6ea1SDimitry Andric InstantiatingTemplate BuildingDeductionGuides( 1373*0fca6ea1SDimitry Andric *this, Loc, Template, 1374*0fca6ea1SDimitry Andric Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); 1375*0fca6ea1SDimitry Andric if (BuildingDeductionGuides.isInvalid()) 1376*0fca6ea1SDimitry Andric return; 1377*0fca6ea1SDimitry Andric 1378*0fca6ea1SDimitry Andric // Convert declared constructors into deduction guide templates. 1379*0fca6ea1SDimitry Andric // FIXME: Skip constructors for which deduction must necessarily fail (those 1380*0fca6ea1SDimitry Andric // for which some class template parameter without a default argument never 1381*0fca6ea1SDimitry Andric // appears in a deduced context). 1382*0fca6ea1SDimitry Andric ClassTemplateDecl *Pattern = 1383*0fca6ea1SDimitry Andric Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; 1384*0fca6ea1SDimitry Andric ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); 1385*0fca6ea1SDimitry Andric llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors; 1386*0fca6ea1SDimitry Andric bool AddedAny = false; 1387*0fca6ea1SDimitry Andric for (NamedDecl *D : LookupConstructors(Pattern->getTemplatedDecl())) { 1388*0fca6ea1SDimitry Andric D = D->getUnderlyingDecl(); 1389*0fca6ea1SDimitry Andric if (D->isInvalidDecl() || D->isImplicit()) 1390*0fca6ea1SDimitry Andric continue; 1391*0fca6ea1SDimitry Andric 1392*0fca6ea1SDimitry Andric D = cast<NamedDecl>(D->getCanonicalDecl()); 1393*0fca6ea1SDimitry Andric 1394*0fca6ea1SDimitry Andric // Within C++20 modules, we may have multiple same constructors in 1395*0fca6ea1SDimitry Andric // multiple same RecordDecls. And it doesn't make sense to create 1396*0fca6ea1SDimitry Andric // duplicated deduction guides for the duplicated constructors. 1397*0fca6ea1SDimitry Andric if (ProcessedCtors.count(D)) 1398*0fca6ea1SDimitry Andric continue; 1399*0fca6ea1SDimitry Andric 1400*0fca6ea1SDimitry Andric auto *FTD = dyn_cast<FunctionTemplateDecl>(D); 1401*0fca6ea1SDimitry Andric auto *CD = 1402*0fca6ea1SDimitry Andric dyn_cast_or_null<CXXConstructorDecl>(FTD ? FTD->getTemplatedDecl() : D); 1403*0fca6ea1SDimitry Andric // Class-scope explicit specializations (MS extension) do not result in 1404*0fca6ea1SDimitry Andric // deduction guides. 1405*0fca6ea1SDimitry Andric if (!CD || (!FTD && CD->isFunctionTemplateSpecialization())) 1406*0fca6ea1SDimitry Andric continue; 1407*0fca6ea1SDimitry Andric 1408*0fca6ea1SDimitry Andric // Cannot make a deduction guide when unparsed arguments are present. 1409*0fca6ea1SDimitry Andric if (llvm::any_of(CD->parameters(), [](ParmVarDecl *P) { 1410*0fca6ea1SDimitry Andric return !P || P->hasUnparsedDefaultArg(); 1411*0fca6ea1SDimitry Andric })) 1412*0fca6ea1SDimitry Andric continue; 1413*0fca6ea1SDimitry Andric 1414*0fca6ea1SDimitry Andric ProcessedCtors.insert(D); 1415*0fca6ea1SDimitry Andric Transform.transformConstructor(FTD, CD); 1416*0fca6ea1SDimitry Andric AddedAny = true; 1417*0fca6ea1SDimitry Andric } 1418*0fca6ea1SDimitry Andric 1419*0fca6ea1SDimitry Andric // C++17 [over.match.class.deduct] 1420*0fca6ea1SDimitry Andric // -- If C is not defined or does not declare any constructors, an 1421*0fca6ea1SDimitry Andric // additional function template derived as above from a hypothetical 1422*0fca6ea1SDimitry Andric // constructor C(). 1423*0fca6ea1SDimitry Andric if (!AddedAny) 1424*0fca6ea1SDimitry Andric Transform.buildSimpleDeductionGuide(std::nullopt); 1425*0fca6ea1SDimitry Andric 1426*0fca6ea1SDimitry Andric // -- An additional function template derived as above from a hypothetical 1427*0fca6ea1SDimitry Andric // constructor C(C), called the copy deduction candidate. 1428*0fca6ea1SDimitry Andric cast<CXXDeductionGuideDecl>( 1429*0fca6ea1SDimitry Andric cast<FunctionTemplateDecl>( 1430*0fca6ea1SDimitry Andric Transform.buildSimpleDeductionGuide(Transform.DeducedType)) 1431*0fca6ea1SDimitry Andric ->getTemplatedDecl()) 1432*0fca6ea1SDimitry Andric ->setDeductionCandidateKind(DeductionCandidate::Copy); 1433*0fca6ea1SDimitry Andric 1434*0fca6ea1SDimitry Andric SavedContext.pop(); 1435*0fca6ea1SDimitry Andric } 1436