mizvekov created this revision. Herald added a subscriber: jeroen.dobbelaere. Herald added a project: All. mizvekov requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
We change the template specialization of __make_integer_seq to be an alias to a synthesized template specialization type of the underlying template, making the resulting type correctly represent the template arguments used to specialize the underlying template. When performing member access on the resulting type, it's now possible to map from a Subst* node to the template argument as-written used in a regular fashion, without special casing. Depends on D133261 <https://reviews.llvm.org/D133261> Signed-off-by: Matheus Izvekov <mizve...@gmail.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D133262 Files: clang/include/clang/AST/ASTContext.h clang/include/clang/AST/DeclTemplate.h clang/lib/AST/ASTContext.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/make_integer_seq.cpp
Index: clang/test/SemaTemplate/make_integer_seq.cpp =================================================================== --- clang/test/SemaTemplate/make_integer_seq.cpp +++ clang/test/SemaTemplate/make_integer_seq.cpp @@ -5,7 +5,7 @@ using test1 = __make_integer_seq<A, int, 1>; // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:5:1, col:43> col:7 test1 '__make_integer_seq<A, int, 1>':'A<int, 0>' // CHECK-NEXT: | `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar -// CHECK-NEXT: | `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar __make_integer_seq +// CHECK-NEXT: | `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar alias __make_integer_seq // CHECK-NEXT: | |-TemplateArgument template A // CHECK-NEXT: | |-TemplateArgument type 'int' // CHECK-NEXT: | | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' @@ -13,12 +13,22 @@ // CHECK-NEXT: | | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' // CHECK-NEXT: | | |-value: Int 1 // CHECK-NEXT: | | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 -// CHECK-NEXT: | `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' -// CHECK-NEXT: | `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A' +// CHECK-NEXT: | `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A +// CHECK-NEXT: | |-TemplateArgument type 'int':'int' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar +// CHECK-NEXT: | | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 +// CHECK-NEXT: | | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} '' +// CHECK-NEXT: | | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: | |-TemplateArgument expr +// CHECK-NEXT: | | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' +// CHECK-NEXT: | | |-value: Int 0 +// CHECK-NEXT: | | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 0 +// CHECK-NEXT: | `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' +// CHECK-NEXT: | `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A' template <class B1, B1 B2> using B = __make_integer_seq<A, B1, B2>; using test2 = B<int, 1>; -// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:20:1, col:23> col:7 test2 'B<int, 1>':'A<int, 0>' +// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:30:1, col:23> col:7 test2 'B<int, 1>':'A<int, 0>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar alias B // CHECK-NEXT: |-TemplateArgument type 'int' @@ -28,7 +38,7 @@ // CHECK-NEXT: | |-value: Int 1 // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:22> 'int' 1 // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar __make_integer_seq +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar alias __make_integer_seq // CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument type 'int':'int' // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar @@ -36,10 +46,20 @@ // CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'B1' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: |-TemplateArgument expr -// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:19:64> 'int' +// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:29:64> 'int' // CHECK-NEXT: | |-value: Int 1 // CHECK-NEXT: | `-SubstNonTypeTemplateParmExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int' // CHECK-NEXT: | |-NonTypeTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <col:21, col:24> col:24 referenced 'B1' depth 0 index 1 B2 // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 1 -// CHECK-NEXT: `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' -// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A' +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A +// CHECK-NEXT: |-TemplateArgument type 'int':'int' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar +// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 +// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} '' +// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: |-TemplateArgument expr +// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int' +// CHECK-NEXT: | |-value: Int 0 +// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 0 +// CHECK-NEXT: `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' +// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A' Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -3528,7 +3528,17 @@ TemplateArgumentListInfo SyntheticTemplateArgs; // The type argument gets reused as the first template argument in the // synthetic template argument list. - SyntheticTemplateArgs.addArgument(TemplateArgs[1]); + auto *TTPD = + cast<TemplateTypeParmDecl>(BTD->getTemplateParameters()->getParam(1)); + const auto *TTP = cast<TemplateTypeParmType>( + SemaRef.Context.getTemplateTypeParmType(0, 1, false, TTPD)); + QualType OrigType = TemplateArgs[1].getArgument().getAsType(); + QualType SyntheticType = SemaRef.Context.getSubstTemplateTypeParmType( + TTP, OrigType.getCanonicalType()); + SyntheticTemplateArgs.addArgument( + TemplateArgumentLoc(TemplateArgument(SyntheticType), + SemaRef.Context.getTrivialTypeSourceInfo( + SyntheticType, TemplateArgs[1].getLocation()))); // Expand N into 0 ... N-1. for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); I < NumArgs; ++I) { @@ -3730,7 +3740,8 @@ // We might have a substituted template template parameter pack. If so, // build a template specialization type for it. if (Name.getAsSubstTemplateTemplateParmPack()) - return Context.getTemplateSpecializationType(Name, TemplateArgs); + return Context.getTemplateSpecializationType(Name, + TemplateArgs.arguments()); Diag(TemplateLoc, diag::err_template_id_not_a_type) << Name; @@ -3903,7 +3914,8 @@ // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); + return Context.getTemplateSpecializationType(Name, TemplateArgs.arguments(), + CanonType); } void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName, Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -1263,10 +1263,11 @@ assert(Ty->isTypeAlias()); llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit); - auto *AliasDecl = - cast<TypeAliasTemplateDecl>(Ty->getTemplateName().getAsTemplateDecl()) - ->getTemplatedDecl(); + const TemplateDecl *TD = Ty->getTemplateName().getAsTemplateDecl(); + if (isa<BuiltinTemplateDecl>(TD)) + return Src; + const auto *AliasDecl = cast<TypeAliasTemplateDecl>(TD)->getTemplatedDecl(); if (AliasDecl->hasAttr<NoDebugAttr>()) return Src; Index: clang/lib/AST/DeclTemplate.cpp =================================================================== --- clang/lib/AST/DeclTemplate.cpp +++ clang/lib/AST/DeclTemplate.cpp @@ -250,6 +250,23 @@ return false; } +bool TemplateDecl::isTypeAlias() const { + switch (getKind()) { + case TemplateDecl::TypeAliasTemplate: + return true; + case TemplateDecl::BuiltinTemplate: { + const auto *BT = cast<BuiltinTemplateDecl>(this); + if (BT->getBuiltinTemplateKind() == + BuiltinTemplateKind::BTK__make_integer_seq) + return true; + return false; + } + default: + return false; + }; + llvm_unreachable("unknown template kind"); +} + //===----------------------------------------------------------------------===// // RedeclarableTemplateDecl Implementation //===----------------------------------------------------------------------===// Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -4841,7 +4841,8 @@ QualType Underlying) const { assert(!Name.getAsDependentTemplateName() && "No dependent template names here!"); - QualType TST = getTemplateSpecializationType(Name, Args, Underlying); + QualType TST = + getTemplateSpecializationType(Name, Args.arguments(), Underlying); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); TemplateSpecializationTypeLoc TL = @@ -4857,14 +4858,14 @@ QualType ASTContext::getTemplateSpecializationType(TemplateName Template, - const TemplateArgumentListInfo &Args, + ArrayRef<TemplateArgumentLoc> Args, QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); SmallVector<TemplateArgument, 4> ArgVec; ArgVec.reserve(Args.size()); - for (const TemplateArgumentLoc &Arg : Args.arguments()) + for (const TemplateArgumentLoc &Arg : Args) ArgVec.push_back(Arg.getArgument()); return getTemplateSpecializationType(Template, ArgVec, Underlying); @@ -4890,8 +4891,8 @@ if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Template = QTN->getUnderlyingTemplate(); - bool IsTypeAlias = - isa_and_nonnull<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); + const auto *TD = Template.getAsTemplateDecl(); + bool IsTypeAlias = TD && TD->isTypeAlias(); QualType CanonType; if (!Underlying.isNull()) CanonType = getCanonicalType(Underlying); Index: clang/include/clang/AST/DeclTemplate.h =================================================================== --- clang/include/clang/AST/DeclTemplate.h +++ clang/include/clang/AST/DeclTemplate.h @@ -452,6 +452,8 @@ TemplatedDecl->getSourceRange().getEnd()); } + bool isTypeAlias() const; + protected: NamedDecl *TemplatedDecl; TemplateParameterList *TemplateParams; Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -1633,7 +1633,7 @@ ArrayRef<TemplateArgument> Args) const; QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgumentListInfo &Args, + ArrayRef<TemplateArgumentLoc> Args, QualType Canon = QualType()) const; TypeSourceInfo *
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits