erichkeane updated this revision to Diff 268822. erichkeane retitled this revision from "(PR46111) Desugar Elaborated types in Deduction Guides." to "(PR46111) Properly handle elaborated types in an implicit deduction guide". erichkeane edited the summary of this revision.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D80743/new/ https://reviews.llvm.org/D80743 Files: clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/AST/deduction-guides.cpp
Index: clang/test/AST/deduction-guides.cpp =================================================================== --- /dev/null +++ clang/test/AST/deduction-guides.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only %s -ast-dump -std=c++17 | FileCheck %s + +namespace PR46111 { +template <typename> +struct S; + +template <typename T> +struct HasDeductionGuide { + typedef PR46111::S<T> STy; + HasDeductionGuide(typename STy::Child); +}; + +// This causes deduction guides to be generated for all constructors. +HasDeductionGuide()->HasDeductionGuide<int>; + +template <typename T> +struct HasDeductionGuideTypeAlias { + using STy = PR46111::S<T>; + HasDeductionGuideTypeAlias(typename STy::Child); +}; + +// This causes deduction guides to be generated for all constructors. +HasDeductionGuideTypeAlias()->HasDeductionGuideTypeAlias<int>; + +// The parameter to this one shouldn't be an elaborated type. +// CHECK: CXXDeductionGuideDecl {{.*}} implicit <deduction guide for HasDeductionGuide> 'auto (typename STy::Child) -> HasDeductionGuide<T>' +// CHECK: CXXDeductionGuideDecl {{.*}} implicit <deduction guide for HasDeductionGuide> 'auto (HasDeductionGuide<T>) -> HasDeductionGuide<T>' +// CHECK: CXXDeductionGuideDecl {{.*}} <deduction guide for HasDeductionGuide> 'auto () -> HasDeductionGuide<int>' +// CHECK: CXXDeductionGuideDecl {{.*}} implicit <deduction guide for HasDeductionGuideTypeAlias> 'auto (typename STy::Child) -> HasDeductionGuideTypeAlias<T>' +// CHECK: CXXDeductionGuideDecl {{.*}} implicit <deduction guide for HasDeductionGuideTypeAlias> 'auto (HasDeductionGuideTypeAlias<T>) -> HasDeductionGuideTypeAlias<T>' +// CHECK: CXXDeductionGuideDecl {{.*}} <deduction guide for HasDeductionGuideTypeAlias> 'auto () -> HasDeductionGuideTypeAlias<int>' +} // namespace PR46111 Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5701,6 +5701,9 @@ bool NeedInstantiate = false; if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) NeedInstantiate = RD->isLocalClass(); + else if (isa<TypedefNameDecl>(D) && + isa<CXXDeductionGuideDecl>(D->getDeclContext())) + NeedInstantiate = true; else NeedInstantiate = isa<EnumDecl>(D); if (NeedInstantiate) { Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3558,6 +3558,12 @@ if (isa<EnumDecl>(D)) return nullptr; + // Materialized typedefs/type alias for implicit deduction guides may require + // instantiation. + if (isa<TypedefNameDecl>(D) && + isa<CXXDeductionGuideDecl>(D->getDeclContext())) + return nullptr; + // If we didn't find the decl, then we either have a sema bug, or we have a // forward reference to a label declaration. Return null to indicate that // we have an uninstantiated label. Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -1947,16 +1947,45 @@ /// constructor to a deduction guide. class ExtractTypeForDeductionGuide : public TreeTransform<ExtractTypeForDeductionGuide> { + llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs; + public: typedef TreeTransform<ExtractTypeForDeductionGuide> Base; - ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {} + ExtractTypeForDeductionGuide( + Sema &SemaRef, + llvm::SmallVectorImpl<TypedefNameDecl *> &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(); + TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); + TypeLocBuilder InnerTLB; + QualType Transformed = + TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); + TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(Transformed); + + TypedefNameDecl *Decl = nullptr; + + if (isa<TypeAliasDecl>(OrigDecl)) + Decl = TypeAliasDecl::Create( + Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), + OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + else { + assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef"); + Decl = TypedefDecl::Create( + Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), + OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + } + + MaterializedTypedefs.push_back(Decl); + + QualType TDTy = Context.getTypedefType(Decl); + TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy); + TypedefTL.setNameLoc(TL.getNameLoc()); + + return TDTy; } }; @@ -2041,14 +2070,16 @@ // new ones. TypeLocBuilder TLB; SmallVector<ParmVarDecl*, 8> Params; - QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args); + SmallVector<TypedefNameDecl *, 4> 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()); + CD->getEndLoc(), MaterializedTypedefs); } /// Build a deduction guide with the specified parameter types. @@ -2143,16 +2174,18 @@ return NewParam; } - QualType transformFunctionProtoType(TypeLocBuilder &TLB, - FunctionProtoTypeLoc TL, - SmallVectorImpl<ParmVarDecl*> &Params, - MultiLevelTemplateArgumentList &Args) { + QualType transformFunctionProtoType( + TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, + SmallVectorImpl<ParmVarDecl *> &Params, + MultiLevelTemplateArgumentList &Args, + SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) { SmallVector<QualType, 4> 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 +2227,9 @@ return Result; } - ParmVarDecl * - transformFunctionTypeParam(ParmVarDecl *OldParam, - MultiLevelTemplateArgumentList &Args) { + ParmVarDecl *transformFunctionTypeParam( + ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args, + llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); TypeSourceInfo *NewDI; if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { @@ -2219,7 +2252,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 +2284,11 @@ 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<TypedefNameDecl *> MaterializedTypedefs = {}) { DeclarationNameInfo Name(DeductionGuideName, Loc); ArrayRef<ParmVarDecl *> Params = TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(); @@ -2267,6 +2302,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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits