================ @@ -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] ... ---------------- hokein wrote:
According to the standard, `A` refers to the synthesized alias template, not the derived class template (which is denoted as `C` in the standard). So, in your case: ```cpp template<class T> struct B { B(T t); }; template<class InBase, class NotInBase> struct C : public B<InBase> { using B<InBase>::B; }; C c(10); ``` The synthesized `A` would be: ```cpp template<class InBase, class NotInBase> using A = B<InBase>; ``` Here, `A` is considered a deducible template because it is an alias template whose defining-type-id is a `simple-template-id`, and the `template-name` (in this case, `B`) within the `simple-template-id` is a deducible template (since `B` is a class template). 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