Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -1947,16 +1947,35 @@ /// constructor to a deduction guide. class ExtractTypeForDeductionGuide : public TreeTransform { + llvm::SmallVectorImpl &MaterializedTypedefs; + public: typedef TreeTransform Base; - ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {} + ExtractTypeForDeductionGuide( + Sema &SemaRef, llvm::SmallVectorImpl &MaterializedTypedefs) + : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {} TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { - return TransformType( - TLB, - TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc()); + ASTContext &Context = SemaRef.getASTContext(); + TypeLocBuilder InnerTLB; + QualType Transformed = TransformType( + InnerTLB, TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc()); + TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(Transformed); + + auto *Decl = TypedefDecl::Create( + SemaRef.getASTContext(), + SemaRef.getASTContext().getTranslationUnitDecl(), SourceLocation(), + SourceLocation(), TL.getTypedefNameDecl()->getIdentifier(), TSI); + MaterializedTypedefs.push_back(Decl); + + QualType TDTy = Context.getTypedefType(Decl); + TypedefTypeLoc TypedefTL = TLB.push(TDTy); + TypedefTL.setNameLoc(TL.getNameLoc()); + + return TDTy; + } }; @@ -2041,14 +2060,16 @@ // new ones. TypeLocBuilder TLB; SmallVector Params; - QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args); + SmallVector MaterializedTypedefs; + QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args, + MaterializedTypedefs); if (NewType.isNull()) return nullptr; TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); - return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(), - NewTInfo, CD->getBeginLoc(), CD->getLocation(), - CD->getEndLoc()); + return buildDeductionGuide( + TemplateParams, CD->getExplicitSpecifier(), NewTInfo, CD->getBeginLoc(), + CD->getLocation(), CD->getEndLoc(), MaterializedTypedefs); } /// Build a deduction guide with the specified parameter types. @@ -2143,16 +2164,18 @@ return NewParam; } - QualType transformFunctionProtoType(TypeLocBuilder &TLB, - FunctionProtoTypeLoc TL, - SmallVectorImpl &Params, - MultiLevelTemplateArgumentList &Args) { + QualType transformFunctionProtoType( + TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, + SmallVectorImpl &Params, + MultiLevelTemplateArgumentList &Args, + SmallVectorImpl &MaterializedTypedefs) { SmallVector ParamTypes; const FunctionProtoType *T = TL.getTypePtr(); // -- The types of the function parameters are those of the constructor. for (auto *OldParam : TL.getParams()) { - ParmVarDecl *NewParam = transformFunctionTypeParam(OldParam, Args); + ParmVarDecl *NewParam = + transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs); if (!NewParam) return QualType(); ParamTypes.push_back(NewParam->getType()); @@ -2194,9 +2217,9 @@ return Result; } - ParmVarDecl * - transformFunctionTypeParam(ParmVarDecl *OldParam, - MultiLevelTemplateArgumentList &Args) { + ParmVarDecl *transformFunctionTypeParam( + ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args, + llvm::SmallVectorImpl &MaterializedTypedefs) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); TypeSourceInfo *NewDI; if (auto PackTL = OldDI->getTypeLoc().getAs()) { @@ -2219,7 +2242,8 @@ // members of the current instantiations with the definitions of those // typedefs, avoiding triggering instantiation of the deduced type during // deduction. - NewDI = ExtractTypeForDeductionGuide(SemaRef).transform(NewDI); + NewDI = ExtractTypeForDeductionGuide(SemaRef, MaterializedTypedefs) + .transform(NewDI); // Resolving a wording defect, we also inherit default arguments from the // constructor. @@ -2250,10 +2274,12 @@ return NewParam; } - NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams, - ExplicitSpecifier ES, TypeSourceInfo *TInfo, - SourceLocation LocStart, SourceLocation Loc, - SourceLocation LocEnd) { + FunctionTemplateDecl * + buildDeductionGuide(TemplateParameterList *TemplateParams, + ExplicitSpecifier ES, TypeSourceInfo *TInfo, + SourceLocation LocStart, SourceLocation Loc, + SourceLocation LocEnd, + llvm::ArrayRef MaterializedTypedefs = {}) { DeclarationNameInfo Name(DeductionGuideName, Loc); ArrayRef Params = TInfo->getTypeLoc().castAs().getParams(); @@ -2267,6 +2293,8 @@ for (auto *Param : Params) Param->setDeclContext(Guide); + for (auto *TD : MaterializedTypedefs) + TD->setDeclContext(Guide); auto *GuideTemplate = FunctionTemplateDecl::Create( SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide); Index: clang/test/AST/deduction-guides.cpp =================================================================== --- /dev/null +++ clang/test/AST/deduction-guides.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only %s -ast-dump -std=c++17 | FileCheck %s + +namespace PR46111 { +template +struct S; + +template +struct HasDeductionGuide { + typedef PR46111::S STy; + HasDeductionGuide(typename STy::Child); + }; + +// This causes deduction guides to be generated for all constructors. +HasDeductionGuide() ->HasDeductionGuide; + +// The parameter to this one shouldn't be an elaborated type. +// CHECK: CXXDeductionGuideDecl {{.*}} implicit 'auto (typename STy::Child) -> HasDeductionGuide' +// CHECK: CXXDeductionGuideDecl {{.*}} implicit 'auto (HasDeductionGuide) -> HasDeductionGuide' +// CHECK: CXXDeductionGuideDecl {{.*}} 'auto () -> HasDeductionGuide' +} // namespace PR46111