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