================ @@ -1216,10 +1308,225 @@ void DeclareImplicitDeductionGuidesForTypeAlias( ->getDeductionCandidateKind() == DeductionCandidate::Aggregate) continue; - BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc); + BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc, + DeducingTemplate, DerivedClassMapperType); } } +void DeclareImplicitDeductionGuidesFromInheritedConstructors( + Sema &SemaRef, TemplateDecl *Template, ClassTemplateDecl *Pattern, + TypeSourceInfo *BaseTSI, unsigned BaseIdx) { + auto &Context = SemaRef.Context; + DeclContext *DC = Template->getDeclContext(); + const auto *BaseTST = BaseTSI->getType()->getAs<TemplateSpecializationType>(); + if (!BaseTST) + return; + SourceLocation BaseLoc = BaseTSI->getTypeLoc().getBeginLoc(); + + TemplateDecl *BaseTD = BaseTST->getTemplateName().getAsTemplateDecl(); + if (!BaseTD) + return; + + // Subsitute any parameters with default arguments not present in the base, + // since partial specializations cannot have default parameters + TemplateParameterList *TemplateTPL = Pattern->getTemplateParameters(); + auto BaseDeducedTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + TemplateTPL, BaseTST->template_arguments()); + SmallVector<NamedDecl *, 8> PartialSpecParams; + SmallVector<TemplateArgument, 8> SubstArgs; + PartialSpecParams.reserve(TemplateTPL->size()); + SubstArgs.reserve(TemplateTPL->size()); + LocalInstantiationScope Scope(SemaRef); + for (unsigned I = 0, N = TemplateTPL->size(); I < N; ++I) { + NamedDecl *Param = TemplateTPL->getParam(I); + if (!BaseDeducedTemplateParams.contains(I)) { + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param); + TTP && TTP->hasDefaultArgument()) { + SubstArgs.push_back(TTP->getDefaultArgument().getArgument()); + continue; + } + + if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param); + NTTP && NTTP->hasDefaultArgument()) { + SubstArgs.push_back(NTTP->getDefaultArgument().getArgument()); + continue; + } + + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param); + TTP && TTP->hasDefaultArgument()) { + SubstArgs.push_back(TTP->getDefaultArgument().getArgument()); + continue; + } + + // We have a template parameter that is not present in the base + // and does not have a default argument. We create the deduction + // guide anyway to display a diagnostic. + } + + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(SubstArgs); + Args.addOuterRetainedLevels(Template->getTemplateDepth()); + + NamedDecl *NewParam = transformTemplateParameter( + SemaRef, DC, Param, Args, PartialSpecParams.size(), + Template->getTemplateDepth()); + if (!NewParam) + return; + + PartialSpecParams.push_back(NewParam); + SubstArgs.push_back(Context.getInjectedTemplateArg(NewParam)); + } + + Expr *RequiresClause = nullptr; + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(SubstArgs); + Args.addOuterRetainedLevels(Template->getTemplateDepth()); + if (Expr *TemplateRC = TemplateTPL->getRequiresClause()) { + ExprResult E = SemaRef.SubstExpr(TemplateRC, Args); + if (E.isInvalid()) + return; + RequiresClause = E.getAs<Expr>(); + } + auto *PartialSpecTPL = TemplateParameterList::Create( + Context, TemplateTPL->getTemplateLoc(), TemplateTPL->getLAngleLoc(), + PartialSpecParams, TemplateTPL->getRAngleLoc(), RequiresClause); + + // [over.match.class.deduct]p1.10 + // Let A be an alias template whose template parameter list is that of + // [Template] and whose defining-type-id is [BaseTSI] ... + auto *TransformedBase = + SemaRef.SubstType(BaseTSI, Args, BaseLoc, DeclarationName(), true); + auto *BaseAD = TypeAliasDecl::Create( + Context, DC, SourceLocation(), BaseLoc, + TransformedBase->getType().getBaseTypeIdentifier(), TransformedBase); + std::string AliasDeclName = + (Twine("__ctad_alias_") + BaseTD->getName() + "_to_" + + Template->getName() + "_" + Twine(BaseIdx)) + .str(); + IdentifierInfo *AliasIdentifier = &Context.Idents.get(AliasDeclName); + auto *BaseATD = TypeAliasTemplateDecl::Create( + Context, DC, BaseLoc, DeclarationName(AliasIdentifier), PartialSpecTPL, + BaseAD); + BaseAD->setDescribedAliasTemplate(BaseATD); + BaseAD->setImplicit(); + BaseATD->setImplicit(); + + DC->addDecl(BaseATD); + + // ... given a class template `template <typename> class CC;` + // whose primary template is not defined ... + auto *TParam = TemplateTypeParmDecl::Create( + Context, DC, SourceLocation(), SourceLocation(), + Template->getTemplateDepth(), 0, nullptr, false, false); + TParam->setImplicit(); + auto *MapperTPL = TemplateParameterList::Create( + Context, SourceLocation(), SourceLocation(), + ArrayRef<NamedDecl *>(TParam), SourceLocation(), nullptr); + + std::string MapperDeclName = + (Twine("__ctad_mapper_") + BaseTD->getName() + "_to_" + + Template->getName() + "_" + Twine(BaseIdx)) + .str(); + IdentifierInfo *MapperII = &Context.Idents.get(MapperDeclName); + CXXRecordDecl *MapperRD = CXXRecordDecl::Create( + Context, CXXRecordDecl::TagKind::Struct, DC, SourceLocation(), + SourceLocation(), nullptr, nullptr); + ClassTemplateDecl *MapperTD = + ClassTemplateDecl::Create(Context, DC, SourceLocation(), + DeclarationName(MapperII), MapperTPL, MapperRD); + MapperRD->setDescribedClassTemplate(MapperTD); + MapperTD->setImplicit(); + MapperRD->setImplicit(); + + DC->addDecl(MapperTD); + + // ... and with a single partial specialization whose template parameter list + // is that of A with the template argument list of A ... + TemplateArgument AliasTA(TransformedBase->getType()); + ArrayRef<TemplateArgument> TAL(AliasTA); + auto MapperTemplateName = + Context.getCanonicalTemplateName(TemplateName(MapperTD)); + QualType CanonType = + Context.getTemplateSpecializationType(MapperTemplateName, TAL); + + auto *MapperSpecialization = ClassTemplatePartialSpecializationDecl::Create( + Context, ClassTemplatePartialSpecializationDecl::TagKind::Struct, DC, + SourceLocation(), SourceLocation(), PartialSpecTPL, MapperTD, TAL, ---------------- antangelo wrote:
Done, I am now cloning the alias TPL and stripping default arguments from it to create a new TPL for the partial specialization. https://github.com/llvm/llvm-project/pull/98788 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits