https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/132442
>From 9d5d42820a4998e0e3eb74f7301aa34dca55b890 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Mon, 30 May 2022 01:46:31 +0200 Subject: [PATCH] [clang] Template Specialization Resugaring - Template Type Alias This implements an additional user of the resugaring transform: the pattern of template type aliases. For more details and discussion see: https://discourse.llvm.org/t/rfc-improving-diagnostics-with-template-specialization-resugaring/64294 Differential Revision: https://reviews.llvm.org/D137199 --- clang/include/clang/Sema/Sema.h | 3 +- clang/lib/Sema/SemaCXXScopeSpec.cpp | 3 +- clang/lib/Sema/SemaCoroutine.cpp | 4 +- clang/lib/Sema/SemaDeclCXX.cpp | 6 ++- clang/lib/Sema/SemaTemplate.cpp | 43 +++++++++++-------- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +- clang/lib/Sema/TreeTransform.h | 3 +- clang/test/AST/ast-dump-template-decls.cpp | 4 +- clang/test/Sema/Resugar/resugar-types.cpp | 6 +-- 9 files changed, 44 insertions(+), 31 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 945ff5e2c2ca6..42a7bf75c3bfc 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11509,7 +11509,8 @@ class Sema final : public SemaBase { void NoteAllFoundTemplates(TemplateName Name); - QualType CheckTemplateIdType(TemplateName Template, + QualType CheckTemplateIdType(const NestedNameSpecifier *NNS, + TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 1085639dcb355..1c7dff35bb8af 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -907,7 +907,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, // We were able to resolve the template name to an actual template. // Build an appropriate nested-name-specifier. - QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateNameLoc, + TemplateArgs); if (T.isNull()) return true; diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 75364a3b2c8b5..8dffbca7463dd 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -90,7 +90,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, // Build the template-id. QualType CoroTrait = - S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args); + S.CheckTemplateIdType(nullptr, TemplateName(CoroTraits), KwLoc, Args); if (CoroTrait.isNull()) return QualType(); if (S.RequireCompleteType(KwLoc, CoroTrait, @@ -169,7 +169,7 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, // Build the template-id. QualType CoroHandleType = - S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args); + S.CheckTemplateIdType(nullptr, TemplateName(CoroHandle), Loc, Args); if (CoroHandleType.isNull()) return QualType(); if (S.RequireCompleteType(Loc, CoroHandleType, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 928bf47285490..8a9ad3271ec26 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1140,7 +1140,8 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, } // Build the template-id. - QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args); + QualType TraitTy = + S.CheckTemplateIdType(nullptr, TemplateName(TraitTD), Loc, Args); if (TraitTy.isNull()) return true; if (!S.isCompleteType(Loc, TraitTy)) { @@ -12163,7 +12164,8 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { Context.getTrivialTypeSourceInfo(Element, Loc))); - QualType T = CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args); + QualType T = + CheckTemplateIdType(nullptr, TemplateName(StdInitializerList), Loc, Args); if (T.isNull()) return QualType(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5652b4548895a..673551bd97f3e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3827,7 +3827,8 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { } } -static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, +static QualType builtinCommonTypeImpl(Sema &S, const NestedNameSpecifier *NNS, + TemplateName BaseTemplate, SourceLocation TemplateLoc, ArrayRef<TemplateArgument> Ts) { auto lookUpCommonType = [&](TemplateArgument T1, @@ -3835,7 +3836,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, // Don't bother looking for other specializations if both types are // builtins - users aren't allowed to specialize for them if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType()) - return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2}); + return builtinCommonTypeImpl(S, NNS, BaseTemplate, TemplateLoc, {T1, T2}); TemplateArgumentListInfo Args; Args.addArgument(TemplateArgumentLoc( @@ -3849,7 +3850,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); QualType BaseTemplateInst = - S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args); + S.CheckTemplateIdType(NNS, BaseTemplate, TemplateLoc, Args); if (SFINAE.hasErrorOccurred()) return QualType(); @@ -3962,8 +3963,8 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, } static QualType checkBuiltinTemplateIdType( - Sema &SemaRef, TemplateName Name, BuiltinTemplateDecl *BTD, - ArrayRef<TemplateArgument> SugaredConverted, + Sema &SemaRef, const NestedNameSpecifier *NNS, TemplateName Name, + BuiltinTemplateDecl *BTD, ArrayRef<TemplateArgument> SugaredConverted, ArrayRef<TemplateArgument> CanonicalConverted, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { ASTContext &Context = SemaRef.getASTContext(); @@ -4015,7 +4016,7 @@ static QualType checkBuiltinTemplateIdType( // The first template argument will be reused as the template decl that // our synthetic template arguments will be applied to. QualType Result = - SemaRef.CheckTemplateIdType(SugaredConverted[0].getAsTemplate(), + SemaRef.CheckTemplateIdType(NNS, SugaredConverted[0].getAsTemplate(), TemplateLoc, SyntheticTemplateArgs); return SemaRef.Context.getTemplateSpecializationType( Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted, @@ -4065,14 +4066,16 @@ static QualType checkBuiltinTemplateIdType( QualType HasNoTypeMember = SugaredConverted[2].getAsType(); ArrayRef<TemplateArgument> Ts = SugaredConverted[3].getPackAsArray(); QualType Result = HasNoTypeMember; - if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts); + if (auto CT = + builtinCommonTypeImpl(SemaRef, NNS, BaseTemplate, TemplateLoc, Ts); !CT.isNull()) { TemplateArgumentListInfo TAs; TAs.addArgument(TemplateArgumentLoc( TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo( CT, TemplateArgs[1].getLocation()))); - Result = SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs); + Result = + SemaRef.CheckTemplateIdType(NNS, HasTypeMember, TemplateLoc, TAs); } return SemaRef.Context.getTemplateSpecializationType( Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted, @@ -4220,7 +4223,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) { return { FailedCond, Description }; } -QualType Sema::CheckTemplateIdType(TemplateName Name, +QualType Sema::CheckTemplateIdType(const NestedNameSpecifier *NNS, + TemplateName Name, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { // FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias @@ -4299,9 +4303,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (!AliasTemplate->getDeclContext()->isFileContext()) SavedContext.emplace(*this, AliasTemplate->getDeclContext()); - CanonType = - SubstType(Pattern->getUnderlyingType(), TemplateArgLists, - AliasTemplate->getLocation(), AliasTemplate->getDeclName()); + QualType T = resugar(NNS, Pattern->getUnderlyingType()); + CanonType = SubstType(T, TemplateArgLists, AliasTemplate->getLocation(), + AliasTemplate->getDeclName()); if (CanonType.isNull()) { // If this was enable_if and we failed to find the nested type // within enable_if in a SFINAE context, dig out the specific @@ -4338,9 +4342,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, return QualType(); } } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { - return checkBuiltinTemplateIdType(*this, Name, BTD, CTAI.SugaredConverted, - CTAI.CanonicalConverted, TemplateLoc, - TemplateArgs); + return checkBuiltinTemplateIdType( + *this, NNS, Name, BTD, CTAI.SugaredConverted, CTAI.CanonicalConverted, + TemplateLoc, TemplateArgs); } else if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, CTAI.CanonicalConverted)) { @@ -4583,7 +4587,8 @@ TypeResult Sema::ActOnTemplateIdType( return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); } - QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs); + QualType SpecTy = CheckTemplateIdType(SS.getScopeRep(), Template, + TemplateIILoc, TemplateArgs); if (SpecTy.isNull()) return true; @@ -4664,7 +4669,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, Diag(TAT->getLocation(), diag::note_declared_at); } - QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); + QualType Result = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateLoc, + TemplateArgs); if (Result.isNull()) return TypeResult(true); @@ -11446,7 +11452,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } - QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs); + QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateIILoc, + TemplateArgs); if (T.isNull()) return true; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9c1eb3f4c88b5..5846b19a5c57b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -6816,7 +6816,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, Args.addArgument( getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc)); } - QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args); + QualType T = + CheckTemplateIdType(/*NNS=*/nullptr, TemplateName(TD), Loc, Args); // We may get a non-null type with errors, in which case // `getAsCXXRecordDecl` will return `nullptr`. For instance, this // happens when one of the template arguments is an invalid diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8250d700d0ac7..94e675383100e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -17347,7 +17347,8 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( TemplateName Template, SourceLocation TemplateNameLoc, TemplateArgumentListInfo &TemplateArgs) { - return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + return SemaRef.CheckTemplateIdType(nullptr, Template, TemplateNameLoc, + TemplateArgs); } template<typename Derived> diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index d5228d4667304..c9e66d18bc454 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -126,7 +126,7 @@ using type2 = typename C<int>::type1<void>; // CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U final // CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' -// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T +// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T final // CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int' } // namespace PR55886 @@ -138,7 +138,7 @@ template <typename... T> struct D { }; }; template struct D<float, char>::bind<int, short>; -// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))' +// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))' // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1{{$}} diff --git a/clang/test/Sema/Resugar/resugar-types.cpp b/clang/test/Sema/Resugar/resugar-types.cpp index baa3b4ed65f20..296a79a05b6be 100644 --- a/clang/test/Sema/Resugar/resugar-types.cpp +++ b/clang/test/Sema/Resugar/resugar-types.cpp @@ -88,7 +88,7 @@ template <class E> struct foo { }; using T1 = foo<Bar>::apply<char>; TEST_NOT(T1::type1); -TEST_NOT(T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases. +TEST(T1::type2); using T2 = foo<int>::apply<Bar>; TEST(T2::type1); @@ -106,7 +106,7 @@ template <typename... Cs> struct foo { }; using T1 = foo<Bar>::bind<char>; TEST_NOT(T1::type1); -TEST_NOT(T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases. +TEST(T1::type2); using T2 = foo<int>::bind<Bar>; TEST(T2::type1); @@ -148,7 +148,7 @@ template <typename... Ts> using Z = Y<Ts...>; using T1 = typename foo<Z, Bar>::template bind<int>; TEST_NOT(typename T1::type1); -TEST_NOT(typename T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases. +TEST(typename T1::type2); using T2 = typename foo<Z, int>::template bind<Bar>; TEST(typename T2::type1); _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits