diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -122,6 +122,9 @@ - Clang will now no longer treat a C 'overloadable' function without a prototype as a variadic function with the attribute. This should make further diagnostics more clear. +- Fixes to builtin template emulation of regular templates. + `Issue 42102 <https://github.com/llvm/llvm-project/issues/42102>`_ + `Issue 51928 <https://github.com/llvm/llvm-project/issues/51928>`_ Improvements to Clang's diagnostics diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1636,7 +1636,7 @@ ArrayRef<TemplateArgument> Args) const; QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgumentListInfo &Args, + ArrayRef<TemplateArgumentLoc> Args, QualType Canon = QualType()) const; TypeSourceInfo * diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -440,6 +440,9 @@ /// Get the underlying, templated declaration. NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } + // Should a specialization behave like an alias for another type. + bool isTypeAlias() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4848,7 +4848,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 = @@ -4864,14 +4865,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); @@ -4897,8 +4898,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); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -250,6 +250,16 @@ return false; } +bool TemplateDecl::isTypeAlias() const { + switch (getKind()) { + case TemplateDecl::TypeAliasTemplate: + case TemplateDecl::BuiltinTemplate: + return true; + default: + return false; + }; +} + //===----------------------------------------------------------------------===// // RedeclarableTemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/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; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3501,45 +3501,70 @@ SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { ASTContext &Context = SemaRef.getASTContext(); + + TemplateParameterList *TPL = BTD->getTemplateParameters(); + + // Wrap the type in substitution sugar. + auto getSubstType = [&](unsigned IndexReplaced, QualType Replacement) { + QualType TTP = SemaRef.Context.getTemplateTypeParmType( + 0, IndexReplaced, false, + cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced))); + return SemaRef.Context.getSubstTemplateTypeParmType( + cast<TemplateTypeParmType>(TTP), Replacement.getCanonicalType()); + }; + switch (BTD->getBuiltinTemplateKind()) { case BTK__make_integer_seq: { // Specializations of __make_integer_seq<S, T, N> are treated like // S<T, 0, ..., N-1>. + QualType OrigType = Converted[1].getAsType(); // C++14 [inteseq.intseq]p1: // T shall be an integer type. - if (!Converted[1].getAsType()->isIntegralType(Context)) { + if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) { SemaRef.Diag(TemplateArgs[1].getLocation(), diag::err_integer_sequence_integral_element_type); return QualType(); } - // C++14 [inteseq.make]p1: - // If N is negative the program is ill-formed. TemplateArgument NumArgsArg = Converted[2]; - llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); - if (NumArgs < 0) { + if (NumArgsArg.isDependent()) + return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD), + Converted); + + TemplateArgumentListInfo SyntheticTemplateArgs; + // The type argument, wrapped in substitution sugar, gets reused as the + // first template argument in the synthetic template argument list. + QualType SyntheticType = getSubstType(1, OrigType); + SyntheticTemplateArgs.addArgument( + TemplateArgumentLoc(TemplateArgument(SyntheticType), + SemaRef.Context.getTrivialTypeSourceInfo( + SyntheticType, TemplateArgs[1].getLocation()))); + + if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) { + // Expand N into 0 ... N-1. + for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); + I < NumArgs; ++I) { + TemplateArgument TA(Context, I, SyntheticType); + SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc( + TA, SyntheticType, TemplateArgs[2].getLocation())); + } + } else { + // C++14 [inteseq.make]p1: + // If N is negative the program is ill-formed. SemaRef.Diag(TemplateArgs[2].getLocation(), diag::err_integer_sequence_negative_length); return QualType(); } - QualType ArgTy = NumArgsArg.getIntegralType(); - TemplateArgumentListInfo SyntheticTemplateArgs; - // The type argument gets reused as the first template argument in the - // synthetic template argument list. - SyntheticTemplateArgs.addArgument(TemplateArgs[1]); - // Expand N into 0 ... N-1. - for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); - I < NumArgs; ++I) { - TemplateArgument TA(Context, I, ArgTy); - SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc( - TA, ArgTy, TemplateArgs[2].getLocation())); - } + // Wrap the template in substitution sugar. + TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm( + cast<TemplateTemplateParmDecl>(TPL->getParam(0)), + Converted[0].getAsTemplate()); + // The first template argument will be reused as the template decl that // our synthetic template arguments will be applied to. - return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(), - TemplateLoc, SyntheticTemplateArgs); + return SemaRef.CheckTemplateIdType(TN, TemplateLoc, SyntheticTemplateArgs); } case BTK__type_pack_element: @@ -3549,11 +3574,15 @@ assert(Converted.size() == 2 && "__type_pack_element should be given an index and a parameter pack"); - // If the Index is out of bounds, the program is ill-formed. TemplateArgument IndexArg = Converted[0], Ts = Converted[1]; + if (IndexArg.isDependent() || Ts.isDependent()) + return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD), + Converted); + llvm::APSInt Index = IndexArg.getAsIntegral(); assert(Index >= 0 && "the index used with __type_pack_element should be of " "type std::size_t, and hence be non-negative"); + // If the Index is out of bounds, the program is ill-formed. if (Index >= Ts.pack_size()) { SemaRef.Diag(TemplateArgs[0].getLocation(), diag::err_type_pack_element_out_of_bounds); @@ -3562,7 +3591,7 @@ // We simply return the type at index `Index`. auto Nth = std::next(Ts.pack_begin(), Index.getExtValue()); - return Nth->getAsType(); + return getSubstType(1, Nth->getAsType()); } llvm_unreachable("unexpected BuiltinTemplateDecl!"); } @@ -3730,7 +3759,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; @@ -3808,6 +3838,9 @@ return QualType(); } + } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { + CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc, + TemplateArgs); } else if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, Converted)) { @@ -3857,8 +3890,8 @@ break; } } - } else if (ClassTemplateDecl *ClassTemplate - = dyn_cast<ClassTemplateDecl>(Template)) { + } else if (ClassTemplateDecl *ClassTemplate = + dyn_cast<ClassTemplateDecl>(Template)) { // Find the class template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; @@ -3895,15 +3928,15 @@ CanonType = Context.getTypeDeclType(Decl); assert(isa<RecordType>(CanonType) && "type of non-dependent specialization is not a RecordType"); - } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { - CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc, - TemplateArgs); + } else { + llvm_unreachable("Unhandled template kind"); } // 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, diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -563,6 +563,12 @@ // FIXME: Try to preserve type sugar here, which is hard // because of the unresolved template arguments. const auto *TP = UP.getCanonicalType()->castAs<TemplateSpecializationType>(); + TemplateName TNP = TP->getTemplateName(); + + // If the parameter is an alias template, there is nothing to deduce. + if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias()) + return Sema::TDK_Success; + ArrayRef<TemplateArgument> PResolved = TP->template_arguments(); QualType UA = A; @@ -574,10 +580,15 @@ // FIXME: Should not lose sugar here. if (const auto *SA = dyn_cast<TemplateSpecializationType>(UA.getCanonicalType())) { + TemplateName TNA = SA->getTemplateName(); + + // If the argument is an alias template, there is nothing to deduce. + if (const auto *TD = TNA.getAsTemplateDecl(); TD && TD->isTypeAlias()) + return Sema::TDK_Success; + // Perform template argument deduction for the template name. if (auto Result = - DeduceTemplateArguments(S, TemplateParams, TP->getTemplateName(), - SA->getTemplateName(), Info, Deduced)) + DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info, Deduced)) return Result; // Perform template argument deduction on each template // argument. Ignore any missing/extra arguments, since they could be diff --git a/clang/test/SemaTemplate/make_integer_seq.cpp b/clang/test/SemaTemplate/make_integer_seq.cpp --- a/clang/test/SemaTemplate/make_integer_seq.cpp +++ b/clang/test/SemaTemplate/make_integer_seq.cpp @@ -4,21 +4,31 @@ 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: | |-TemplateArgument template A -// CHECK-NEXT: | |-TemplateArgument type 'int' -// 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 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: `-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 alias __make_integer_seq +// CHECK-NEXT: |-TemplateArgument template A +// CHECK-NEXT: |-TemplateArgument type 'int' +// 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 1 +// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 +// 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':'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,61 +46,93 @@ // 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':'int' 0 +// CHECK-NEXT: `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' +// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A' template <template <class T, T...> class S, class T, int N> struct C { using test3 = __make_integer_seq<S, T, N>; -// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:48:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<S, T, N>' +// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:68:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<type-parameter-0-1, N>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' dependent __make_integer_seq +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias __make_integer_seq // CHECK-NEXT: |-TemplateArgument template S // CHECK-NEXT: |-TemplateArgument type 'T' // CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1 // CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T' -// CHECK-NEXT: `-TemplateArgument expr -// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent> -// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' +// CHECK-NEXT: |-TemplateArgument expr +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent> +// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<type-parameter-0-1, N>' dependent __make_integer_seq +// CHECK-NEXT: |-TemplateArgument template +// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-1' +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1 +// CHECK-NEXT: `-TemplateArgument expr +// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent> +// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' using test4 = __make_integer_seq<A, T, 1>; -// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:60:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, T, 1>' +// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:87:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, type-parameter-0-1, 1>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' dependent __make_integer_seq +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias __make_integer_seq // CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument type 'T' // CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1 // CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T' -// CHECK-NEXT: `-TemplateArgument expr -// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent> -// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 +// CHECK-NEXT: |-TemplateArgument expr +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent> +// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, type-parameter-0-1, 1>' dependent __make_integer_seq +// CHECK-NEXT: |-TemplateArgument template A +// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-1' +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1 +// CHECK-NEXT: `-TemplateArgument expr +// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent> +// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1 using test5 = __make_integer_seq<A, int, N>; -// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:72:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>' +// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:106:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent __make_integer_seq +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias __make_integer_seq // CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' -// CHECK-NEXT: `-TemplateArgument expr -// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' +// CHECK-NEXT: |-TemplateArgument expr +// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent __make_integer_seq +// CHECK-NEXT: |-TemplateArgument template A +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: `-TemplateArgument expr +// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' }; -template <class T, class S> struct D; // expected-note {{template is declared here}} +// expected-no-diagnostics + +template <class T, class S> struct D; template <class T> struct D<T, __make_integer_seq<A, int, sizeof(T)>> {}; -template struct D<char, A<int, 0>>; // expected-error {{explicit instantiation of undefined template}} +template struct D<char, A<int, 0>>; -template <class T, class S> struct E; // expected-note {{template is declared here}} +template <class T, class S> struct E; template <class T> struct E<T, __make_integer_seq<A, T, 2>> {}; -template struct E<short, A<short, 0, 1>>; // expected-error {{explicit instantiation of undefined template}} +template struct E<short, A<short, 0, 1>>; -template <template <class A1, A1... A2> class T, class S> struct F; // expected-note {{template is declared here}} +template <template <class A1, A1... A2> class T, class S> struct F; template <template <class A1, A1... A2> class T> struct F<T, __make_integer_seq<T, long, 3>> {}; -template struct F<A, A<long, 0, 1, 2>>; // expected-error {{explicit instantiation of undefined template}} +template struct F<A, A<long, 0, 1, 2>>; template <class T> struct G; template <class T> struct G<__make_integer_seq<A, T, 1>> {}; @@ -99,5 +141,5 @@ template <int S, class = __make_integer_seq<A, int, S>> struct H; template <int S, int... Is> struct H<S, A<int, Is...>> { }; -template <int S> void h(H<S>); // expected-note {{could not match '__make_integer_seq' against 'A'}} -void test_h() { h(H<5>{}); } // expected-error {{no matching function for call to 'h'}} +template <int S> void h(H<S>); +void test_h() { h(H<5>{}); } diff --git a/clang/test/SemaTemplate/type_pack_element.cpp b/clang/test/SemaTemplate/type_pack_element.cpp --- a/clang/test/SemaTemplate/type_pack_element.cpp +++ b/clang/test/SemaTemplate/type_pack_element.cpp @@ -3,7 +3,7 @@ using test1 = __type_pack_element<0, int>; // CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <<stdin>:3:1, col:41> col:7 test1 '__type_pack_element<0, int>':'int' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, int>' sugar -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, int>' sugar __type_pack_element +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, int>' sugar alias __type_pack_element // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:35> 'unsigned long' // CHECK-NEXT: | |-value: Int 0 @@ -11,53 +11,79 @@ // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:35> 'int' 0 // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' -// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} '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' template<int N, class ...Ts> struct A { using test2 = __type_pack_element<N, Ts...>; -// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:17:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, Ts...>' +// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:20:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, type-parameter-0-1...>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' dependent __type_pack_element +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias __type_pack_element // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast> // CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' -// CHECK-NEXT: `-TemplateArgument type 'Ts...' -// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent -// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack -// CHECK-NEXT: `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts' +// CHECK-NEXT: |-TemplateArgument type 'Ts...' +// CHECK-NEXT: | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack +// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts' +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, type-parameter-0-1...>' dependent __type_pack_element +// CHECK-NEXT: |-TemplateArgument expr +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast> +// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' +// CHECK-NEXT: `-TemplateArgument pack +// CHECK-NEXT: `-TemplateArgument type 'type-parameter-0-1...' +// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent +// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack using test3 = __type_pack_element<0, Ts...>; -// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:29:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, Ts...>' +// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:40:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, type-parameter-0-1...>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' dependent __type_pack_element +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias __type_pack_element // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' // CHECK-NEXT: | |-value: Int 0 // CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast> // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:37> 'int' 0 -// CHECK-NEXT: `-TemplateArgument type 'Ts...' -// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent -// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack -// CHECK-NEXT: `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts' +// CHECK-NEXT: |-TemplateArgument type 'Ts...' +// CHECK-NEXT: | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack +// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts' +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, type-parameter-0-1...>' dependent __type_pack_element +// CHECK-NEXT: |-TemplateArgument integral 0 +// CHECK-NEXT: `-TemplateArgument pack +// CHECK-NEXT: `-TemplateArgument type 'type-parameter-0-1...' +// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent +// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack using test4 = __type_pack_element<N, int>; -// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:43:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>' +// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:60:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent __type_pack_element +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias __type_pack_element // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast> // CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' -// CHECK-NEXT: `-TemplateArgument type 'int' -// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent __type_pack_element +// CHECK-NEXT: |-TemplateArgument expr +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast> +// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int' +// CHECK-NEXT: `-TemplateArgument pack +// CHECK-NEXT: `-TemplateArgument type 'int' +// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' }; -template <class T, class S> struct B; // expected-note {{template is declared here}} +// expected-no-diagnostics + +template <class T, class S> struct B; template <class T> struct B<T, __type_pack_element<sizeof(T), void, long>> {}; -template struct B<char, long>; // expected-error {{explicit instantiation of undefined template}} +template struct B<char, long>; -template <class T, class S> struct C; // expected-note {{template is declared here}} +template <class T, class S> struct C; template <class T> struct C<T, __type_pack_element<0, T, short>> {}; -template struct C<int, int>; // expected-error {{explicit instantiation of undefined template}} +template struct C<int, int>; template <class T> struct D; template <class T, class U> struct D<__type_pack_element<0, T, U>> {};