diff mbox series

[03/14] C++: add location_t wrapper nodes during parsing (minimal impl)

Message ID 1510350329-48956-4-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series Preserving locations for variable-uses and constants (PR 43486) | expand

Commit Message

David Malcolm Nov. 10, 2017, 9:45 p.m. UTC
The initial version of the patch kit added location wrapper nodes
around constants and uses-of-declarations, along with some other
places in the parser (typeid, alignof, sizeof, offsetof).

This version takes a much more minimal approach: it only adds
location wrapper nodes around the arguments at callsites, thus
not adding wrapper nodes around uses of constants and decls in other
locations.

It keeps them for the other places in the parser (typeid, alignof,
sizeof, offsetof).

In addition, for now, each site that adds wrapper nodes is guarded
with !processing_template_decl, suppressing the creation of wrapper
nodes when processing template declarations.  This is to simplify
the patch kit so that we don't have to support wrapper nodes during
template expansion.

gcc/cp/ChangeLog:
	* parser.c (cp_parser_postfix_expression): Call
	maybe_add_location_wrapper on the result for RID_TYPEID. Pass true
	for new "wrap_locations_p" param of
	cp_parser_parenthesized_expression_list.
	(cp_parser_parenthesized_expression_list): Add "wrap_locations_p"
	param, defaulting to false.  Convert "expr" to a cp_expr, and call
	maybe_add_location_wrapper on it when wrap_locations_p is true,
	except when processing template decls.
	(cp_parser_unary_expression): Call maybe_add_location_wrapper on
	the result for RID_ALIGNOF and RID_SIZEOF.
	(cp_parser_builtin_offsetof): Likewise.

FIXME: don't do alignof etc when processing template decls
---
 gcc/cp/parser.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

Comments

Jason Merrill Dec. 12, 2017, 2:10 a.m. UTC | #1
On 11/10/2017 04:45 PM, David Malcolm wrote:
> The initial version of the patch kit added location wrapper nodes
> around constants and uses-of-declarations, along with some other
> places in the parser (typeid, alignof, sizeof, offsetof).
> 
> This version takes a much more minimal approach: it only adds
> location wrapper nodes around the arguments at callsites, thus
> not adding wrapper nodes around uses of constants and decls in other
> locations.
> 
> It keeps them for the other places in the parser (typeid, alignof,
> sizeof, offsetof).
> 
> In addition, for now, each site that adds wrapper nodes is guarded
> with !processing_template_decl, suppressing the creation of wrapper
> nodes when processing template declarations.  This is to simplify
> the patch kit so that we don't have to support wrapper nodes during
> template expansion.

Hmm, it should be easy to support them, since NON_LVALUE_EXPR and 
VIEW_CONVERT_EXPR don't otherwise appear in template trees.

Jason
David Malcolm Dec. 14, 2017, 7:25 p.m. UTC | #2
On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > The initial version of the patch kit added location wrapper nodes
> > around constants and uses-of-declarations, along with some other
> > places in the parser (typeid, alignof, sizeof, offsetof).
> > 
> > This version takes a much more minimal approach: it only adds
> > location wrapper nodes around the arguments at callsites, thus
> > not adding wrapper nodes around uses of constants and decls in
> > other
> > locations.
> > 
> > It keeps them for the other places in the parser (typeid, alignof,
> > sizeof, offsetof).
> > 
> > In addition, for now, each site that adds wrapper nodes is guarded
> > with !processing_template_decl, suppressing the creation of wrapper
> > nodes when processing template declarations.  This is to simplify
> > the patch kit so that we don't have to support wrapper nodes during
> > template expansion.
> 
> Hmm, it should be easy to support them, since NON_LVALUE_EXPR and 
> VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> 
> Jason

I don't know if it's "easy"; it's at least non-trivial.

I attempted to support them in the obvious way by adding the two codes
to the switch statement tsubst_copy, reusing the case used by NOP_EXPR
and others, but ran into a issue when dealing with template parameter
packs.

Attached is the reproducer I've been testing with (minimized using
"delta" from a stdlib reproducer); my code was failing with:

../../src/cp-stdlib.ii: In instantiation of ‘struct allocator_traits<allocator<char> >’:
../../src/cp-stdlib.ii:31:8:   required from ‘struct __alloc_traits<allocator<char>, char>’
../../src/cp-stdlib.ii:43:75:   required from ‘class basic_string<char, allocator<char> >’
../../src/cp-stdlib.ii:47:58:   required from here
../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of ‘type_pack_expansion’ in template
     -> decltype(_S_construct(__a, __p, forward<_Args>(__args)...))  {   }
                                                       ^~~~~~

