* [PATCH] c++: Member initializer list diagnostic locations [PR94024]
@ 2020-08-03 14:14 Patrick Palka
2020-08-03 15:17 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-08-03 14:14 UTC (permalink / raw)
To: gcc-patches
This patch preserves the source locations of each node in a member
initializer list so that during processing of the list we can set
input_location appropriately for generally more accurate diagnostic
locations. Since TREE_LIST nodes are tcc_exceptional, they can't have
source locations, so we instead store the location in a dummy
tcc_expression node within the TREE_TYPE of the list node.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to
commit?
gcc/cp/ChangeLog:
PR c++/94024
* init.c (sort_mem_initializers): Preserve TREE_TYPE of the
member initializer list node.
(emit_mem_initializers): Set input_location when performing each
member initialization.
* parser.c (cp_parser_mem_initializer_list): Attach the source
location of this initializer to a dummy EMPTY_CLASS_EXPR within
the TREE_TYPE of the list node.
* pt.c (tsubst_initializer_list): Preserve TREE_TYPE of the
member initializer list node.
gcc/testsuite/ChangeLog:
PR c++/94024
* g++.dg/diagnostic/mem-init1.C: New test.
---
gcc/cp/init.c | 6 +++++
gcc/cp/parser.c | 8 ++++++
gcc/cp/pt.c | 3 +++
gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++
4 files changed, 46 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/diagnostic/mem-init1.C
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index cb9bd2dbfba..3f089404cf2 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1151,6 +1151,8 @@ sort_mem_initializers (tree t, tree mem_inits)
/* Record the initialization. */
TREE_VALUE (subobject_init) = TREE_VALUE (init);
+ /* Carry over the dummy TREE_TYPE node containing the source location. */
+ TREE_TYPE (subobject_init) = TREE_TYPE (init);
next_subobject = subobject_init;
}
@@ -1367,6 +1369,10 @@ emit_mem_initializers (tree mem_inits)
/* Initialize the data members. */
while (mem_inits)
{
+ /* If this initializer was explicitly provided, then the dummy TREE_TYPE
+ node contains the source location. */
+ iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
+
perform_member_init (TREE_PURPOSE (mem_inits),
TREE_VALUE (mem_inits));
mem_inits = TREE_CHAIN (mem_inits);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ab088874ba7..2f9b8786121 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15326,6 +15326,14 @@ cp_parser_mem_initializer_list (cp_parser* parser)
{
TREE_CHAIN (mem_initializer) = mem_initializer_list;
mem_initializer_list = mem_initializer;
+
+ /* We can't attach the source location of this initializer directly to
+ the list node, so we instead attach it to a dummy EMPTY_CLASS_EXPR
+ within the TREE_TYPE of the list node. */
+ TREE_TYPE (mem_initializer) = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
+ SET_EXPR_LOCATION (TREE_TYPE (mem_initializer),
+ make_location (token->location,
+ token->location, input_location));
}
/* If the next token is not a `,', we're done. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3a168d506cf..bed1a3532e7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26014,6 +26014,9 @@ tsubst_initializer_list (tree t, tree argvec)
if (decl)
{
init = build_tree_list (decl, init);
+ /* Carry over the dummy TREE_TYPE node containing the source
+ location. */
+ TREE_TYPE (init) = TREE_TYPE (t);
TREE_CHAIN (init) = inits;
inits = init;
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/mem-init1.C b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
new file mode 100644
index 00000000000..b749c72cd8b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
@@ -0,0 +1,29 @@
+// PR c++/94024
+// { dg-do compile }
+
+struct A {
+ A()
+ : a() // { dg-error "reference type" }
+ , b(1) // { dg-error "incompatible" }
+ , c(0) // { dg-bogus "" }
+ {}
+
+ int &a;
+ int b[1];
+ char c;
+};
+
+template<typename T, typename U>
+struct B {
+ B()
+ : a() // { dg-error "reference type" }
+ , b(1) // { dg-error "incompatible" }
+ , c(0) // { dg-bogus "" }
+ {}
+
+ T a;
+ U b;
+ char c;
+};
+
+B<int&, int[1]> b;
--
2.28.0.89.g85b4e0a6dc
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: Member initializer list diagnostic locations [PR94024]
2020-08-03 14:14 [PATCH] c++: Member initializer list diagnostic locations [PR94024] Patrick Palka
@ 2020-08-03 15:17 ` Jason Merrill
2020-08-03 18:49 ` Patrick Palka
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2020-08-03 15:17 UTC (permalink / raw)
To: Patrick Palka, gcc-patches
On 8/3/20 10:14 AM, Patrick Palka wrote:
> This patch preserves the source locations of each node in a member
> initializer list so that during processing of the list we can set
> input_location appropriately for generally more accurate diagnostic
> locations. Since TREE_LIST nodes are tcc_exceptional, they can't have
> source locations, so we instead store the location in a dummy
> tcc_expression node within the TREE_TYPE of the list node.
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to
> commit?
>
> gcc/cp/ChangeLog:
>
> PR c++/94024
> * init.c (sort_mem_initializers): Preserve TREE_TYPE of the
> member initializer list node.
> (emit_mem_initializers): Set input_location when performing each
> member initialization.
> * parser.c (cp_parser_mem_initializer_list): Attach the source
> location of this initializer to a dummy EMPTY_CLASS_EXPR within
> the TREE_TYPE of the list node.
> * pt.c (tsubst_initializer_list): Preserve TREE_TYPE of the
> member initializer list node.
>
> gcc/testsuite/ChangeLog:
>
> PR c++/94024
> * g++.dg/diagnostic/mem-init1.C: New test.
> ---
> gcc/cp/init.c | 6 +++++
> gcc/cp/parser.c | 8 ++++++
> gcc/cp/pt.c | 3 +++
> gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++
> 4 files changed, 46 insertions(+)
> create mode 100644 gcc/testsuite/g++.dg/diagnostic/mem-init1.C
>
> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> index cb9bd2dbfba..3f089404cf2 100644
> --- a/gcc/cp/init.c
> +++ b/gcc/cp/init.c
> @@ -1151,6 +1151,8 @@ sort_mem_initializers (tree t, tree mem_inits)
>
> /* Record the initialization. */
> TREE_VALUE (subobject_init) = TREE_VALUE (init);
> + /* Carry over the dummy TREE_TYPE node containing the source location. */
> + TREE_TYPE (subobject_init) = TREE_TYPE (init);
> next_subobject = subobject_init;
> }
>
> @@ -1367,6 +1369,10 @@ emit_mem_initializers (tree mem_inits)
> /* Initialize the data members. */
> while (mem_inits)
> {
> + /* If this initializer was explicitly provided, then the dummy TREE_TYPE
> + node contains the source location. */
> + iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
> +
> perform_member_init (TREE_PURPOSE (mem_inits),
> TREE_VALUE (mem_inits));
> mem_inits = TREE_CHAIN (mem_inits);
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index ab088874ba7..2f9b8786121 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -15326,6 +15326,14 @@ cp_parser_mem_initializer_list (cp_parser* parser)
> {
> TREE_CHAIN (mem_initializer) = mem_initializer_list;
> mem_initializer_list = mem_initializer;
> +
> + /* We can't attach the source location of this initializer directly to
> + the list node, so we instead attach it to a dummy EMPTY_CLASS_EXPR
> + within the TREE_TYPE of the list node. */
> + TREE_TYPE (mem_initializer) = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
> + SET_EXPR_LOCATION (TREE_TYPE (mem_initializer),
> + make_location (token->location,
> + token->location, input_location));
Why not do this in cp_parser_mem_initializer?
Also, use parser->lexer for the last argument to make_location.
> }
> /* If the next token is not a `,', we're done. */
> if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 3a168d506cf..bed1a3532e7 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -26014,6 +26014,9 @@ tsubst_initializer_list (tree t, tree argvec)
> if (decl)
> {
> init = build_tree_list (decl, init);
> + /* Carry over the dummy TREE_TYPE node containing the source
> + location. */
> + TREE_TYPE (init) = TREE_TYPE (t);
> TREE_CHAIN (init) = inits;
> inits = init;
> }
> diff --git a/gcc/testsuite/g++.dg/diagnostic/mem-init1.C b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
> new file mode 100644
> index 00000000000..b749c72cd8b
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
> @@ -0,0 +1,29 @@
> +// PR c++/94024
> +// { dg-do compile }
> +
> +struct A {
> + A()
> + : a() // { dg-error "reference type" }
> + , b(1) // { dg-error "incompatible" }
> + , c(0) // { dg-bogus "" }
> + {}
> +
> + int &a;
> + int b[1];
> + char c;
> +};
> +
> +template<typename T, typename U>
> +struct B {
> + B()
> + : a() // { dg-error "reference type" }
> + , b(1) // { dg-error "incompatible" }
> + , c(0) // { dg-bogus "" }
> + {}
> +
> + T a;
> + U b;
> + char c;
> +};
> +
> +B<int&, int[1]> b;
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: Member initializer list diagnostic locations [PR94024]
2020-08-03 15:17 ` Jason Merrill
@ 2020-08-03 18:49 ` Patrick Palka
2020-08-03 20:10 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-08-03 18:49 UTC (permalink / raw)
To: Jason Merrill; +Cc: Patrick Palka, gcc-patches
On Mon, 3 Aug 2020, Jason Merrill wrote:
> On 8/3/20 10:14 AM, Patrick Palka wrote:
> > This patch preserves the source locations of each node in a member
> > initializer list so that during processing of the list we can set
> > input_location appropriately for generally more accurate diagnostic
> > locations. Since TREE_LIST nodes are tcc_exceptional, they can't have
> > source locations, so we instead store the location in a dummy
> > tcc_expression node within the TREE_TYPE of the list node.
>
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to
> > commit?
> >
> > gcc/cp/ChangeLog:
> >
> > PR c++/94024
> > * init.c (sort_mem_initializers): Preserve TREE_TYPE of the
> > member initializer list node.
> > (emit_mem_initializers): Set input_location when performing each
> > member initialization.
> > * parser.c (cp_parser_mem_initializer_list): Attach the source
> > location of this initializer to a dummy EMPTY_CLASS_EXPR within
> > the TREE_TYPE of the list node.
> > * pt.c (tsubst_initializer_list): Preserve TREE_TYPE of the
> > member initializer list node.
> >
> > gcc/testsuite/ChangeLog:
> >
> > PR c++/94024
> > * g++.dg/diagnostic/mem-init1.C: New test.
> > ---
> > gcc/cp/init.c | 6 +++++
> > gcc/cp/parser.c | 8 ++++++
> > gcc/cp/pt.c | 3 +++
> > gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++
> > 4 files changed, 46 insertions(+)
> > create mode 100644 gcc/testsuite/g++.dg/diagnostic/mem-init1.C
> >
> > diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> > index cb9bd2dbfba..3f089404cf2 100644
> > --- a/gcc/cp/init.c
> > +++ b/gcc/cp/init.c
> > @@ -1151,6 +1151,8 @@ sort_mem_initializers (tree t, tree mem_inits)
> > /* Record the initialization. */
> > TREE_VALUE (subobject_init) = TREE_VALUE (init);
> > + /* Carry over the dummy TREE_TYPE node containing the source
> > location. */
> > + TREE_TYPE (subobject_init) = TREE_TYPE (init);
> > next_subobject = subobject_init;
> > }
> > @@ -1367,6 +1369,10 @@ emit_mem_initializers (tree mem_inits)
> > /* Initialize the data members. */
> > while (mem_inits)
> > {
> > + /* If this initializer was explicitly provided, then the dummy
> > TREE_TYPE
> > + node contains the source location. */
> > + iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
> > +
> > perform_member_init (TREE_PURPOSE (mem_inits),
> > TREE_VALUE (mem_inits));
> > mem_inits = TREE_CHAIN (mem_inits);
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index ab088874ba7..2f9b8786121 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -15326,6 +15326,14 @@ cp_parser_mem_initializer_list (cp_parser* parser)
> > {
> > TREE_CHAIN (mem_initializer) = mem_initializer_list;
> > mem_initializer_list = mem_initializer;
> > +
> > + /* We can't attach the source location of this initializer directly
> > to
> > + the list node, so we instead attach it to a dummy
> > EMPTY_CLASS_EXPR
> > + within the TREE_TYPE of the list node. */
> > + TREE_TYPE (mem_initializer) = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
> > + SET_EXPR_LOCATION (TREE_TYPE (mem_initializer),
> > + make_location (token->location,
> > + token->location, input_location));
>
> Why not do this in cp_parser_mem_initializer?
>
> Also, use parser->lexer for the last argument to make_location.
That's a much better spot for it :) Done and done. Does the following
look OK after testing completes?
-- >8 --
Subject: [PATCH] c++: Member initializer list diagnostic locations [PR94024]
This patch preserves the source locations of each node in a member
initializer list so that during processing of the list we can set
input_location appropriately for generally more accurate diagnostic
locations. Since TREE_LIST nodes are tcc_exceptional, they can't have
source locations, so we instead store the location in a dummy
tcc_expression node within the TREE_TYPE of the list node.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to
commit?
gcc/cp/ChangeLog:
PR c++/94024
* init.c (sort_mem_initializers): Preserve TREE_TYPE of the
member initializer list node.
(emit_mem_initializers): Set input_location when performing each
member initialization.
* parser.c (cp_parser_mem_initializer): Attach the source
location of this initializer to a dummy EMPTY_CLASS_EXPR
within the TREE_TYPE of the list node.
* pt.c (tsubst_initializer_list): Preserve TREE_TYPE of the
member initializer list node.
gcc/testsuite/ChangeLog:
PR c++/94024
* g++.dg/diagnostic/mem-init1.C: New test.
---
gcc/cp/init.c | 6 +++++
gcc/cp/parser.c | 13 ++++++++-
gcc/cp/pt.c | 3 +++
gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++
4 files changed, 50 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/diagnostic/mem-init1.C
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index cb9bd2dbfba..3f089404cf2 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1151,6 +1151,8 @@ sort_mem_initializers (tree t, tree mem_inits)
/* Record the initialization. */
TREE_VALUE (subobject_init) = TREE_VALUE (init);
+ /* Carry over the dummy TREE_TYPE node containing the source location. */
+ TREE_TYPE (subobject_init) = TREE_TYPE (init);
next_subobject = subobject_init;
}
@@ -1367,6 +1369,10 @@ emit_mem_initializers (tree mem_inits)
/* Initialize the data members. */
while (mem_inits)
{
+ /* If this initializer was explicitly provided, then the dummy TREE_TYPE
+ node contains the source location. */
+ iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
+
perform_member_init (TREE_PURPOSE (mem_inits),
TREE_VALUE (mem_inits));
mem_inits = TREE_CHAIN (mem_inits);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ab088874ba7..8b11e478c83 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15411,7 +15411,18 @@ cp_parser_mem_initializer (cp_parser* parser)
in_base_initializer = 0;
- return member ? build_tree_list (member, expression_list) : error_mark_node;
+ if (!member)
+ return error_mark_node;
+
+ tree node = build_tree_list (member, expression_list);
+ /* We can't attach the source location of this initializer directly to
+ the list node, so we instead attach it to a dummy EMPTY_CLASS_EXPR
+ within the TREE_TYPE of the list node. */
+ TREE_TYPE (node) = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
+ SET_EXPR_LOCATION (TREE_TYPE (node),
+ make_location (token->location,
+ token->location, parser->lexer));
+ return node;
}
/* Parse a mem-initializer-id.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 524c0bfe2d6..721eb5262d6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26014,6 +26014,9 @@ tsubst_initializer_list (tree t, tree argvec)
if (decl)
{
init = build_tree_list (decl, init);
+ /* Carry over the dummy TREE_TYPE node containing the source
+ location. */
+ TREE_TYPE (init) = TREE_TYPE (t);
TREE_CHAIN (init) = inits;
inits = init;
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/mem-init1.C b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
new file mode 100644
index 00000000000..b749c72cd8b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
@@ -0,0 +1,29 @@
+// PR c++/94024
+// { dg-do compile }
+
+struct A {
+ A()
+ : a() // { dg-error "reference type" }
+ , b(1) // { dg-error "incompatible" }
+ , c(0) // { dg-bogus "" }
+ {}
+
+ int &a;
+ int b[1];
+ char c;
+};
+
+template<typename T, typename U>
+struct B {
+ B()
+ : a() // { dg-error "reference type" }
+ , b(1) // { dg-error "incompatible" }
+ , c(0) // { dg-bogus "" }
+ {}
+
+ T a;
+ U b;
+ char c;
+};
+
+B<int&, int[1]> b;
--
2.28.0.89.g85b4e0a6dc
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: Member initializer list diagnostic locations [PR94024]
2020-08-03 18:49 ` Patrick Palka
@ 2020-08-03 20:10 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2020-08-03 20:10 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches
On 8/3/20 2:49 PM, Patrick Palka wrote:
> On Mon, 3 Aug 2020, Jason Merrill wrote:
>
>> On 8/3/20 10:14 AM, Patrick Palka wrote:
>>> This patch preserves the source locations of each node in a member
>>> initializer list so that during processing of the list we can set
>>> input_location appropriately for generally more accurate diagnostic
>>> locations. Since TREE_LIST nodes are tcc_exceptional, they can't have
>>> source locations, so we instead store the location in a dummy
>>> tcc_expression node within the TREE_TYPE of the list node.
>>
>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to
>>> commit?
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> PR c++/94024
>>> * init.c (sort_mem_initializers): Preserve TREE_TYPE of the
>>> member initializer list node.
>>> (emit_mem_initializers): Set input_location when performing each
>>> member initialization.
>>> * parser.c (cp_parser_mem_initializer_list): Attach the source
>>> location of this initializer to a dummy EMPTY_CLASS_EXPR within
>>> the TREE_TYPE of the list node.
>>> * pt.c (tsubst_initializer_list): Preserve TREE_TYPE of the
>>> member initializer list node.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> PR c++/94024
>>> * g++.dg/diagnostic/mem-init1.C: New test.
>>> ---
>>> gcc/cp/init.c | 6 +++++
>>> gcc/cp/parser.c | 8 ++++++
>>> gcc/cp/pt.c | 3 +++
>>> gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++
>>> 4 files changed, 46 insertions(+)
>>> create mode 100644 gcc/testsuite/g++.dg/diagnostic/mem-init1.C
>>>
>>> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
>>> index cb9bd2dbfba..3f089404cf2 100644
>>> --- a/gcc/cp/init.c
>>> +++ b/gcc/cp/init.c
>>> @@ -1151,6 +1151,8 @@ sort_mem_initializers (tree t, tree mem_inits)
>>> /* Record the initialization. */
>>> TREE_VALUE (subobject_init) = TREE_VALUE (init);
>>> + /* Carry over the dummy TREE_TYPE node containing the source
>>> location. */
>>> + TREE_TYPE (subobject_init) = TREE_TYPE (init);
>>> next_subobject = subobject_init;
>>> }
>>> @@ -1367,6 +1369,10 @@ emit_mem_initializers (tree mem_inits)
>>> /* Initialize the data members. */
>>> while (mem_inits)
>>> {
>>> + /* If this initializer was explicitly provided, then the dummy
>>> TREE_TYPE
>>> + node contains the source location. */
>>> + iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
>>> +
>>> perform_member_init (TREE_PURPOSE (mem_inits),
>>> TREE_VALUE (mem_inits));
>>> mem_inits = TREE_CHAIN (mem_inits);
>>> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>>> index ab088874ba7..2f9b8786121 100644
>>> --- a/gcc/cp/parser.c
>>> +++ b/gcc/cp/parser.c
>>> @@ -15326,6 +15326,14 @@ cp_parser_mem_initializer_list (cp_parser* parser)
>>> {
>>> TREE_CHAIN (mem_initializer) = mem_initializer_list;
>>> mem_initializer_list = mem_initializer;
>>> +
>>> + /* We can't attach the source location of this initializer directly
>>> to
>>> + the list node, so we instead attach it to a dummy
>>> EMPTY_CLASS_EXPR
>>> + within the TREE_TYPE of the list node. */
>>> + TREE_TYPE (mem_initializer) = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
>>> + SET_EXPR_LOCATION (TREE_TYPE (mem_initializer),
>>> + make_location (token->location,
>>> + token->location, input_location));
>>
>> Why not do this in cp_parser_mem_initializer?
>>
>> Also, use parser->lexer for the last argument to make_location.
>
> That's a much better spot for it :) Done and done. Does the following
> look OK after testing completes?
OK.
> -- >8 --
>
> Subject: [PATCH] c++: Member initializer list diagnostic locations [PR94024]
>
> This patch preserves the source locations of each node in a member
> initializer list so that during processing of the list we can set
> input_location appropriately for generally more accurate diagnostic
> locations. Since TREE_LIST nodes are tcc_exceptional, they can't have
> source locations, so we instead store the location in a dummy
> tcc_expression node within the TREE_TYPE of the list node.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to
> commit?
>
> gcc/cp/ChangeLog:
>
> PR c++/94024
> * init.c (sort_mem_initializers): Preserve TREE_TYPE of the
> member initializer list node.
> (emit_mem_initializers): Set input_location when performing each
> member initialization.
> * parser.c (cp_parser_mem_initializer): Attach the source
> location of this initializer to a dummy EMPTY_CLASS_EXPR
> within the TREE_TYPE of the list node.
> * pt.c (tsubst_initializer_list): Preserve TREE_TYPE of the
> member initializer list node.
>
> gcc/testsuite/ChangeLog:
>
> PR c++/94024
> * g++.dg/diagnostic/mem-init1.C: New test.
> ---
> gcc/cp/init.c | 6 +++++
> gcc/cp/parser.c | 13 ++++++++-
> gcc/cp/pt.c | 3 +++
> gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++
> 4 files changed, 50 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/g++.dg/diagnostic/mem-init1.C
>
> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> index cb9bd2dbfba..3f089404cf2 100644
> --- a/gcc/cp/init.c
> +++ b/gcc/cp/init.c
> @@ -1151,6 +1151,8 @@ sort_mem_initializers (tree t, tree mem_inits)
>
> /* Record the initialization. */
> TREE_VALUE (subobject_init) = TREE_VALUE (init);
> + /* Carry over the dummy TREE_TYPE node containing the source location. */
> + TREE_TYPE (subobject_init) = TREE_TYPE (init);
> next_subobject = subobject_init;
> }
>
> @@ -1367,6 +1369,10 @@ emit_mem_initializers (tree mem_inits)
> /* Initialize the data members. */
> while (mem_inits)
> {
> + /* If this initializer was explicitly provided, then the dummy TREE_TYPE
> + node contains the source location. */
> + iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
> +
> perform_member_init (TREE_PURPOSE (mem_inits),
> TREE_VALUE (mem_inits));
> mem_inits = TREE_CHAIN (mem_inits);
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index ab088874ba7..8b11e478c83 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -15411,7 +15411,18 @@ cp_parser_mem_initializer (cp_parser* parser)
>
> in_base_initializer = 0;
>
> - return member ? build_tree_list (member, expression_list) : error_mark_node;
> + if (!member)
> + return error_mark_node;
> +
> + tree node = build_tree_list (member, expression_list);
> + /* We can't attach the source location of this initializer directly to
> + the list node, so we instead attach it to a dummy EMPTY_CLASS_EXPR
> + within the TREE_TYPE of the list node. */
> + TREE_TYPE (node) = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
> + SET_EXPR_LOCATION (TREE_TYPE (node),
> + make_location (token->location,
> + token->location, parser->lexer));
> + return node;
> }
>
> /* Parse a mem-initializer-id.
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 524c0bfe2d6..721eb5262d6 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -26014,6 +26014,9 @@ tsubst_initializer_list (tree t, tree argvec)
> if (decl)
> {
> init = build_tree_list (decl, init);
> + /* Carry over the dummy TREE_TYPE node containing the source
> + location. */
> + TREE_TYPE (init) = TREE_TYPE (t);
> TREE_CHAIN (init) = inits;
> inits = init;
> }
> diff --git a/gcc/testsuite/g++.dg/diagnostic/mem-init1.C b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
> new file mode 100644
> index 00000000000..b749c72cd8b
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/mem-init1.C
> @@ -0,0 +1,29 @@
> +// PR c++/94024
> +// { dg-do compile }
> +
> +struct A {
> + A()
> + : a() // { dg-error "reference type" }
> + , b(1) // { dg-error "incompatible" }
> + , c(0) // { dg-bogus "" }
> + {}
> +
> + int &a;
> + int b[1];
> + char c;
> +};
> +
> +template<typename T, typename U>
> +struct B {
> + B()
> + : a() // { dg-error "reference type" }
> + , b(1) // { dg-error "incompatible" }
> + , c(0) // { dg-bogus "" }
> + {}
> +
> + T a;
> + U b;
> + char c;
> +};
> +
> +B<int&, int[1]> b;
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-08-03 20:10 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-03 14:14 [PATCH] c++: Member initializer list diagnostic locations [PR94024] Patrick Palka
2020-08-03 15:17 ` Jason Merrill
2020-08-03 18:49 ` Patrick Palka
2020-08-03 20:10 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).