https://github.com/Serosh-commits updated https://github.com/llvm/llvm-project/pull/180407
>From cf731e642abeece29ee5f397123b28a84bd2a428 Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Sun, 8 Feb 2026 17:40:06 +0530 Subject: [PATCH 1/4] [clang][sema] fix crash on builtin template ids with dependent packs (gh180307) --- clang/lib/Sema/SemaTemplate.cpp | 28 ++++++------- .../builtin_templates_invalid_parameters.cpp | 41 +++++++++++++++++++ 2 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3497ff7856eed..c54392418e25e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3406,10 +3406,22 @@ static QualType checkBuiltinTemplateIdType( Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD, ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { + TemplateParameterList *Params = BTD->getTemplateParameters(); + unsigned RequiredArgs = Params->size(); + if (Params->hasParameterPack()) { + if (Converted.size() < RequiredArgs) + return QualType(); + } else { + if (Converted.size() != RequiredArgs) + return QualType(); + } + ASTContext &Context = SemaRef.getASTContext(); switch (BTD->getBuiltinTemplateKind()) { case BTK__make_integer_seq: { + if (Converted[2].isDependent()) + return QualType(); // Specializations of __make_integer_seq<S, T, N> are treated like // S<T, 0, ..., N-1>. @@ -3423,8 +3435,6 @@ static QualType checkBuiltinTemplateIdType( } TemplateArgument NumArgsArg = Converted[2]; - if (NumArgsArg.isDependent()) - return QualType(); TemplateArgumentListInfo SyntheticTemplateArgs; // The type argument, wrapped in substitution sugar, gets reused as the @@ -3459,12 +3469,6 @@ static QualType checkBuiltinTemplateIdType( } case BTK__type_pack_element: { - // Specializations of - // __type_pack_element<Index, T_1, ..., T_N> - // are treated like T_Index. - assert(Converted.size() == 2 && - "__type_pack_element should be given an index and a parameter pack"); - TemplateArgument IndexArg = Converted[0], Ts = Converted[1]; if (IndexArg.isDependent() || Ts.isDependent()) return QualType(); @@ -3485,7 +3489,6 @@ static QualType checkBuiltinTemplateIdType( } case BTK__builtin_common_type: { - assert(Converted.size() == 4); if (llvm::any_of(Converted, [](auto &C) { return C.isDependent(); })) return QualType(); @@ -3508,8 +3511,6 @@ static QualType checkBuiltinTemplateIdType( } case BTK__hlsl_spirv_type: { - assert(Converted.size() == 4); - if (!Context.getTargetInfo().getTriple().isSPIRV()) { SemaRef.Diag(TemplateLoc, diag::err_hlsl_spirv_only) << BTD; } @@ -3537,12 +3538,7 @@ static QualType checkBuiltinTemplateIdType( return Context.getHLSLInlineSpirvType(Opcode, Size, Alignment, Operands); } case BTK__builtin_dedup_pack: { - assert(Converted.size() == 1 && "__builtin_dedup_pack should be given " - "a parameter pack"); TemplateArgument Ts = Converted[0]; - // Delay the computation until we can compute the final result. We choose - // not to remove the duplicates upfront before substitution to keep the code - // simple. if (Ts.isDependent()) return QualType(); assert(Ts.getKind() == clang::TemplateArgument::Pack); diff --git a/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp b/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp new file mode 100644 index 0000000000000..dd74bbd1d900d --- /dev/null +++ b/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// expected-error@* 2 {{template argument for non-type template parameter must be an expression}} + +using SizeT = decltype(sizeof(int)); + +// Dependent cases that previously crashed but now return QualType() gracefully. +template <SizeT... Seq> // expected-note {{template parameter is declared here}} +using gh180307 = __type_pack_element<Seq...>; + +template <typename T> +using gh180307_bis = __make_integer_seq<gh180307, T>; +// expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}} + +// Eager expansion checks: Built-in templates should expand even if the +// destination template OR the type argument is dependent, provided the size is known. +template <template <typename T, T... Ints> class Seq> +using test_make_integer_seq_eager = __make_integer_seq<Seq, int, 2>; + +template <typename T, T... Ints> struct MySeq; +using check_eager = test_make_integer_seq_eager<MySeq>; +using check_eager = MySeq<int, 0, 1>; + +template <typename T> +using test_make_integer_seq_type_dependent = __make_integer_seq<MySeq, T, 2>; +using check_type_eager = test_make_integer_seq_type_dependent<int>; +using check_type_eager = MySeq<int, 0, 1>; + +// Too many arguments tests +template <int N> struct S; // expected-note {{template parameter is declared here}} +using too_many_args = __make_integer_seq<S, int, 10, int>; +// expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}} + +// Too few arguments tests +template <SizeT Index> +using too_few_args = __type_pack_element<Index>; + +// Verify that too_few_args doesn't crash on instantiation either +// (It should just be an invalid type) +template <SizeT I> struct Wrap { + using type = too_few_args<I>; +}; >From 533718dd5cdc35aefed75eeee5f6a0dafe030069 Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Sun, 22 Feb 2026 19:07:35 +0530 Subject: [PATCH 2/4] [clang] address reviewer feedback --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaTemplate.cpp | 27 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f999c362307af..d75ca7a933e6e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6099,7 +6099,7 @@ def note_template_declared_here : Note< "%1 declared here">; def err_template_expansion_into_fixed_list : Error< "pack expansion used as argument for non-pack parameter of %select{alias " - "template|concept}0">; + "template|concept|builtin template}0">; def note_parameter_type : Note< "parameter of type %0 is declared here">; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c54392418e25e..f094fcbd51dfd 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3408,20 +3408,19 @@ static QualType checkBuiltinTemplateIdType( TemplateArgumentListInfo &TemplateArgs) { TemplateParameterList *Params = BTD->getTemplateParameters(); unsigned RequiredArgs = Params->size(); - if (Params->hasParameterPack()) { - if (Converted.size() < RequiredArgs) - return QualType(); - } else { - if (Converted.size() != RequiredArgs) - return QualType(); + + if (Converted.size() != RequiredArgs) { + // If we have a different number of arguments than parameters, it's either + // an error or we have a dependent pack expansion that hasn't been expanded + // and partitioned yet. In either case, we can't proceed with instantiation, + // so we return an empty QualType (staying dependent or signaling an error). + return QualType(); } ASTContext &Context = SemaRef.getASTContext(); switch (BTD->getBuiltinTemplateKind()) { case BTK__make_integer_seq: { - if (Converted[2].isDependent()) - return QualType(); // Specializations of __make_integer_seq<S, T, N> are treated like // S<T, 0, ..., N-1>. @@ -3435,6 +3434,9 @@ static QualType checkBuiltinTemplateIdType( } TemplateArgument NumArgsArg = Converted[2]; + if (NumArgsArg.isDependent()) + return QualType(); + TemplateArgumentListInfo SyntheticTemplateArgs; // The type argument, wrapped in substitution sugar, gets reused as the @@ -5979,11 +5981,14 @@ bool Sema::CheckTemplateArgumentList( // CWG1430/CWG2686: we have a pack expansion as an argument to an // alias template or concept, and it's not part of a parameter pack. // This can't be canonicalized, so reject it now. - if (isa<TypeAliasTemplateDecl, ConceptDecl>(Template)) { + if (isa<TypeAliasTemplateDecl, ConceptDecl, BuiltinTemplateDecl>( + Template)) { + unsigned DiagSelect = isa<ConceptDecl>(Template) ? 1 + : isa<BuiltinTemplateDecl>(Template) ? 2 + : 0; Diag(ArgLoc.getLocation(), diag::err_template_expansion_into_fixed_list) - << (isa<ConceptDecl>(Template) ? 1 : 0) - << ArgLoc.getSourceRange(); + << DiagSelect << ArgLoc.getSourceRange(); NoteTemplateParameterLocation(**Param); return true; } >From dd2bdf9176cb34a08a92e8f4d70367291d71a866 Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Sun, 1 Mar 2026 02:15:01 +0530 Subject: [PATCH 3/4] address reviewer feedbacks --- clang/lib/Sema/SemaTemplate.cpp | 33 +++++++++++-------- .../builtin_templates_invalid_parameters.cpp | 7 ++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f094fcbd51dfd..c5cb3199c0b6c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3406,19 +3406,11 @@ static QualType checkBuiltinTemplateIdType( Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD, ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { - TemplateParameterList *Params = BTD->getTemplateParameters(); - unsigned RequiredArgs = Params->size(); - - if (Converted.size() != RequiredArgs) { - // If we have a different number of arguments than parameters, it's either - // an error or we have a dependent pack expansion that hasn't been expanded - // and partitioned yet. In either case, we can't proceed with instantiation, - // so we return an empty QualType (staying dependent or signaling an error). - return QualType(); - } - ASTContext &Context = SemaRef.getASTContext(); + assert(Converted.size() == BTD->getTemplateParameters()->size() && + "Builtin template arguments do not match its parameters"); + switch (BTD->getBuiltinTemplateKind()) { case BTK__make_integer_seq: { // Specializations of __make_integer_seq<S, T, N> are treated like @@ -3437,7 +3429,6 @@ static QualType checkBuiltinTemplateIdType( if (NumArgsArg.isDependent()) return QualType(); - TemplateArgumentListInfo SyntheticTemplateArgs; // The type argument, wrapped in substitution sugar, gets reused as the // first template argument in the synthetic template argument list. @@ -3471,6 +3462,12 @@ static QualType checkBuiltinTemplateIdType( } case BTK__type_pack_element: { + // Specializations of + // __type_pack_element<Index, T_1, ..., T_N> + // are treated like T_Index. + assert(Converted.size() == 2 && + "__type_pack_element should be given an index and a parameter pack"); + TemplateArgument IndexArg = Converted[0], Ts = Converted[1]; if (IndexArg.isDependent() || Ts.isDependent()) return QualType(); @@ -3491,6 +3488,7 @@ static QualType checkBuiltinTemplateIdType( } case BTK__builtin_common_type: { + assert(Converted.size() == 4); if (llvm::any_of(Converted, [](auto &C) { return C.isDependent(); })) return QualType(); @@ -3513,6 +3511,8 @@ static QualType checkBuiltinTemplateIdType( } case BTK__hlsl_spirv_type: { + assert(Converted.size() == 4); + if (!Context.getTargetInfo().getTriple().isSPIRV()) { SemaRef.Diag(TemplateLoc, diag::err_hlsl_spirv_only) << BTD; } @@ -3540,7 +3540,12 @@ static QualType checkBuiltinTemplateIdType( return Context.getHLSLInlineSpirvType(Opcode, Size, Alignment, Operands); } case BTK__builtin_dedup_pack: { + assert(Converted.size() == 1 && "__builtin_dedup_pack should be given " + "a parameter pack"); TemplateArgument Ts = Converted[0]; + // Delay the computation until we can compute the final result. We choose + // not to remove the duplicates upfront before substitution to keep the code + // simple. if (Ts.isDependent()) return QualType(); assert(Ts.getKind() == clang::TemplateArgument::Pack); @@ -5979,8 +5984,8 @@ bool Sema::CheckTemplateArgumentList( Params->getDepth())); if (ArgIsExpansion && NonPackParameter) { // CWG1430/CWG2686: we have a pack expansion as an argument to an - // alias template or concept, and it's not part of a parameter pack. - // This can't be canonicalized, so reject it now. + // alias template, builtin template, or concept, and it's not part of + // a parameter pack. This can't be canonicalized, so reject it now. if (isa<TypeAliasTemplateDecl, ConceptDecl, BuiltinTemplateDecl>( Template)) { unsigned DiagSelect = isa<ConceptDecl>(Template) ? 1 diff --git a/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp b/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp index dd74bbd1d900d..dfd5d9191422b 100644 --- a/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp +++ b/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // expected-error@* 2 {{template argument for non-type template parameter must be an expression}} +// expected-note@* 2 {{template template argument has different template parameters than its corresponding template template parameter}} using SizeT = decltype(sizeof(int)); // Dependent cases that previously crashed but now return QualType() gracefully. template <SizeT... Seq> // expected-note {{template parameter is declared here}} -using gh180307 = __type_pack_element<Seq...>; +using gh180307 = __type_pack_element<Seq...>; // expected-error {{pack expansion used as argument for non-pack parameter of builtin template}} template <typename T> using gh180307_bis = __make_integer_seq<gh180307, T>; -// expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}} // Eager expansion checks: Built-in templates should expand even if the // destination template OR the type argument is dependent, provided the size is known. @@ -27,8 +27,7 @@ using check_type_eager = MySeq<int, 0, 1>; // Too many arguments tests template <int N> struct S; // expected-note {{template parameter is declared here}} -using too_many_args = __make_integer_seq<S, int, 10, int>; -// expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}} +using too_many_args = __make_integer_seq<S, int, 10, int>; // Too few arguments tests template <SizeT Index> >From e10816e1ce839aec92cf569e3c754aa0f9f28a04 Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Sun, 1 Mar 2026 03:38:04 +0530 Subject: [PATCH 4/4] ci fixes --- .../builtin_templates_invalid_parameters.cpp | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp b/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp index dfd5d9191422b..0546655f974b4 100644 --- a/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp +++ b/clang/test/SemaCXX/builtin_templates_invalid_parameters.cpp @@ -1,40 +1,28 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -// expected-error@* 2 {{template argument for non-type template parameter must be an expression}} -// expected-note@* 2 {{template template argument has different template parameters than its corresponding template template parameter}} +// expected-note@* 0+ {{from hidden source}} using SizeT = decltype(sizeof(int)); -// Dependent cases that previously crashed but now return QualType() gracefully. -template <SizeT... Seq> // expected-note {{template parameter is declared here}} -using gh180307 = __type_pack_element<Seq...>; // expected-error {{pack expansion used as argument for non-pack parameter of builtin template}} +// 1. Check pack expansion into non-pack parameter (The core fix) +template <SizeT... Seq> // expected-note 1+ {{template parameter is declared here}} +using error_expansion = __type_pack_element<Seq...>; +// expected-error@-1 {{pack expansion used as argument for non-pack parameter of builtin template}} -template <typename T> -using gh180307_bis = __make_integer_seq<gh180307, T>; - -// Eager expansion checks: Built-in templates should expand even if the -// destination template OR the type argument is dependent, provided the size is known. -template <template <typename T, T... Ints> class Seq> -using test_make_integer_seq_eager = __make_integer_seq<Seq, int, 2>; - -template <typename T, T... Ints> struct MySeq; -using check_eager = test_make_integer_seq_eager<MySeq>; -using check_eager = MySeq<int, 0, 1>; - -template <typename T> -using test_make_integer_seq_type_dependent = __make_integer_seq<MySeq, T, 2>; -using check_type_eager = test_make_integer_seq_type_dependent<int>; -using check_type_eager = MySeq<int, 0, 1>; - -// Too many arguments tests -template <int N> struct S; // expected-note {{template parameter is declared here}} -using too_many_args = __make_integer_seq<S, int, 10, int>; +// 2. Check Arity mismatch (Too many/few) +template <int N> struct S; // expected-note 1+ {{template parameter is declared here}} +using too_many_args = __make_integer_seq<S, int, 2, int>; +// expected-error@* {{template argument for non-type template parameter must be an expression}} +// expected-note@* {{template template argument has different template parameters}} -// Too few arguments tests -template <SizeT Index> -using too_few_args = __type_pack_element<Index>; +using too_few_args = __type_pack_element<>; +// expected-error@-1 {{too few template arguments for template '__type_pack_element'}} -// Verify that too_few_args doesn't crash on instantiation either -// (It should just be an invalid type) template <SizeT I> struct Wrap { - using type = too_few_args<I>; + using type = __type_pack_element<I>; // expected-error@* {{too few template arguments}} }; + +// Verify that the compiler survives even if the alias refers back to an invalid one +// (We expect an 'undeclared identifier' here because error_expansion failed above) +template <typename T> +using bis = __make_integer_seq<error_expansion, T>; +// expected-error@-1 {{use of undeclared identifier 'error_expansion'}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