The issue is that normally "__args" would be a PARM_DECL of type
TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on adding a
wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
TYPE_PACK_EXPANSION wrapping the PARM_DECL.

When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached first,
and it attempts to substitute the type TYPE_PACK_EXPANSION, which leads
to the "sorry".

If I understand things right, during substitution, only tsubst_decl on
PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.

The simplest approach seems to be to not create wrapper nodes for decls
of type TYPE_PACK_EXPANSION, and that seems to fix the issue.

Alternatively I can handle TYPE_PACK_EXPANSION for VIEW_CONVERT_EXPR in
tsubst by remapping the type to that of what they wrap after
substitution; doing so also fixes the issue.

Does this sound correct and sane?  Do you have a preferred approach?

On fixing that I'm running into a different issue when testing the
stdlib (again with parameter packs, I think), but I'm still
investigating that one...

Thanks
Dave
typedef long unsigned int size_t;

template<typename _Tp>
struct remove_reference {};

template<typename _Tp>
constexpr _Tp&&
forward(typename remove_reference<_Tp>::type& __t) noexcept
{
}

struct __allocator_traits_base {
  template<typename _Tp, typename _Up, typename = void>
  struct __rebind
  {
    using type = typename _Tp::template rebind<_Up>::other;
  };
};

template<typename _Alloc, typename _Up>
using __alloc_rebind = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;

template<typename _Alloc>  struct allocator_traits {
  template<typename _Tp>  using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
  template<typename _Tp, typename... _Args>
  static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
    -> decltype(_S_construct(__a, __p, forward<_Args>(__args)...))  {   }
};

template<typename _Alloc, typename = typename _Alloc::value_type>
struct __alloc_traits    : allocator_traits<_Alloc>    {
  typedef allocator_traits<_Alloc> _Base_type;
  template<typename _Tp>       struct rebind       {   typedef typename _Base_type::template rebind_alloc<_Tp> other;   };
};

template<typename _Tp>     class allocator {
  typedef _Tp value_type;
  template<typename _Tp1>  struct rebind  {   typedef allocator<_Tp1> other;   };
};

template<typename _CharT, typename _Alloc>
class basic_string {
  typedef typename __alloc_traits<_Alloc>::template rebind<_CharT>::other _Char_alloc_type;
};

template<size_t _Nw>  struct _Base_bitset {
  static void foo (basic_string<char, allocator<char> >) {}
};
Jason Merrill Dec. 15, 2017, 3:01 p.m. UTC | #3
On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
>> On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > The initial version of the patch kit added location wrapper nodes
>> > around constants and uses-of-declarations, along with some other
>> > places in the parser (typeid, alignof, sizeof, offsetof).
>> >
>> > This version takes a much more minimal approach: it only adds
>> > location wrapper nodes around the arguments at callsites, thus
>> > not adding wrapper nodes around uses of constants and decls in
>> > other
>> > locations.
>> >
>> > It keeps them for the other places in the parser (typeid, alignof,
>> > sizeof, offsetof).
>> >
>> > In addition, for now, each site that adds wrapper nodes is guarded
>> > with !processing_template_decl, suppressing the creation of wrapper
>> > nodes when processing template declarations.  This is to simplify
>> > the patch kit so that we don't have to support wrapper nodes during
>> > template expansion.
>>
>> Hmm, it should be easy to support them, since NON_LVALUE_EXPR and
>> VIEW_CONVERT_EXPR don't otherwise appear in template trees.
>>
>> Jason
>
> I don't know if it's "easy"; it's at least non-trivial.
>
> I attempted to support them in the obvious way by adding the two codes
> to the switch statement tsubst_copy, reusing the case used by NOP_EXPR
> and others, but ran into a issue when dealing with template parameter
> packs.

