From f4ab82085f180b7264407ce7f0920eefd73d8010 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 18 Jul 2017 17:35:13 -0400
Subject: [PATCH 07/27] C++: use BLT to highlight parameter of callee decl for
 mismatching types

This patch uses the BLT infrastructure to improve:

  extern int callee_1 (int one, const char *two, float three);

  int test_1 (int first, int second, float third)
  {
    return callee_1 (first, second, third);
  }

from:

  error: invalid conversion from 'int' to 'const char*' [-fpermissive]
   return callee_1 (first, second, third);
                                        ^
  note:   initializing argument 2 of 'int callee_1(int, const char*, float)'
   extern int callee_1 (int one, const char *two, float three);
              ^~~~~~~~

to:

  error: invalid conversion from 'int' to 'const char*' [-fpermissive]
   return callee_1 (first, second, third);
                                        ^
  note:   initializing argument 2 of 'int callee_1(int, const char*, float)'
   extern int callee_1 (int one, const char *two, float three);
                                 ^~~~~~~~~~~~~~~

by locating the pertinent parameter within the decl, by traversing the
BLT tree (if present).

gcc/cp/ChangeLog:
	* call.c: Include "blt.h".
	(get_blt_node_for_function_decl): New function.
	(get_fndecl_argument_location): New function.
	(convert_like_real): Use the above when determining the location
	for the note about a mismatching argument.

gcc/testsuite/ChangeLog:
	* g++.dg/diagnostic/param-type-mismatch.C: Add -fblt to the
	options.  Update expected output to show that the pertinent
	callee parameters are underlined.
---
 gcc/cp/call.c                                      | 79 +++++++++++++++++++++-
 .../g++.dg/diagnostic/param-type-mismatch.C        | 21 +++---
 2 files changed, 86 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fac6b6c..99693df 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "c-family/c-objc.h"
 #include "internal-fn.h"
+#include "blt.h"
 
 /* The various kinds of conversion.  */
 
@@ -6590,6 +6591,77 @@ maybe_print_user_conv_context (conversion *convs)
 	}
 }
 
+/* Attempt to locate the blt_node for FNDECL, or return NULL
+   if not found (or blt was not enabled).  */
+
+static blt_node *
+get_blt_node_for_function_decl (tree fndecl)
+{
+  if (!flag_blt)
+    return NULL;
+
+  blt_node *node = blt_get_node_for_tree (fndecl);
+  if (node)
+    return node;
+
+  tree template_decl = DECL_TI_TEMPLATE (fndecl);
+  if (template_decl)
+    {
+      node = blt_get_node_for_tree (template_decl);
+      if (node)
+        return node;
+    }
+
+  return NULL;
+}
+
+/* Attempt to locate the parameter with the given index within
+   FNDECL, returning DECL_SOURCE_LOCATION (fndecl) if it can't
+   be found (or blt was not enabled).  */
+
+static location_t
+get_fndecl_argument_location (tree fndecl, int argnum)
+{
+  location_t loc = DECL_SOURCE_LOCATION (fndecl);
+  blt_node *node = get_blt_node_for_function_decl (fndecl);
+  if (!node)
+    return loc;
+
+  /* For "member-declaration", expect the "direct-declarator" to be
+     inside a "declarator".  */
+  if (node->get_kind () == BLT_MEMBER_DECLARATION)
+    {
+      node = node->get_first_child_of_kind (BLT_DECLARATOR);
+      if (!node)
+        return loc;
+      node = node->get_first_child_of_kind (BLT_DIRECT_DECLARATOR);
+      if (!node)
+        return loc;
+    }
+
+  if (node->get_kind () != BLT_DIRECT_DECLARATOR)
+    return loc;
+
+  blt_node *pdc
+    = node->get_first_child_of_kind (BLT_PARAMETER_DECLARATION_CLAUSE);
+  if (!pdc)
+    return loc;
+
+  blt_node *pdl = pdc->get_first_child_of_kind (BLT_PARAMETER_DECLARATION_LIST);
+  if (!pdl)
+    return loc;
+
+  auto_vec<blt_node *> params;
+  pdl->get_children_of_kind (params, BLT_PARAMETER_DECLARATION);
+
+  if (argnum >= (int)params.length ())
+    return loc;
+
+  blt_node *param = params[argnum];
+  return param->get_range ();
+}
+
+
 /* Perform the conversions in CONVS on the expression EXPR.  FN and
    ARGNUM are used for diagnostics.  ARGNUM is zero based, -1
    indicates the `this' argument of a method.  INNER is nonzero when
@@ -6691,8 +6763,11 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	complained = permerror (loc, "invalid conversion from %qH to %qI",
 				TREE_TYPE (expr), totype);
       if (complained && fn)
-	inform (DECL_SOURCE_LOCATION (fn),
-		"  initializing argument %P of %qD", argnum, fn);
+        {
+          location_t decl_loc = get_fndecl_argument_location (fn, argnum);
+          inform (decl_loc,
+                  "  initializing argument %P of %qD", argnum, fn);
+        }
 
       return cp_convert (totype, expr, complain);
     }
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index 864ead1..5c89098 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -1,12 +1,9 @@
-// { dg-options "-fdiagnostics-show-caret" }
+// { dg-options "-fdiagnostics-show-caret -fblt" }
 
 /* A collection of calls where argument 2 is of the wrong type.
 
    TODO: we should put the caret and underline for the diagnostic
-   at the second argument, rather than the close paren.
-
-   TODO: we should highlight the second parameter of the callee, rather
-   than its name.  */
+   at the second argument, rather than the close paren.  */
 
 /* decl, with argname.  */
 
@@ -22,7 +19,7 @@ int test_1 (int first, int second, float third)
   // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
   /* { dg-begin-multiline-output "" }
  extern int callee_1 (int one, const char *two, float three);
-            ^~~~~~~~
+                               ^~~~~~~~~~~~~~~
      { dg-end-multiline-output "" } */
 }
 
@@ -40,7 +37,7 @@ int test_2 (int first, int second, float third)
   // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
   /* { dg-begin-multiline-output "" }
  extern int callee_2 (int, const char *, float);
-            ^~~~~~~~
+                           ^~~~~~~~~~~~
      { dg-end-multiline-output "" } */
 }
 
@@ -61,7 +58,7 @@ int test_3 (int first, int second, float third)
   // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
   /* { dg-begin-multiline-output "" }
  static int callee_3 (int one, const char *two, float three)
-            ^~~~~~~~
+                               ^~~~~~~~~~~~~~~
      { dg-end-multiline-output "" } */
 }
 
@@ -78,7 +75,7 @@ int test_4 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s4 { static int member_1 (int one, const char *two, float three); };
-                        ^~~~~~~~
+                                           ^~~~~~~~~~~~~~~
      { dg-end-multiline-output "" } */
 }
 
@@ -96,7 +93,7 @@ int test_5 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s5 { int member_1 (int one, const char *two, float three); };
-                 ^~~~~~~~
+                                    ^~~~~~~~~~~~~~~
      { dg-end-multiline-output "" } */
 }
 
@@ -136,7 +133,7 @@ int test_7 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s7 { static int member_1 (int one, T two, float three); };
-                        ^~~~~~~~
+                                           ^~~~~
      { dg-end-multiline-output "" } */
 }
 
@@ -155,7 +152,7 @@ int test_8 (int first, int second, float third)
      { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
  struct s8 { int member_1 (int one, T two, float three); };
-                 ^~~~~~~~
+                                    ^~~~~
      { dg-end-multiline-output "" } */
 }
 
-- 
1.8.5.3

