Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Tue, 18 Apr 2023, Jason Merrill wrote: > On 4/11/23 10:21, Patrick Palka wrote: > > On Thu, 26 Jan 2023, Jason Merrill wrote: > > > > > On 1/25/23 15:35, Patrick Palka wrote: > > > > On Tue, 17 Jan 2023, Jason Merrill wrote: > > > > > > > > > On 1/9/23 14:25, Patrick Palka via Gcc-patches wrote: > > > > > > On Mon, 9 Jan 2023, Patrick Palka wrote: > > > > > > > > > > > > > On Wed, 5 Oct 2022, Patrick Palka wrote: > > > > > > > > > > > > > > > On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > > > > > > > > > > > > > > > > > This adds a new built-in to replace the recursive class > > > > > > > > > template > > > > > > > > > instantiations done by traits such as std::tuple_element and > > > > > > > > > std::variant_alternative. The purpose is to select the Nth > > > > > > > > > type > > > > > > > > > from a > > > > > > > > > list of types, e.g. __builtin_type_pack_element(1, char, int, > > > > > > > > > float) > > > > > > > > > is > > > > > > > > > int. > > > > > > > > > > > > > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 > > > > > > > > > types...>> > > > > > > > > > the compilation time is reduced by more than 90% and the > > > > > > > > > memory > > > > > > > > > used > > > > > > > > > by > > > > > > > > > the compiler is reduced by 97%. In realistic examples the > > > > > > > > > gains > > > > > > > > > will > > > > > > > > > be > > > > > > > > > much smaller, but still relevant. > > > > > > > > > > > > > > > > > > Clang has a similar built-in, __type_pack_element, > > > > > > > > > but > > > > > > > > > that's > > > > > > > > > a > > > > > > > > > "magic template" built-in using <> syntax, which GCC doesn't > > > > > > > > > support. > > > > > > > > > So > > > > > > > > > this provides an equivalent feature, but as a built-in > > > > > > > > > function > > > > > > > > > using > > > > > > > > > parens instead of <>. I don't really like the name "type pack > > > > > > > > > element" > > > > > > > > > (it gives you an element from a pack of types) but the > > > > > > > > > semi-consistency > > > > > > > > > with Clang seems like a reasonable argument in favour of > > > > > > > > > keeping > > > > > > > > > the > > > > > > > > > name. I'd be open to alternative names though, e.g. > > > > > > > > > __builtin_nth_type > > > > > > > > > or __builtin_type_at_index. > > > > > > > > > > > > > > > > Rather than giving the trait a different name from > > > > > > > > __type_pack_element, > > > > > > > > I wonder if we could just special case cp_parser_trait to expect > > > > > > > > <> > > > > > > > > instead of parens for this trait? > > > > > > > > > > > > > > > > Btw the frontend recently got a generic TRAIT_TYPE tree code, > > > > > > > > which > > > > > > > > gets > > > > > > > > rid of much of the boilerplate of adding a new type-yielding > > > > > > > > built-in > > > > > > > > trait, see e.g. cp-trait.def. > > > > > > > > > > > > > > Here's a tested patch based on Jonathan's original patch that > > > > > > > implements > > > > > > > the built-in in terms of TRAIT_TYPE, names it __type_pack_element > > > > > > > instead of __builtin_type_pack_element, and treats invocations of > > > > > > > it > > > > > > > like a template-id instead of a call (to match Clang). > > > > > > > > > > > > > > -- >8 -- > > > > > > > > > > > > > > Subject: [PATCH] c++: Define built-in for std::tuple_element > > > > > > > [PR100157] > > > > > > > > > > > > > > This adds a new built-in to replace the recursive class template > > > > > > > instantiations done by traits such as std::tuple_element and > > > > > > > std::variant_alternative. The purpose is to select the Nth type > > > > > > > from > > > > > > > a > > > > > > > list of types, e.g. __type_pack_element<1, char, int, float> is > > > > > > > int. > > > > > > > We implement it as a special kind of TRAIT_TYPE. > > > > > > > > > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 > > > > > > > types...>> > > > > > > > the compilation time is reduced by more than 90% and the memory > > > > > > > used > > > > > > > by > > > > > > > the compiler is reduced by 97%. In realistic examples the gains > > > > > > > will > > > > > > > be > > > > > > > much smaller, but still relevant. > > > > > > > > > > > > > > Unlike the other built-in traits, __type_pack_element uses > > > > > > > template-id > > > > > > > syntax instead of call syntax and is SFINAE-enabled, matching > > > > > > > Clang's > > > > > > > implementation. And like the other built-in traits, it's not > > > > > > > mangleable > > > > > > > so we can't use it directly in function signatures. > > > > > > > > > > > > > > Some caveats: > > > > > > > > > > > > > > * Clang's version of the built-in seems to act like a "magic > > > > > > > template" > > > > > > >that can e.g. be used as a template template argument. For > > > > > > > simplicity > > > > > > >we implement it in a more ad-hoc way. > > > > > > > * Our parsing of the
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On 4/11/23 10:21, Patrick Palka wrote: On Thu, 26 Jan 2023, Jason Merrill wrote: On 1/25/23 15:35, Patrick Palka wrote: On Tue, 17 Jan 2023, Jason Merrill wrote: On 1/9/23 14:25, Patrick Palka via Gcc-patches wrote: On Mon, 9 Jan 2023, Patrick Palka wrote: On Wed, 5 Oct 2022, Patrick Palka wrote: On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __builtin_type_pack_element(1, char, int, float) is int. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Clang has a similar built-in, __type_pack_element, but that's a "magic template" built-in using <> syntax, which GCC doesn't support. So this provides an equivalent feature, but as a built-in function using parens instead of <>. I don't really like the name "type pack element" (it gives you an element from a pack of types) but the semi-consistency with Clang seems like a reasonable argument in favour of keeping the name. I'd be open to alternative names though, e.g. __builtin_nth_type or __builtin_type_at_index. Rather than giving the trait a different name from __type_pack_element, I wonder if we could just special case cp_parser_trait to expect <> instead of parens for this trait? Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets rid of much of the boilerplate of adding a new type-yielding built-in trait, see e.g. cp-trait.def. Here's a tested patch based on Jonathan's original patch that implements the built-in in terms of TRAIT_TYPE, names it __type_pack_element instead of __builtin_type_pack_element, and treats invocations of it like a template-id instead of a call (to match Clang). -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. Some caveats: * Clang's version of the built-in seems to act like a "magic template" that can e.g. be used as a template template argument. For simplicity we implement it in a more ad-hoc way. * Our parsing of the <>'s in __type_pack_element<...> is currently rudimentary and doesn't try to disambiguate a trailing >> vs > > as cp_parser_enclosed_template_argument_list does. Hmm, this latter caveat turns out to be inconvenient (for code such as type_pack_element3.C) and admits an easy workaround inspired by what cp_parser_enclosed_template_argument_list does. v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of CPTK_TYPE_PACK_ELEMENT). Why not use cp_parser_enclosed_template_argument_list directly? If we used cp_parser_enclosed_template_argument_list we would then need to convert the returned TREE_VEC into a TREE_LIST and also diagnose argument kind mismatches (i.e. verify the first argument is an expression and the rest are types). It seemed like more complexity overall then just duplicating the >> splitting logic, but I can do that if you prefer? I think I would prefer that, parser stuff can be pretty subtle. Instead of turning the TREE_VEC into a TREE_LIST, we could handle TREE_VEC as a trait operand? Sorry for the late follow up... Here's an updated patch that uses cp_parser_enclosed_template_argument_list instead of copying the parsing logic from there. I put off handling TREE_VEC as a trait operand for now. We could convert all variadic traits to use TREE_VEC instead of TREE_LIST at once in a followup patch. Bootstrapped and regtested on x86_64-pc-linux-gnu, also tested against libc++'s tuple/variant impl for good measure (which uses __type_pack_element when available). -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Thu, 26 Jan 2023, Jason Merrill wrote: > On 1/25/23 15:35, Patrick Palka wrote: > > On Tue, 17 Jan 2023, Jason Merrill wrote: > > > > > On 1/9/23 14:25, Patrick Palka via Gcc-patches wrote: > > > > On Mon, 9 Jan 2023, Patrick Palka wrote: > > > > > > > > > On Wed, 5 Oct 2022, Patrick Palka wrote: > > > > > > > > > > > On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > > > > > > > > > > > > > This adds a new built-in to replace the recursive class template > > > > > > > instantiations done by traits such as std::tuple_element and > > > > > > > std::variant_alternative. The purpose is to select the Nth type > > > > > > > from a > > > > > > > list of types, e.g. __builtin_type_pack_element(1, char, int, > > > > > > > float) > > > > > > > is > > > > > > > int. > > > > > > > > > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 > > > > > > > types...>> > > > > > > > the compilation time is reduced by more than 90% and the memory > > > > > > > used > > > > > > > by > > > > > > > the compiler is reduced by 97%. In realistic examples the gains > > > > > > > will > > > > > > > be > > > > > > > much smaller, but still relevant. > > > > > > > > > > > > > > Clang has a similar built-in, __type_pack_element, but > > > > > > > that's > > > > > > > a > > > > > > > "magic template" built-in using <> syntax, which GCC doesn't > > > > > > > support. > > > > > > > So > > > > > > > this provides an equivalent feature, but as a built-in function > > > > > > > using > > > > > > > parens instead of <>. I don't really like the name "type pack > > > > > > > element" > > > > > > > (it gives you an element from a pack of types) but the > > > > > > > semi-consistency > > > > > > > with Clang seems like a reasonable argument in favour of keeping > > > > > > > the > > > > > > > name. I'd be open to alternative names though, e.g. > > > > > > > __builtin_nth_type > > > > > > > or __builtin_type_at_index. > > > > > > > > > > > > Rather than giving the trait a different name from > > > > > > __type_pack_element, > > > > > > I wonder if we could just special case cp_parser_trait to expect <> > > > > > > instead of parens for this trait? > > > > > > > > > > > > Btw the frontend recently got a generic TRAIT_TYPE tree code, which > > > > > > gets > > > > > > rid of much of the boilerplate of adding a new type-yielding > > > > > > built-in > > > > > > trait, see e.g. cp-trait.def. > > > > > > > > > > Here's a tested patch based on Jonathan's original patch that > > > > > implements > > > > > the built-in in terms of TRAIT_TYPE, names it __type_pack_element > > > > > instead of __builtin_type_pack_element, and treats invocations of it > > > > > like a template-id instead of a call (to match Clang). > > > > > > > > > > -- >8 -- > > > > > > > > > > Subject: [PATCH] c++: Define built-in for std::tuple_element > > > > > [PR100157] > > > > > > > > > > This adds a new built-in to replace the recursive class template > > > > > instantiations done by traits such as std::tuple_element and > > > > > std::variant_alternative. The purpose is to select the Nth type from > > > > > a > > > > > list of types, e.g. __type_pack_element<1, char, int, float> is int. > > > > > We implement it as a special kind of TRAIT_TYPE. > > > > > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > > > > the compilation time is reduced by more than 90% and the memory used > > > > > by > > > > > the compiler is reduced by 97%. In realistic examples the gains will > > > > > be > > > > > much smaller, but still relevant. > > > > > > > > > > Unlike the other built-in traits, __type_pack_element uses template-id > > > > > syntax instead of call syntax and is SFINAE-enabled, matching Clang's > > > > > implementation. And like the other built-in traits, it's not > > > > > mangleable > > > > > so we can't use it directly in function signatures. > > > > > > > > > > Some caveats: > > > > > > > > > > * Clang's version of the built-in seems to act like a "magic > > > > > template" > > > > > that can e.g. be used as a template template argument. For > > > > > simplicity > > > > > we implement it in a more ad-hoc way. > > > > > * Our parsing of the <>'s in __type_pack_element<...> is currently > > > > > rudimentary and doesn't try to disambiguate a trailing >> vs > > > > > > > as cp_parser_enclosed_template_argument_list does. > > > > > > > > Hmm, this latter caveat turns out to be inconvenient (for code such as > > > > type_pack_element3.C) and admits an easy workaround inspired by what > > > > cp_parser_enclosed_template_argument_list does. > > > > > > > > v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. > > > > Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of > > > > CPTK_TYPE_PACK_ELEMENT). > > > > > > Why not use cp_parser_enclosed_template_argument_list directly? > > > > If we used cp_parser_enclosed_template_argum
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On 1/25/23 15:35, Patrick Palka wrote: On Tue, 17 Jan 2023, Jason Merrill wrote: On 1/9/23 14:25, Patrick Palka via Gcc-patches wrote: On Mon, 9 Jan 2023, Patrick Palka wrote: On Wed, 5 Oct 2022, Patrick Palka wrote: On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __builtin_type_pack_element(1, char, int, float) is int. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Clang has a similar built-in, __type_pack_element, but that's a "magic template" built-in using <> syntax, which GCC doesn't support. So this provides an equivalent feature, but as a built-in function using parens instead of <>. I don't really like the name "type pack element" (it gives you an element from a pack of types) but the semi-consistency with Clang seems like a reasonable argument in favour of keeping the name. I'd be open to alternative names though, e.g. __builtin_nth_type or __builtin_type_at_index. Rather than giving the trait a different name from __type_pack_element, I wonder if we could just special case cp_parser_trait to expect <> instead of parens for this trait? Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets rid of much of the boilerplate of adding a new type-yielding built-in trait, see e.g. cp-trait.def. Here's a tested patch based on Jonathan's original patch that implements the built-in in terms of TRAIT_TYPE, names it __type_pack_element instead of __builtin_type_pack_element, and treats invocations of it like a template-id instead of a call (to match Clang). -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. Some caveats: * Clang's version of the built-in seems to act like a "magic template" that can e.g. be used as a template template argument. For simplicity we implement it in a more ad-hoc way. * Our parsing of the <>'s in __type_pack_element<...> is currently rudimentary and doesn't try to disambiguate a trailing >> vs > > as cp_parser_enclosed_template_argument_list does. Hmm, this latter caveat turns out to be inconvenient (for code such as type_pack_element3.C) and admits an easy workaround inspired by what cp_parser_enclosed_template_argument_list does. v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of CPTK_TYPE_PACK_ELEMENT). Why not use cp_parser_enclosed_template_argument_list directly? If we used cp_parser_enclosed_template_argument_list we would then need to convert the returned TREE_VEC into a TREE_LIST and also diagnose argument kind mismatches (i.e. verify the first argument is an expression and the rest are types). It seemed like more complexity overall then just duplicating the >> splitting logic, but I can do that if you prefer? I think I would prefer that, parser stuff can be pretty subtle. Instead of turning the TREE_VEC into a TREE_LIST, we could handle TREE_VEC as a trait operand? -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Tue, 17 Jan 2023, Jason Merrill wrote: > On 1/9/23 14:25, Patrick Palka via Gcc-patches wrote: > > On Mon, 9 Jan 2023, Patrick Palka wrote: > > > > > On Wed, 5 Oct 2022, Patrick Palka wrote: > > > > > > > On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > > > > > > > > > This adds a new built-in to replace the recursive class template > > > > > instantiations done by traits such as std::tuple_element and > > > > > std::variant_alternative. The purpose is to select the Nth type from a > > > > > list of types, e.g. __builtin_type_pack_element(1, char, int, float) > > > > > is > > > > > int. > > > > > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > > > > the compilation time is reduced by more than 90% and the memory used > > > > > by > > > > > the compiler is reduced by 97%. In realistic examples the gains will > > > > > be > > > > > much smaller, but still relevant. > > > > > > > > > > Clang has a similar built-in, __type_pack_element, but that's > > > > > a > > > > > "magic template" built-in using <> syntax, which GCC doesn't support. > > > > > So > > > > > this provides an equivalent feature, but as a built-in function using > > > > > parens instead of <>. I don't really like the name "type pack element" > > > > > (it gives you an element from a pack of types) but the > > > > > semi-consistency > > > > > with Clang seems like a reasonable argument in favour of keeping the > > > > > name. I'd be open to alternative names though, e.g. __builtin_nth_type > > > > > or __builtin_type_at_index. > > > > > > > > Rather than giving the trait a different name from __type_pack_element, > > > > I wonder if we could just special case cp_parser_trait to expect <> > > > > instead of parens for this trait? > > > > > > > > Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets > > > > rid of much of the boilerplate of adding a new type-yielding built-in > > > > trait, see e.g. cp-trait.def. > > > > > > Here's a tested patch based on Jonathan's original patch that implements > > > the built-in in terms of TRAIT_TYPE, names it __type_pack_element > > > instead of __builtin_type_pack_element, and treats invocations of it > > > like a template-id instead of a call (to match Clang). > > > > > > -- >8 -- > > > > > > Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] > > > > > > This adds a new built-in to replace the recursive class template > > > instantiations done by traits such as std::tuple_element and > > > std::variant_alternative. The purpose is to select the Nth type from a > > > list of types, e.g. __type_pack_element<1, char, int, float> is int. > > > We implement it as a special kind of TRAIT_TYPE. > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > > the compilation time is reduced by more than 90% and the memory used by > > > the compiler is reduced by 97%. In realistic examples the gains will be > > > much smaller, but still relevant. > > > > > > Unlike the other built-in traits, __type_pack_element uses template-id > > > syntax instead of call syntax and is SFINAE-enabled, matching Clang's > > > implementation. And like the other built-in traits, it's not mangleable > > > so we can't use it directly in function signatures. > > > > > > Some caveats: > > > > > >* Clang's version of the built-in seems to act like a "magic template" > > > that can e.g. be used as a template template argument. For > > > simplicity > > > we implement it in a more ad-hoc way. > > >* Our parsing of the <>'s in __type_pack_element<...> is currently > > > rudimentary and doesn't try to disambiguate a trailing >> vs > > > > > as cp_parser_enclosed_template_argument_list does. > > > > Hmm, this latter caveat turns out to be inconvenient (for code such as > > type_pack_element3.C) and admits an easy workaround inspired by what > > cp_parser_enclosed_template_argument_list does. > > > > v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. > > Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of > > CPTK_TYPE_PACK_ELEMENT). > > Why not use cp_parser_enclosed_template_argument_list directly? If we used cp_parser_enclosed_template_argument_list we would then need to convert the returned TREE_VEC into a TREE_LIST and also diagnose argument kind mismatches (i.e. verify the first argument is an expression and the rest are types). It seemed like more complexity overall then just duplicating the >> splitting logic, but I can do that if you prefer? > > > -- >8 -- > > > > Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] > > > > This adds a new built-in to replace the recursive class template > > instantiations done by traits such as std::tuple_element and > > std::variant_alternative. The purpose is to select the Nth type from a > > list of types, e.g. __type_pack_element<1, char, int, float> is int. > > We
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On 1/9/23 14:25, Patrick Palka via Gcc-patches wrote: On Mon, 9 Jan 2023, Patrick Palka wrote: On Wed, 5 Oct 2022, Patrick Palka wrote: On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __builtin_type_pack_element(1, char, int, float) is int. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Clang has a similar built-in, __type_pack_element, but that's a "magic template" built-in using <> syntax, which GCC doesn't support. So this provides an equivalent feature, but as a built-in function using parens instead of <>. I don't really like the name "type pack element" (it gives you an element from a pack of types) but the semi-consistency with Clang seems like a reasonable argument in favour of keeping the name. I'd be open to alternative names though, e.g. __builtin_nth_type or __builtin_type_at_index. Rather than giving the trait a different name from __type_pack_element, I wonder if we could just special case cp_parser_trait to expect <> instead of parens for this trait? Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets rid of much of the boilerplate of adding a new type-yielding built-in trait, see e.g. cp-trait.def. Here's a tested patch based on Jonathan's original patch that implements the built-in in terms of TRAIT_TYPE, names it __type_pack_element instead of __builtin_type_pack_element, and treats invocations of it like a template-id instead of a call (to match Clang). -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. Some caveats: * Clang's version of the built-in seems to act like a "magic template" that can e.g. be used as a template template argument. For simplicity we implement it in a more ad-hoc way. * Our parsing of the <>'s in __type_pack_element<...> is currently rudimentary and doesn't try to disambiguate a trailing >> vs > > as cp_parser_enclosed_template_argument_list does. Hmm, this latter caveat turns out to be inconvenient (for code such as type_pack_element3.C) and admits an easy workaround inspired by what cp_parser_enclosed_template_argument_list does. v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of CPTK_TYPE_PACK_ELEMENT). Why not use cp_parser_enclosed_template_argument_list directly? -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. N.B. Clang seems to implement __type_pack_element as a first-class template that can e.g. be used as a template template argument. For simplicity we implement it in a more ad-hoc way. Co-authored-by: Jonathan Wakely PR c++/100157 gcc/cp/ChangeLog: * cp-trait.def (TYPE_PACK_ELEMENT): Define. * cp-tree.h (finish_trait_type): Add complain parameter. * cxx-pretty-print.cc (pp_cxx_trait): Handle CPTK_TYPE_PACK_ELEMENT.
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Mon, 9 Jan 2023 at 19:25, Patrick Palka wrote: > > On Mon, 9 Jan 2023, Patrick Palka wrote: > > > On Wed, 5 Oct 2022, Patrick Palka wrote: > > > > > On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > > > > > > > This adds a new built-in to replace the recursive class template > > > > instantiations done by traits such as std::tuple_element and > > > > std::variant_alternative. The purpose is to select the Nth type from a > > > > list of types, e.g. __builtin_type_pack_element(1, char, int, float) is > > > > int. > > > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > > > the compilation time is reduced by more than 90% and the memory used by > > > > the compiler is reduced by 97%. In realistic examples the gains will be > > > > much smaller, but still relevant. > > > > > > > > Clang has a similar built-in, __type_pack_element, but that's a > > > > "magic template" built-in using <> syntax, which GCC doesn't support. So > > > > this provides an equivalent feature, but as a built-in function using > > > > parens instead of <>. I don't really like the name "type pack element" > > > > (it gives you an element from a pack of types) but the semi-consistency > > > > with Clang seems like a reasonable argument in favour of keeping the > > > > name. I'd be open to alternative names though, e.g. __builtin_nth_type > > > > or __builtin_type_at_index. > > > > > > Rather than giving the trait a different name from __type_pack_element, > > > I wonder if we could just special case cp_parser_trait to expect <> > > > instead of parens for this trait? > > > > > > Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets > > > rid of much of the boilerplate of adding a new type-yielding built-in > > > trait, see e.g. cp-trait.def. > > > > Here's a tested patch based on Jonathan's original patch that implements > > the built-in in terms of TRAIT_TYPE, names it __type_pack_element > > instead of __builtin_type_pack_element, and treats invocations of it > > like a template-id instead of a call (to match Clang). The library change is very much OK, thanks for taking this over. > > > > -- >8 -- > > > > Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] > > > > This adds a new built-in to replace the recursive class template > > instantiations done by traits such as std::tuple_element and > > std::variant_alternative. The purpose is to select the Nth type from a > > list of types, e.g. __type_pack_element<1, char, int, float> is int. > > We implement it as a special kind of TRAIT_TYPE. > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > the compilation time is reduced by more than 90% and the memory used by > > the compiler is reduced by 97%. In realistic examples the gains will be > > much smaller, but still relevant. > > > > Unlike the other built-in traits, __type_pack_element uses template-id > > syntax instead of call syntax and is SFINAE-enabled, matching Clang's > > implementation. And like the other built-in traits, it's not mangleable > > so we can't use it directly in function signatures. > > > > Some caveats: > > > > * Clang's version of the built-in seems to act like a "magic template" > > that can e.g. be used as a template template argument. For simplicity > > we implement it in a more ad-hoc way. > > * Our parsing of the <>'s in __type_pack_element<...> is currently > > rudimentary and doesn't try to disambiguate a trailing >> vs > > > > as cp_parser_enclosed_template_argument_list does. > > Hmm, this latter caveat turns out to be inconvenient (for code such as > type_pack_element3.C) and admits an easy workaround inspired by what > cp_parser_enclosed_template_argument_list does. > > v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. > Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of > CPTK_TYPE_PACK_ELEMENT). > > -- >8 -- > > Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] > > This adds a new built-in to replace the recursive class template > instantiations done by traits such as std::tuple_element and > std::variant_alternative. The purpose is to select the Nth type from a > list of types, e.g. __type_pack_element<1, char, int, float> is int. > We implement it as a special kind of TRAIT_TYPE. > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > the compilation time is reduced by more than 90% and the memory used by > the compiler is reduced by 97%. In realistic examples the gains will be > much smaller, but still relevant. > > Unlike the other built-in traits, __type_pack_element uses template-id > syntax instead of call syntax and is SFINAE-enabled, matching Clang's > implementation. And like the other built-in traits, it's not mangleable > so we can't use it directly in function signatures. > > N.B. Clang seems to implement __type_pack_element as a first-class > template that
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Mon, 9 Jan 2023, Patrick Palka wrote: > On Wed, 5 Oct 2022, Patrick Palka wrote: > > > On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > > > > > This adds a new built-in to replace the recursive class template > > > instantiations done by traits such as std::tuple_element and > > > std::variant_alternative. The purpose is to select the Nth type from a > > > list of types, e.g. __builtin_type_pack_element(1, char, int, float) is > > > int. > > > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > > the compilation time is reduced by more than 90% and the memory used by > > > the compiler is reduced by 97%. In realistic examples the gains will be > > > much smaller, but still relevant. > > > > > > Clang has a similar built-in, __type_pack_element, but that's a > > > "magic template" built-in using <> syntax, which GCC doesn't support. So > > > this provides an equivalent feature, but as a built-in function using > > > parens instead of <>. I don't really like the name "type pack element" > > > (it gives you an element from a pack of types) but the semi-consistency > > > with Clang seems like a reasonable argument in favour of keeping the > > > name. I'd be open to alternative names though, e.g. __builtin_nth_type > > > or __builtin_type_at_index. > > > > Rather than giving the trait a different name from __type_pack_element, > > I wonder if we could just special case cp_parser_trait to expect <> > > instead of parens for this trait? > > > > Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets > > rid of much of the boilerplate of adding a new type-yielding built-in > > trait, see e.g. cp-trait.def. > > Here's a tested patch based on Jonathan's original patch that implements > the built-in in terms of TRAIT_TYPE, names it __type_pack_element > instead of __builtin_type_pack_element, and treats invocations of it > like a template-id instead of a call (to match Clang). > > -- >8 -- > > Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] > > This adds a new built-in to replace the recursive class template > instantiations done by traits such as std::tuple_element and > std::variant_alternative. The purpose is to select the Nth type from a > list of types, e.g. __type_pack_element<1, char, int, float> is int. > We implement it as a special kind of TRAIT_TYPE. > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > the compilation time is reduced by more than 90% and the memory used by > the compiler is reduced by 97%. In realistic examples the gains will be > much smaller, but still relevant. > > Unlike the other built-in traits, __type_pack_element uses template-id > syntax instead of call syntax and is SFINAE-enabled, matching Clang's > implementation. And like the other built-in traits, it's not mangleable > so we can't use it directly in function signatures. > > Some caveats: > > * Clang's version of the built-in seems to act like a "magic template" > that can e.g. be used as a template template argument. For simplicity > we implement it in a more ad-hoc way. > * Our parsing of the <>'s in __type_pack_element<...> is currently > rudimentary and doesn't try to disambiguate a trailing >> vs > > > as cp_parser_enclosed_template_argument_list does. Hmm, this latter caveat turns out to be inconvenient (for code such as type_pack_element3.C) and admits an easy workaround inspired by what cp_parser_enclosed_template_argument_list does. v2: Consider the >> in __type_pack_element<0, int, char>> to be two >'s. Handle non-type TRAIT_TYPE_TYPE1 in strip_typedefs (for sake of CPTK_TYPE_PACK_ELEMENT). -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. N.B. Clang seems to implement __type_pack_element as a first-class template that can e.g. be used as a template template argument. For simplicity we implement it in a more ad-hoc way. Co-authored-by: Jonathan Wakely PR c++/100157 gcc/cp/ChangeLog: * cp-trait.def (TYPE_PACK_ELEMENT): Define. * cp-tree.h (finish_trait_type): Add complain parame
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Wed, 5 Oct 2022, Patrick Palka wrote: > On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > > > This adds a new built-in to replace the recursive class template > > instantiations done by traits such as std::tuple_element and > > std::variant_alternative. The purpose is to select the Nth type from a > > list of types, e.g. __builtin_type_pack_element(1, char, int, float) is > > int. > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > the compilation time is reduced by more than 90% and the memory used by > > the compiler is reduced by 97%. In realistic examples the gains will be > > much smaller, but still relevant. > > > > Clang has a similar built-in, __type_pack_element, but that's a > > "magic template" built-in using <> syntax, which GCC doesn't support. So > > this provides an equivalent feature, but as a built-in function using > > parens instead of <>. I don't really like the name "type pack element" > > (it gives you an element from a pack of types) but the semi-consistency > > with Clang seems like a reasonable argument in favour of keeping the > > name. I'd be open to alternative names though, e.g. __builtin_nth_type > > or __builtin_type_at_index. > > Rather than giving the trait a different name from __type_pack_element, > I wonder if we could just special case cp_parser_trait to expect <> > instead of parens for this trait? > > Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets > rid of much of the boilerplate of adding a new type-yielding built-in > trait, see e.g. cp-trait.def. Here's a tested patch based on Jonathan's original patch that implements the built-in in terms of TRAIT_TYPE, names it __type_pack_element instead of __builtin_type_pack_element, and treats invocations of it like a template-id instead of a call (to match Clang). -- >8 -- Subject: [PATCH] c++: Define built-in for std::tuple_element [PR100157] This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __type_pack_element<1, char, int, float> is int. We implement it as a special kind of TRAIT_TYPE. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Unlike the other built-in traits, __type_pack_element uses template-id syntax instead of call syntax and is SFINAE-enabled, matching Clang's implementation. And like the other built-in traits, it's not mangleable so we can't use it directly in function signatures. Some caveats: * Clang's version of the built-in seems to act like a "magic template" that can e.g. be used as a template template argument. For simplicity we implement it in a more ad-hoc way. * Our parsing of the <>'s in __type_pack_element<...> is currently rudimentary and doesn't try to disambiguate a trailing >> vs > > as cp_parser_enclosed_template_argument_list does. Co-authored-by: Jonathan Wakely PR c++/100157 gcc/cp/ChangeLog: * cp-trait.def (TYPE_PACK_ELEMENT): Define. * cp-tree.h (finish_trait_type): Add complain parameter. * cxx-pretty-print.cc (pp_cxx_trait): Handle CPTK_TYPE_PACK_ELEMENT. * parser.cc (cp_parser_constant_expression): Document default arguments. (cp_parser_trait): Handle CPTK_TYPE_PACK_ELEMENT. Pass tf_warning_or_error to finish_trait_type. * pt.cc (tsubst) : Handle CPTK_TYPE_PACK_ELEMENT. * semantics.cc (finish_type_pack_element): Define. (finish_trait_type): Add complain parameter. Handle CPTK_TYPE_PACK_ELEMENT. * tree.cc (strip_typedefs): Pass tf_warning_or_error to finish_trait_type. * typeck.cc (structural_comptypes) : Use cp_tree_equal instead of same_type_p for TRAIT_TYPE_TYPE. libstdc++-v3/ChangeLog: * include/bits/utility.h (_Nth_type): Conditionally define using __type_pack_element. gcc/testsuite/ChangeLog: * g++.dg/ext/type_pack_element1.C: New test. * g++.dg/ext/type_pack_element2.C: New test. * g++.dg/ext/type_pack_element3.C: New test. --- gcc/cp/cp-trait.def | 1 + gcc/cp/cp-tree.h | 2 +- gcc/cp/cxx-pretty-print.cc| 17 ++-- gcc/cp/parser.cc | 36 - gcc/cp/pt.cc | 8 +++- gcc/cp/semantics.cc | 39 ++- gcc/cp/tree.cc| 3 +- gcc/cp/typeck.cc | 2 +- gcc/testsuite/g++.dg/ext/type_pack_element1.C | 19 + gcc/testsuite/g++.dg/ext/type_pack_element2.C | 14 +++
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Thu, 7 Jul 2022, Jonathan Wakely via Gcc-patches wrote: > This adds a new built-in to replace the recursive class template > instantiations done by traits such as std::tuple_element and > std::variant_alternative. The purpose is to select the Nth type from a > list of types, e.g. __builtin_type_pack_element(1, char, int, float) is > int. > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > the compilation time is reduced by more than 90% and the memory used by > the compiler is reduced by 97%. In realistic examples the gains will be > much smaller, but still relevant. > > Clang has a similar built-in, __type_pack_element, but that's a > "magic template" built-in using <> syntax, which GCC doesn't support. So > this provides an equivalent feature, but as a built-in function using > parens instead of <>. I don't really like the name "type pack element" > (it gives you an element from a pack of types) but the semi-consistency > with Clang seems like a reasonable argument in favour of keeping the > name. I'd be open to alternative names though, e.g. __builtin_nth_type > or __builtin_type_at_index. Rather than giving the trait a different name from __type_pack_element, I wonder if we could just special case cp_parser_trait to expect <> instead of parens for this trait? Btw the frontend recently got a generic TRAIT_TYPE tree code, which gets rid of much of the boilerplate of adding a new type-yielding built-in trait, see e.g. cp-trait.def. > > > The patch has some problems though ... > > FIXME 1: Marek pointed out that this this ICEs: > template using type = __builtin_type_pack_element(sizeof(T), > T...); > type c; > > The sizeof(T) expression is invalid, because T is an unexpanded pack, > but it's not rejected and instead crashes: > > ice.C: In substitution of 'template using type = > __builtin_type_pack_element (sizeof (T), T ...) [with T = {int, char}]': > ice.C:2:15: required from here > ice.C:1:63: internal compiler error: in dependent_type_p, at cp/pt.cc:27490 > 1 | template using type = > __builtin_type_pack_element(sizeof(T), T...); > | > ^ > 0xe13eea dependent_type_p(tree_node*) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:27490 > 0xeb1286 cxx_sizeof_or_alignof_type(unsigned int, tree_node*, tree_code, > bool, bool) > /home/jwakely/src/gcc/gcc/gcc/cp/typeck.cc:1912 > 0xdf4fcc tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, > bool) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:20582 > 0xdd9121 tsubst_tree_list(tree_node*, tree_node*, int, tree_node*) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15587 > 0xddb583 tsubst(tree_node*, tree_node*, int, tree_node*) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:16056 > 0xddcc9d tsubst(tree_node*, tree_node*, int, tree_node*) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:16436 > 0xdd6d45 tsubst_decl > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15038 > 0xdd952a tsubst(tree_node*, tree_node*, int, tree_node*) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15668 > 0xdfb9a1 instantiate_template(tree_node*, tree_node*, int) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:21811 > 0xdfc1b6 instantiate_alias_template > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:21896 > 0xdd9796 tsubst(tree_node*, tree_node*, int, tree_node*) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15696 > 0xdbaba5 lookup_template_class(tree_node*, tree_node*, tree_node*, > tree_node*, int, int) > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:10131 > 0xe4bac0 finish_template_type(tree_node*, tree_node*, int) > /home/jwakely/src/gcc/gcc/gcc/cp/semantics.cc:3727 > 0xd334c8 cp_parser_template_id > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:18458 > 0xd429b0 cp_parser_class_name > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:25923 > 0xd1ade9 cp_parser_qualifying_entity > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:7193 > 0xd1a2c8 cp_parser_nested_name_specifier_opt > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:6875 > 0xd4eefd cp_parser_template_introduction > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:31668 > 0xd4f416 cp_parser_template_declaration_after_export > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:31840 > 0xd2d60e cp_parser_declaration > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:15083 > > > FIXME 2: I want to mangle __builtin_type_pack_element(N, T...) the same as > typename std::_Nth_type::type but I don't know how. Instead of > trying to fake the mangled string, it's probably better to build a decl > for that nested type, right? Any suggestions where to find something > similar I can learn from? > > The reason to mangle it that way is that it preserves the same symbol > names as the library produced in GCC 12, and that it will still produce > with non-GCC compilers (see the definitions of std::_Nth_type in the > library parts of the patch). If we
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Thu, 7 Jul 2022 at 20:29, Jason Merrill wrote: > > On 7/7/22 13:14, Jonathan Wakely wrote: > > This adds a new built-in to replace the recursive class template > > instantiations done by traits such as std::tuple_element and > > std::variant_alternative. The purpose is to select the Nth type from a > > list of types, e.g. __builtin_type_pack_element(1, char, int, float) is > > int. > > > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > > the compilation time is reduced by more than 90% and the memory used by > > the compiler is reduced by 97%. In realistic examples the gains will be > > much smaller, but still relevant. > > > > Clang has a similar built-in, __type_pack_element, but that's a > > "magic template" built-in using <> syntax, which GCC doesn't support. So > > this provides an equivalent feature, but as a built-in function using > > parens instead of <>. I don't really like the name "type pack element" > > (it gives you an element from a pack of types) but the semi-consistency > > with Clang seems like a reasonable argument in favour of keeping the > > name. I'd be open to alternative names though, e.g. __builtin_nth_type > > or __builtin_type_at_index. > > > > > > The patch has some problems though ... > > > > FIXME 1: Marek pointed out that this this ICEs: > > template using type = __builtin_type_pack_element(sizeof(T), > > T...); > > type c; > > > > The sizeof(T) expression is invalid, because T is an unexpanded pack, > > but it's not rejected and instead crashes: > > > > ice.C: In substitution of 'template using type = > > __builtin_type_pack_element (sizeof (T), T ...) [with T = {int, char}]': > > ice.C:2:15: required from here > > ice.C:1:63: internal compiler error: in dependent_type_p, at cp/pt.cc:27490 > > 1 | template using type = > > __builtin_type_pack_element(sizeof(T), T...); > >| > > ^ > > 0xe13eea dependent_type_p(tree_node*) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:27490 > > 0xeb1286 cxx_sizeof_or_alignof_type(unsigned int, tree_node*, tree_code, > > bool, bool) > > /home/jwakely/src/gcc/gcc/gcc/cp/typeck.cc:1912 > > 0xdf4fcc tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, > > bool, bool) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:20582 > > 0xdd9121 tsubst_tree_list(tree_node*, tree_node*, int, tree_node*) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15587 > > 0xddb583 tsubst(tree_node*, tree_node*, int, tree_node*) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:16056 > > 0xddcc9d tsubst(tree_node*, tree_node*, int, tree_node*) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:16436 > > 0xdd6d45 tsubst_decl > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15038 > > 0xdd952a tsubst(tree_node*, tree_node*, int, tree_node*) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15668 > > 0xdfb9a1 instantiate_template(tree_node*, tree_node*, int) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:21811 > > 0xdfc1b6 instantiate_alias_template > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:21896 > > 0xdd9796 tsubst(tree_node*, tree_node*, int, tree_node*) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15696 > > 0xdbaba5 lookup_template_class(tree_node*, tree_node*, tree_node*, > > tree_node*, int, int) > > /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:10131 > > 0xe4bac0 finish_template_type(tree_node*, tree_node*, int) > > /home/jwakely/src/gcc/gcc/gcc/cp/semantics.cc:3727 > > 0xd334c8 cp_parser_template_id > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:18458 > > 0xd429b0 cp_parser_class_name > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:25923 > > 0xd1ade9 cp_parser_qualifying_entity > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:7193 > > 0xd1a2c8 cp_parser_nested_name_specifier_opt > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:6875 > > 0xd4eefd cp_parser_template_introduction > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:31668 > > 0xd4f416 cp_parser_template_declaration_after_export > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:31840 > > 0xd2d60e cp_parser_declaration > > /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:15083 > > > > > > FIXME 2: I want to mangle __builtin_type_pack_element(N, T...) the same as > > typename std::_Nth_type::type but I don't know how. Instead of > > trying to fake the mangled string, it's probably better to build a decl > > for that nested type, right? Any suggestions where to find something > > similar I can learn from? > > The tricky thing is dealing with mangling compression, where we use a > substitution instead of repeating a type; that's definitely easier if we > actually have the type. Yeah, that's what I discovered when trying to fudge it as "19__builtin_type_pack_elementE" etc. > So you'd probably want to have a declaration of std::_Nth_type to work > with, and lookup_template_class
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On 7/7/22 13:14, Jonathan Wakely wrote: This adds a new built-in to replace the recursive class template instantiations done by traits such as std::tuple_element and std::variant_alternative. The purpose is to select the Nth type from a list of types, e.g. __builtin_type_pack_element(1, char, int, float) is int. For a pathological example tuple_element_t<1000, tuple<2000 types...>> the compilation time is reduced by more than 90% and the memory used by the compiler is reduced by 97%. In realistic examples the gains will be much smaller, but still relevant. Clang has a similar built-in, __type_pack_element, but that's a "magic template" built-in using <> syntax, which GCC doesn't support. So this provides an equivalent feature, but as a built-in function using parens instead of <>. I don't really like the name "type pack element" (it gives you an element from a pack of types) but the semi-consistency with Clang seems like a reasonable argument in favour of keeping the name. I'd be open to alternative names though, e.g. __builtin_nth_type or __builtin_type_at_index. The patch has some problems though ... FIXME 1: Marek pointed out that this this ICEs: template using type = __builtin_type_pack_element(sizeof(T), T...); type c; The sizeof(T) expression is invalid, because T is an unexpanded pack, but it's not rejected and instead crashes: ice.C: In substitution of 'template using type = __builtin_type_pack_element (sizeof (T), T ...) [with T = {int, char}]': ice.C:2:15: required from here ice.C:1:63: internal compiler error: in dependent_type_p, at cp/pt.cc:27490 1 | template using type = __builtin_type_pack_element(sizeof(T), T...); | ^ 0xe13eea dependent_type_p(tree_node*) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:27490 0xeb1286 cxx_sizeof_or_alignof_type(unsigned int, tree_node*, tree_code, bool, bool) /home/jwakely/src/gcc/gcc/gcc/cp/typeck.cc:1912 0xdf4fcc tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:20582 0xdd9121 tsubst_tree_list(tree_node*, tree_node*, int, tree_node*) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15587 0xddb583 tsubst(tree_node*, tree_node*, int, tree_node*) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:16056 0xddcc9d tsubst(tree_node*, tree_node*, int, tree_node*) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:16436 0xdd6d45 tsubst_decl /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15038 0xdd952a tsubst(tree_node*, tree_node*, int, tree_node*) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15668 0xdfb9a1 instantiate_template(tree_node*, tree_node*, int) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:21811 0xdfc1b6 instantiate_alias_template /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:21896 0xdd9796 tsubst(tree_node*, tree_node*, int, tree_node*) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:15696 0xdbaba5 lookup_template_class(tree_node*, tree_node*, tree_node*, tree_node*, int, int) /home/jwakely/src/gcc/gcc/gcc/cp/pt.cc:10131 0xe4bac0 finish_template_type(tree_node*, tree_node*, int) /home/jwakely/src/gcc/gcc/gcc/cp/semantics.cc:3727 0xd334c8 cp_parser_template_id /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:18458 0xd429b0 cp_parser_class_name /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:25923 0xd1ade9 cp_parser_qualifying_entity /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:7193 0xd1a2c8 cp_parser_nested_name_specifier_opt /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:6875 0xd4eefd cp_parser_template_introduction /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:31668 0xd4f416 cp_parser_template_declaration_after_export /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:31840 0xd2d60e cp_parser_declaration /home/jwakely/src/gcc/gcc/gcc/cp/parser.cc:15083 FIXME 2: I want to mangle __builtin_type_pack_element(N, T...) the same as typename std::_Nth_type::type but I don't know how. Instead of trying to fake the mangled string, it's probably better to build a decl for that nested type, right? Any suggestions where to find something similar I can learn from? The tricky thing is dealing with mangling compression, where we use a substitution instead of repeating a type; that's definitely easier if we actually have the type. So you'd probably want to have a declaration of std::_Nth_type to work with, and lookup_template_class to get the type of that specialization. And then if it's complete, look up ...::type; if not, we could probably stuff a ...::type in its TYPE_FIELDS that would get clobbered if we actually instantiated the type... The reason to mangle it that way is that it preserves the same symbol names as the library produced in GCC 12, and that it will still produce with non-GCC compilers (see the definitions of std::_Nth_type in the library parts of the patch). If we don't do that then either we need to e
Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]
On Thu, Jul 07, 2022 at 06:14:36PM +0100, Jonathan Wakely wrote: > This adds a new built-in to replace the recursive class template > instantiations done by traits such as std::tuple_element and > std::variant_alternative. The purpose is to select the Nth type from a > list of types, e.g. __builtin_type_pack_element(1, char, int, float) is > int. > > For a pathological example tuple_element_t<1000, tuple<2000 types...>> > the compilation time is reduced by more than 90% and the memory used by > the compiler is reduced by 97%. In realistic examples the gains will be > much smaller, but still relevant. > > Clang has a similar built-in, __type_pack_element, but that's a > "magic template" built-in using <> syntax, which GCC doesn't support. So > this provides an equivalent feature, but as a built-in function using > parens instead of <>. I don't really like the name "type pack element" > (it gives you an element from a pack of types) but the semi-consistency > with Clang seems like a reasonable argument in favour of keeping the > name. I'd be open to alternative names though, e.g. __builtin_nth_type > or __builtin_type_at_index. > > > The patch has some problems though ... > > FIXME 1: Marek pointed out that this this ICEs: > template using type = __builtin_type_pack_element(sizeof(T), > T...); > type c; > > The sizeof(T) expression is invalid, because T is an unexpanded pack, > but it's not rejected and instead crashes: I think this could be fixed by if (check_for_bare_parameter_packs (n)) return error_mark_node; in finish_type_pack_element. (I haven't looked at the rest of the patch yet.) Marek