> Attached is the reproducer I've been testing with (minimized using
> "delta" from a stdlib reproducer); my code was failing with:
>
> ../../src/cp-stdlib.ii: In instantiation of ‘struct allocator_traits<allocator<char> >’:
> ../../src/cp-stdlib.ii:31:8:   required from ‘struct __alloc_traits<allocator<char>, char>’
> ../../src/cp-stdlib.ii:43:75:   required from ‘class basic_string<char, allocator<char> >’
> ../../src/cp-stdlib.ii:47:58:   required from here
> ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of ‘type_pack_expansion’ in template
>      -> decltype(_S_construct(__a, __p, forward<_Args>(__args)...))  {   }
>                                                        ^~~~~~
>
> The issue is that normally "__args" would be a PARM_DECL of type
> TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on adding a
> wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
> TYPE_PACK_EXPANSION wrapping the PARM_DECL.
>
> When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached first,
> and it attempts to substitute the type TYPE_PACK_EXPANSION, which leads
> to the "sorry".
>
> If I understand things right, during substitution, only tsubst_decl on
> PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.
>
> The simplest approach seems to be to not create wrapper nodes for decls
> of type TYPE_PACK_EXPANSION, and that seems to fix the issue.

That does seem simplest.

> Alternatively I can handle TYPE_PACK_EXPANSION for VIEW_CONVERT_EXPR in
> tsubst by remapping the type to that of what they wrap after
> substitution; doing so also fixes the issue.

This will be more correct.  For the wrappers you don't need all the
handling that we currently have for NOP_EXPR and such; since we know
they don't change the type, we can substitute what they wrap, and then
rewrap the result.

Jason
David Malcolm Dec. 15, 2017, 4:35 p.m. UTC | #4
On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
> On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > The initial version of the patch kit added location wrapper
> > > > nodes
> > > > around constants and uses-of-declarations, along with some
> > > > other
> > > > places in the parser (typeid, alignof, sizeof, offsetof).
> > > > 
> > > > This version takes a much more minimal approach: it only adds
> > > > location wrapper nodes around the arguments at callsites, thus
> > > > not adding wrapper nodes around uses of constants and decls in
> > > > other
> > > > locations.
> > > > 
> > > > It keeps them for the other places in the parser (typeid,
> > > > alignof,
> > > > sizeof, offsetof).
> > > > 
> > > > In addition, for now, each site that adds wrapper nodes is
> > > > guarded
> > > > with !processing_template_decl, suppressing the creation of
> > > > wrapper
> > > > nodes when processing template declarations.  This is to
> > > > simplify
> > > > the patch kit so that we don't have to support wrapper nodes
> > > > during
> > > > template expansion.
> > > 
> > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR and
> > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> > > 
> > > Jason
> > 
> > I don't know if it's "easy"; it's at least non-trivial.
> > 
> > I attempted to support them in the obvious way by adding the two
> > codes
> > to the switch statement tsubst_copy, reusing the case used by
> > NOP_EXPR
> > and others, but ran into a issue when dealing with template
> > parameter
> > packs.
> > Attached is the reproducer I've been testing with (minimized using
> > "delta" from a stdlib reproducer); my code was failing with:
> > 
> > ../../src/cp-stdlib.ii: In instantiation of ‘struct
> > allocator_traits<allocator<char> >’:
> > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
> > __alloc_traits<allocator<char>, char>’
> > ../../src/cp-stdlib.ii:43:75:   required from ‘class
> > basic_string<char, allocator<char> >’
> > ../../src/cp-stdlib.ii:47:58:   required from here
> > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
> > ‘type_pack_expansion’ in template
> >      -> decltype(_S_construct(__a, __p,
> > forward<_Args>(__args)...))  {   }
> >                                                        ^~~~~~
> > 
> > The issue is that normally "__args" would be a PARM_DECL of type
> > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
> > adding a
> > wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
> > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
> > 
> > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached
> > first,
> > and it attempts to substitute the type TYPE_PACK_EXPANSION, which
> > leads
> > to the "sorry".
> > 
> > If I understand things right, during substitution, only tsubst_decl
> > on
> > PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.
> > 
> > The simplest approach seems to be to not create wrapper nodes for
> > decls
> > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
> 
> That does seem simplest.
> 
> > Alternatively I can handle TYPE_PACK_EXPANSION for
> > VIEW_CONVERT_EXPR in
> > tsubst by remapping the type to that of what they wrap after
> > substitution; doing so also fixes the issue.
> 
> This will be more correct.  For the wrappers you don't need all the
> handling that we currently have for NOP_EXPR and such; since we know
> they don't change the type, we can substitute what they wrap, and
> then
> rewrap the result.

(nods; I have this working)

I've been debugging the other issues that I ran into when removing the
"!processing_template_decl" filter on making wrapper nodes (ICEs and
other errors on valid code).  They turn out to relate to wrappers
around decls of type TEMPLATE_TYPE_PARM; having these wrappers leads to
such VIEW_CONVERT_EXPRs turning up in unexpected places.

