Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-04-18 Thread Patrick Palka via Gcc-patches
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 invocatio

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-04-18 Thread Jason Merrill via Gcc-patches

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::

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-04-11 Thread Patrick Palka via Gcc-patches
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

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-01-26 Thread Jason Merrill via Gcc-patches

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

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-01-25 Thread Patrick Palka via Gcc-patches
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

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-01-17 Thread Jason Merrill via Gcc-patches

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.

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-01-10 Thread Jonathan Wakely via Gcc-patches
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

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-01-09 Thread Patrick Palka via Gcc-patches
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
implementa

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2023-01-09 Thread Patrick Palka via Gcc-patches
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  

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2022-10-05 Thread Patrick Palka via Gcc-patches
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 

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2022-07-07 Thread Jonathan Wakely via Gcc-patches
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]

2022-07-07 Thread Jason Merrill via Gcc-patches

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

Re: [PATCH] c++: Define built-in for std::tuple_element [PR100157]

2022-07-07 Thread Marek Polacek via Gcc-patches
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



[PATCH] c++: Define built-in for std::tuple_element [PR100157]

2022-07-07 Thread Jonathan Wakely via Gcc-patches
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 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
ensure it never appears in a mangled name, or define some other
GCC-specific mangling for this built-in (e.g. we could just mangle it as
though it's a function, "19__builtin_type_pack_elementELm1EJDpT_E" or
something like that!). If we ensure it doesn't appear in mangled names
that means we still need to instantiate the _Nth_type class template,
rather than defining the alias template _Nth_type_t to use the built-in
directly.  That loses a little of the compilation performance gain that
comes from defining the built-in in the first place (although avoid