================ @@ -944,12 +950,67 @@ getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } +struct InheritedConstructorDeductionInfo { + TemplateDecl *DerivedClassTemplate; + TypeSourceInfo *CCType; +}; + +// Build the type for a deduction guide generated from an inherited constructor +// [over.match.class.deduct]p1.10: +// ... the set contains the guides of A with the return type R +// of each guide replaced with `typename CC<R>::type` ... +TypeSourceInfo *buildInheritedConstructorDeductionGuideType( + Sema &SemaRef, InheritedConstructorDeductionInfo Info, + TypeSourceInfo *SourceGuideTSI) { + auto &Context = SemaRef.Context; + const auto *FPT = SourceGuideTSI->getType()->getAs<FunctionProtoType>(); + assert(FPT && "Source Guide type should be a FunctionProtoType"); + + // This substitution can fail in cases where the source return type + // is not dependent and the derived class is not deducible + Sema::SFINAETrap Trap(SemaRef); + + MultiLevelTemplateArgumentList Args; + Args.addOuterTemplateArguments(Info.DerivedClassTemplate, + TemplateArgument(FPT->getReturnType()), false); + Args.addOuterRetainedLevels(Info.DerivedClassTemplate->getTemplateDepth()); + TypeSourceInfo *ReturnTypeTSI = SemaRef.SubstType( + Info.CCType, Args, Info.DerivedClassTemplate->getBeginLoc(), + DeclarationName()); + if (!ReturnTypeTSI || Trap.hasErrorOccurred()) + return nullptr; + QualType ReturnType = ReturnTypeTSI->getType(); + + TypeLocBuilder TLB; + TLB.pushFullCopy(ReturnTypeTSI->getTypeLoc()); + + QualType FT = Context.getFunctionType(ReturnType, FPT->getParamTypes(), + FPT->getExtProtoInfo()); + FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(FT); + const auto &TL = SourceGuideTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setExceptionSpecRange(TL.getExceptionSpecRange()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); + for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I) + NewTL.setParam(I, TL.getParam(I)); + + TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, FT); + return TSI; +} + // Build deduction guides for a type alias template from the given underlying // deduction guide F. -FunctionTemplateDecl * -BuildDeductionGuideForTypeAlias(Sema &SemaRef, - TypeAliasTemplateDecl *AliasTemplate, - FunctionTemplateDecl *F, SourceLocation Loc) { +// If F is synthesized from a base class (as an inherited constructor), +// then the return type will be transformed using DerivedClassMapperType. +// The resulting deduction guide is added to the DeducingTemplate argument, +// defaulting to AliasTemplate. +FunctionTemplateDecl *BuildDeductionGuideForTypeAlias( + Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, + FunctionTemplateDecl *F, SourceLocation Loc, + std::optional<InheritedConstructorDeductionInfo> FromInheritedCtor = ---------------- hokein wrote:
nit: you can get rid of the `std::optional` by passing an pointer 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