I could try to track all those places down, but it seems much simpler
to just add an exclusion to adding wrapper nodes around decls of type
TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++ stdlib
work again.  Does that sound reasonable?

Thanks
Dave
Jason Merrill Dec. 15, 2017, 6:58 p.m. UTC | #5
On Fri, Dec 15, 2017 at 11:35 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
>> On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.com>
>> wrote:
>> > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
>> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > The initial version of the patch kit added location wrapper
>> > > > nodes
>> > > > around constants and uses-of-declarations, along with some
>> > > > other
>> > > > places in the parser (typeid, alignof, sizeof, offsetof).
>> > > >
>> > > > This version takes a much more minimal approach: it only adds
>> > > > location wrapper nodes around the arguments at callsites, thus
>> > > > not adding wrapper nodes around uses of constants and decls in
>> > > > other
>> > > > locations.
>> > > >
>> > > > It keeps them for the other places in the parser (typeid,
>> > > > alignof,
>> > > > sizeof, offsetof).
>> > > >
>> > > > In addition, for now, each site that adds wrapper nodes is
>> > > > guarded
>> > > > with !processing_template_decl, suppressing the creation of
>> > > > wrapper
>> > > > nodes when processing template declarations.  This is to
>> > > > simplify
>> > > > the patch kit so that we don't have to support wrapper nodes
>> > > > during
>> > > > template expansion.
>> > >
>> > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR and
>> > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
>> > >
>> > > Jason
>> >
>> > I don't know if it's "easy"; it's at least non-trivial.
>> >
>> > I attempted to support them in the obvious way by adding the two
>> > codes
>> > to the switch statement tsubst_copy, reusing the case used by
>> > NOP_EXPR
>> > and others, but ran into a issue when dealing with template
>> > parameter
>> > packs.
>> > Attached is the reproducer I've been testing with (minimized using
>> > "delta" from a stdlib reproducer); my code was failing with:
>> >
>> > ../../src/cp-stdlib.ii: In instantiation of ‘struct
>> > allocator_traits<allocator<char> >’:
>> > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
>> > __alloc_traits<allocator<char>, char>’
>> > ../../src/cp-stdlib.ii:43:75:   required from ‘class
>> > basic_string<char, allocator<char> >’
>> > ../../src/cp-stdlib.ii:47:58:   required from here
>> > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
>> > ‘type_pack_expansion’ in template
>> >      -> decltype(_S_construct(__a, __p,
>> > forward<_Args>(__args)...))  {   }
>> >                                                        ^~~~~~
>> >
>> > The issue is that normally "__args" would be a PARM_DECL of type
>> > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
>> > adding a
>> > wrapper node we now have a VIEW_CONVERT_EXPR of the same type i.e.
>> > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
>> >
>> > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is reached
>> > first,
>> > and it attempts to substitute the type TYPE_PACK_EXPANSION, which
>> > leads
>> > to the "sorry".
>> >
>> > If I understand things right, during substitution, only tsubst_decl
>> > on
>> > PARM_DECL can handle nodes with type with code TYPE_PACK_EXPANSION.
>> >
>> > The simplest approach seems to be to not create wrapper nodes for
>> > decls
>> > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
>>
>> That does seem simplest.
>>
>> > Alternatively I can handle TYPE_PACK_EXPANSION for
>> > VIEW_CONVERT_EXPR in
>> > tsubst by remapping the type to that of what they wrap after
>> > substitution; doing so also fixes the issue.
>>
>> This will be more correct.  For the wrappers you don't need all the
>> handling that we currently have for NOP_EXPR and such; since we know
>> they don't change the type, we can substitute what they wrap, and
>> then
>> rewrap the result.
>
> (nods; I have this working)
>
> I've been debugging the other issues that I ran into when removing the
> "!processing_template_decl" filter on making wrapper nodes (ICEs and
> other errors on valid code).  They turn out to relate to wrappers
> around decls of type TEMPLATE_TYPE_PARM; having these wrappers leads to
> such VIEW_CONVERT_EXPRs turning up in unexpected places.

Hmm, that's odd.  What kind of decls?  A variable which happens to
have a template parameter for a type shouldn't be a problem.

> I could try to track all those places down, but it seems much simpler
> to just add an exclusion to adding wrapper nodes around decls of type
> TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++ stdlib
> work again.  Does that sound reasonable?

