From 843710c037c1396dcdbc23e5b6b456b8ae6e2b8b Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Tue, 4 Aug 2020 10:11:35 -0400 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. 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 | 15 ++++++++++- gcc/cp/pt.c | 3 +++ gcc/testsuite/g++.dg/diagnostic/mem-init1.C | 29 +++++++++++++++++++++ 4 files changed, 52 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..765714597b6 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 bd2af8b6679..cff2db4a07e 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 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 +struct B { + B() + : a() // { dg-error "reference type" } + , b(1) // { dg-error "incompatible" } + , c(0) // { dg-bogus "" } + {} + + T a; + U b; + char c; +}; + +B b; -- 2.30.2