From c78382d98b23327cbefea3d105a681951a651569 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 13 Jul 2018 12:45:13 -0400
Subject: [PATCH 19/24] FIXME: WIP on PR c++/43064 ("improve location and text
 of diagnostics in constructor initializer lists")

---
 gcc/cp/call.c                         | 10 ++++++----
 gcc/cp/parser.c                       |  4 +++-
 gcc/cp/typeck.c                       |  4 ----
 gcc/testsuite/g++.dg/init/pr43064-1.C | 19 +++++++++++++++++++
 gcc/testsuite/g++.dg/init/pr43064-2.C | 32 ++++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/init/pr43064-3.C | 32 ++++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/init/pr43064-4.C | 18 ++++++++++++++++++
 7 files changed, 110 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-1.C
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-2.C
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-3.C
 create mode 100644 gcc/testsuite/g++.dg/init/pr43064-4.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f2b34b5..8042ab5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6642,8 +6642,8 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
   if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
       && ARITHMETIC_TYPE_P (totype))
     {
-      source_location loc =
-	expansion_point_location_if_in_system_header (input_location);
+      location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+      loc = expansion_point_location_if_in_system_header (loc);
 
       if (fn)
 	warning_at (loc, OPT_Wconversion_null,
@@ -6658,12 +6658,14 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
   else if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
 	   && TYPE_PTR_P (totype))
     {
+      location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+
       if (fn)
-	warning_at (input_location, OPT_Wconversion_null,
+	warning_at (loc, OPT_Wconversion_null,
 		    "converting %<false%> to pointer type for argument %P "
 		    "of %qD", argnum, fn);
       else
-	warning_at (input_location, OPT_Wconversion_null,
+	warning_at (loc, OPT_Wconversion_null,
 		    "converting %<false%> to pointer type %qT", totype);
     }
   /* Handle zero as null pointer warnings for cases other
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a7d8895..5110751 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14642,7 +14642,9 @@ cp_parser_mem_initializer (cp_parser* parser)
       vec = cp_parser_parenthesized_expression_list (parser, non_attr,
 						     /*cast_p=*/false,
 						     /*allow_expansion_p=*/true,
-						     /*non_constant_p=*/NULL);
+						     /*non_constant_p=*/NULL,
+						     /*close_paren_loc=*/NULL,
+						     /*wrap_locations_p=*/true);
       if (vec == NULL)
 	return error_mark_node;
       expression_list = build_tree_list_vec (vec);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 67f20d7..2351b9b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8802,10 +8802,6 @@ convert_for_assignment (tree type, tree rhs,
   tree rhstype;
   enum tree_code coder;
 
-  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
-  if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
-    rhs = TREE_OPERAND (rhs, 0);
-
   /* Handle [dcl.init.list] direct-list-initialization from
      single element of enumeration with a fixed underlying type.  */
   if (is_direct_enum_init (type, rhs))
diff --git a/gcc/testsuite/g++.dg/init/pr43064-1.C b/gcc/testsuite/g++.dg/init/pr43064-1.C
new file mode 100644
index 0000000..55079a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-1.C
@@ -0,0 +1,19 @@
+/* Verify that errors about member initializers appear at the bad value,
+   rather than on the last token of the final initializer.  */
+
+// { dg-do compile }
+// { dg-options "-fdiagnostics-show-caret" }
+
+class X {
+  X() : bad(42), // { dg-error "invalid conversion from 'int' to 'void\\*'" }
+	good(42)
+  { }
+  
+  void* bad;
+  int good;
+
+  /* { dg-begin-multiline-output "" }
+   X() : bad(42),
+             ^~
+     { dg-end-multiline-output "" } */
+};
diff --git a/gcc/testsuite/g++.dg/init/pr43064-2.C b/gcc/testsuite/g++.dg/init/pr43064-2.C
new file mode 100644
index 0000000..a4e8cd1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-2.C
@@ -0,0 +1,32 @@
+/* Verify that warnings about member initializers appear at the bad value,
+   rather than on the last token of the final initializer.  */
+
+// { dg-do compile }
+// { dg-options "-Wconversion-null -fdiagnostics-show-caret" }
+
+#define NULL ((void *)0) // { dg-error "invalid conversion from 'void\\*' to 'int'" }
+/* { dg-begin-multiline-output "" }
+ #define NULL ((void *)0)
+              ~^~~~~~~~~~
+   { dg-end-multiline-output "" } */
+
+class A
+{
+public:
+  A();
+  bool m_bool;
+  int m_int;
+  void *m_ptr;
+};
+
+A::A()
+  : m_bool(NULL),
+    m_int(NULL), // { dg-message "in expansion of macro 'NULL'" }
+    m_ptr(NULL)
+{
+}
+
+/* { dg-begin-multiline-output "" }
+     m_int(NULL),
+           ^~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/init/pr43064-3.C b/gcc/testsuite/g++.dg/init/pr43064-3.C
new file mode 100644
index 0000000..36726a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-3.C
@@ -0,0 +1,32 @@
+/* Verify that warnings about member initializers appear at the bad value,
+   rather than on the last token of the final initializer.  */
+
+// { dg-do compile }
+// { dg-options "-Wconversion-null -fdiagnostics-show-caret" }
+
+#define NULL __null // { dg-warning "converting to non-pointer type 'int' from NULL" }
+/* { dg-begin-multiline-output "" }
+ #define NULL __null
+              ^~~~~~
+   { dg-end-multiline-output "" } */
+
+class A
+{
+public:
+  A();
+  bool m_bool;
+  int m_int;
+  void *m_ptr;
+};
+
+A::A()
+  : m_bool(NULL),
+    m_int(NULL), // { dg-message "in expansion of macro 'NULL'" }
+    m_ptr(NULL)
+{
+}
+
+/* { dg-begin-multiline-output "" }
+     m_int(NULL),
+           ^~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/init/pr43064-4.C b/gcc/testsuite/g++.dg/init/pr43064-4.C
new file mode 100644
index 0000000..830ddf6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr43064-4.C
@@ -0,0 +1,18 @@
+// { dg-do compile }
+// { dg-options "-fdiagnostics-show-caret" }
+
+class A {};
+class B {};
+
+struct t1
+{
+  A m_a;
+  int m_int;
+
+  /* The type mismatch for the member initializer for "m_a" should be
+     reported there, rather than on the final token (for "m_int").  */
+  t1(B b)
+    : m_a (b),
+      m_int (42)
+  {}
+};
-- 
1.8.5.3