Jason
David Malcolm Dec. 15, 2017, 10:48 p.m. UTC | #6
On Fri, 2017-12-15 at 13:58 -0500, Jason Merrill wrote:
> On Fri, Dec 15, 2017 at 11:35 AM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > On Fri, 2017-12-15 at 10:01 -0500, Jason Merrill wrote:
> > > On Thu, Dec 14, 2017 at 2:25 PM, David Malcolm <dmalcolm@redhat.c
> > > om>
> > > wrote:
> > > > On Mon, 2017-12-11 at 21:10 -0500, Jason Merrill wrote:
> > > > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > > > The initial version of the patch kit added location wrapper
> > > > > > nodes
> > > > > > around constants and uses-of-declarations, along with some
> > > > > > other
> > > > > > places in the parser (typeid, alignof, sizeof, offsetof).
> > > > > > 
> > > > > > This version takes a much more minimal approach: it only
> > > > > > adds
> > > > > > location wrapper nodes around the arguments at callsites,
> > > > > > thus
> > > > > > not adding wrapper nodes around uses of constants and decls
> > > > > > in
> > > > > > other
> > > > > > locations.
> > > > > > 
> > > > > > It keeps them for the other places in the parser (typeid,
> > > > > > alignof,
> > > > > > sizeof, offsetof).
> > > > > > 
> > > > > > In addition, for now, each site that adds wrapper nodes is
> > > > > > guarded
> > > > > > with !processing_template_decl, suppressing the creation of
> > > > > > wrapper
> > > > > > nodes when processing template declarations.  This is to
> > > > > > simplify
> > > > > > the patch kit so that we don't have to support wrapper
> > > > > > nodes
> > > > > > during
> > > > > > template expansion.
> > > > > 
> > > > > Hmm, it should be easy to support them, since NON_LVALUE_EXPR
> > > > > and
> > > > > VIEW_CONVERT_EXPR don't otherwise appear in template trees.
> > > > > 
> > > > > Jason
> > > > 
> > > > I don't know if it's "easy"; it's at least non-trivial.
> > > > 
> > > > I attempted to support them in the obvious way by adding the
> > > > two
> > > > codes
> > > > to the switch statement tsubst_copy, reusing the case used by
> > > > NOP_EXPR
> > > > and others, but ran into a issue when dealing with template
> > > > parameter
> > > > packs.
> > > > Attached is the reproducer I've been testing with (minimized
> > > > using
> > > > "delta" from a stdlib reproducer); my code was failing with:
> > > > 
> > > > ../../src/cp-stdlib.ii: In instantiation of ‘struct
> > > > allocator_traits<allocator<char> >’:
> > > > ../../src/cp-stdlib.ii:31:8:   required from ‘struct
> > > > __alloc_traits<allocator<char>, char>’
> > > > ../../src/cp-stdlib.ii:43:75:   required from ‘class
> > > > basic_string<char, allocator<char> >’
> > > > ../../src/cp-stdlib.ii:47:58:   required from here
> > > > ../../src/cp-stdlib.ii:27:55: sorry, unimplemented: use of
> > > > ‘type_pack_expansion’ in template
> > > >      -> decltype(_S_construct(__a, __p,
> > > > forward<_Args>(__args)...))  {   }
> > > >                                                        ^~~~~~
> > > > 
> > > > The issue is that normally "__args" would be a PARM_DECL of
> > > > type
> > > > TYPE_PACK_EXPANSION, and that's handled by tsubst_decl, but on
> > > > adding a
> > > > wrapper node we now have a VIEW_CONVERT_EXPR of the same type
> > > > i.e.
> > > > TYPE_PACK_EXPANSION wrapping the PARM_DECL.
> > > > 
> > > > When tsubst traverses the tree, the VIEW_CONVERT_EXPR is
> > > > reached
> > > > first,
> > > > and it attempts to substitute the type TYPE_PACK_EXPANSION,
> > > > which
> > > > leads
> > > > to the "sorry".
> > > > 
> > > > If I understand things right, during substitution, only
> > > > tsubst_decl
> > > > on
> > > > PARM_DECL can handle nodes with type with code
> > > > TYPE_PACK_EXPANSION.
> > > > 
> > > > The simplest approach seems to be to not create wrapper nodes
> > > > for
> > > > decls
> > > > of type TYPE_PACK_EXPANSION, and that seems to fix the issue.
> > > 
> > > That does seem simplest.
> > > 
> > > > Alternatively I can handle TYPE_PACK_EXPANSION for
> > > > VIEW_CONVERT_EXPR in
> > > > tsubst by remapping the type to that of what they wrap after
> > > > substitution; doing so also fixes the issue.
> > > 
> > > This will be more correct.  For the wrappers you don't need all
> > > the
> > > handling that we currently have for NOP_EXPR and such; since we
> > > know
> > > they don't change the type, we can substitute what they wrap, and
> > > then
> > > rewrap the result.
> > 
> > (nods; I have this working)
> > 
> > I've been debugging the other issues that I ran into when removing
> > the
> > "!processing_template_decl" filter on making wrapper nodes (ICEs
> > and
> > other errors on valid code).  They turn out to relate to wrappers
> > around decls of type TEMPLATE_TYPE_PARM; having these wrappers
> > leads to
> > such VIEW_CONVERT_EXPRs turning up in unexpected places.
> 
> Hmm, that's odd.  What kind of decls?  A variable which happens to
> have a template parameter for a type shouldn't be a problem.

