aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-08-04 10:11:35 -0400
committerPatrick Palka <ppalka@redhat.com>2020-08-04 10:11:35 -0400
commit843710c037c1396dcdbc23e5b6b456b8ae6e2b8b (patch)
tree75dae029db26c025f3c25904c70b1cec9057bd9e /gcc
parent1af5cdd77985daf76130f527deac425c43df9f49 (diff)
downloadgcc-843710c037c1396dcdbc23e5b6b456b8ae6e2b8b.zip
gcc-843710c037c1396dcdbc23e5b6b456b8ae6e2b8b.tar.gz
gcc-843710c037c1396dcdbc23e5b6b456b8ae6e2b8b.tar.bz2
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. 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/init.c6
-rw-r--r--gcc/cp/parser.c15
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/mem-init1.C29
4 files changed, 52 insertions, 1 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index cb9bd2d..3f08940 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 ab08887..7657145 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15411,7 +15411,20 @@ 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. */
+ location_t loc
+ = make_location (token->location, token->location, parser->lexer);
+ tree dummy = build0 (EMPTY_CLASS_EXPR, NULL_TREE);
+ SET_EXPR_LOCATION (dummy, loc);
+ TREE_TYPE (node) = dummy;
+
+ return node;
}
/* Parse a mem-initializer-id.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bd2af8b..cff2db4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26018,6 +26018,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 0000000..b749c72
--- /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;