That one turned out to be a bug in my changes to tsubst_copy, which
I've fixed.

But I'm still running into various other issues when attempting to
enable the wrappers for when processing_template_decl is true.  Having
spent a fair chunk of the week on it, I'm not finding it "easy to
support them" (though that may be one, of course...).

I'm working on addressing the other issues you raised; I hope to
post some updated patches when I get things bootstrapping again.

Thanks
Dave


> > I could try to track all those places down, but it seems much
> > simpler
> > to just add an exclusion to adding wrapper nodes around decls of
> > type
> > TEMPLATE_TYPE_PARM.  On doing that my smoketests with the C++
> > stdlib
> > work again.  Does that sound reasonable?
> 
> Jason
diff mbox series

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 77b9637..54029ef 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2054,7 +2054,8 @@  static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, cp_expr, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, location_t * = NULL);
+  (cp_parser *, int, bool, bool, bool *, location_t * = NULL,
+   bool = false);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
@@ -6776,6 +6777,8 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    location_t typeid_loc
 	      = make_location (start_loc, start_loc, close_paren->location);
 	    postfix_expression.set_location (typeid_loc);
+	    if (!processing_template_decl)
+	      postfix_expression.maybe_add_location_wrapper ();
 	  }
       }
       break;
@@ -7096,7 +7099,8 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
 		     /*non_constant_p=*/NULL,
-		     /*close_paren_loc=*/&close_paren_loc));
+		     /*close_paren_loc=*/&close_paren_loc,
+		     /*wrap_locations_p=*/true));
 	    if (is_builtin_constant_p)
 	      {
 		parser->integral_constant_expression_p
@@ -7736,6 +7740,10 @@  cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
+   WRAP_LOCATIONS_P is true if expressions within this list for which
+   CAN_HAVE_LOCATION_P is false should be wrapped with nodes expressing
+   their source locations.
+
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
@@ -7755,7 +7763,8 @@  cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p,
-					 location_t *close_paren_loc)
+					 location_t *close_paren_loc,
+					 bool wrap_locations_p)
 {
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
@@ -7778,12 +7787,12 @@  cp_parser_parenthesized_expression_list (cp_parser* parser,
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = true;
 
+  cp_expr expr (NULL_TREE);
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
-	tree expr;
-
 	/* At the beginning of attribute lists, check to see if the
 	   next token is an identifier.  */
 	if (is_attribute_list == id_attr
@@ -7837,11 +7846,15 @@  cp_parser_parenthesized_expression_list (cp_parser* parser,
                 expr = make_pack_expansion (expr);
               }
 
+	    if (wrap_locations_p)
+	      if (!processing_template_decl)
+		expr.maybe_add_location_wrapper ();
+
 	     /* Add it to the list.  We add error_mark_node
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    vec_safe_push (expression_list, expr);
+	    vec_safe_push (expression_list, expr.get_value ());
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -8107,6 +8120,8 @@  cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
 	    cp_expr ret_expr (ret);
 	    ret_expr.set_location (compound_loc);
+	    if (!processing_template_decl)
+	      ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
 
@@ -9933,6 +9948,8 @@  cp_parser_builtin_offsetof (cp_parser *parser)
   parser->integral_constant_expression_p = save_ice_p;
   parser->non_integral_constant_expression_p = save_non_ice_p;
 
+  if (!processing_template_decl)
+    expr = expr.maybe_add_location_wrapper ();
   return expr;
 }