From b2f7527f3ba8e9e2e8148c9727f05cdab343931b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 16 Dec 2015 17:18:41 -0500
Subject: [PATCH 14/31] FIXME: C FE: improvements to errors for bad arguments

---
 gcc/c/c-parser.c                                   |  1 +
 gcc/c/c-typeck.c                                   | 16 +++----
 .../gcc.dg/diagnostic-range-bad-arguments.c        | 51 ++++++++++++++++++++++
 3 files changed, 60 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/diagnostic-range-bad-arguments.c

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7f491f1..4c8ffb5 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -8647,6 +8647,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
       if (literal_zero_mask)
 	c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
       expr = c_parser_expr_no_commas (parser, NULL);
+      loc = EXPR_LOC_OR_LOC (expr.value, loc);
       if (convert_p)
 	expr = convert_lvalue_to_rvalue (loc, expr, true, true);
       if (fold_p)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 7c6241c..29e3155 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6050,9 +6050,9 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (pedwarn (PLOC, OPT, AR, parmnum, rname))			 \
-          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))	         \
-		  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,		 \
+        if (pedwarn (PLOC, OPT, AR, parmnum, rname))                    \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
+                 ? DECL_SOURCE_LOCATION (fundecl) : PLOC,       \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -6080,8 +6080,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
       {                                                                  \
       case ic_argpass:                                                   \
         if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS))		 \
-          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))	         \
-		  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,		 \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
+                 ? DECL_SOURCE_LOCATION (fundecl) : PLOC,       \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -6108,9 +6108,9 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS))           \
+        if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS))          \
           inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
-                  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,               \
+                  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,      \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -6685,7 +6685,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   switch (errtype)
     {
     case ic_argpass:
-      error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
+      error_at (location, "incompatible type for argument %d of %qE", parmnum,
 		rname);
       inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
 	      ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
diff --git a/gcc/testsuite/gcc.dg/diagnostic-range-bad-arguments.c b/gcc/testsuite/gcc.dg/diagnostic-range-bad-arguments.c
new file mode 100644
index 0000000..2e5406f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diagnostic-range-bad-arguments.c
@@ -0,0 +1,51 @@
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+extern void test_callee (int first, const char *second, int third);
+
+void test_bad_argument_types (int first, int second, int third)
+{
+  test_callee (first, first + second + third, third); /* { dg-warning "passing argument 2 of 'test_callee' makes pointer from integer without a cast" }  */
+
+/*
+{ dg-begin-multiline-output "" }
+   test_callee (first, first + second + third, third);
+                       ~~~~~~~~~~~~~~~^~~~~~~
+{ dg-end-multiline-output "" }
+{ dg-begin-multiline-output "" }
+ extern void test_callee (int first, const char *second, int third);
+             ^~~~~~~~~~~
+{ dg-end-multiline-output "" }
+TODO: ideally we ought to highlight the specific param in the decl;
+however FUNCTION_DECL doesn't seem to store the locations of the params,
+just the types.
+*/
+
+  test_callee (first, &first, third); /* { dg-warning "passing argument 2 of 'test_callee' from incompatible pointer type" } */
+
+/*
+{ dg-begin-multiline-output "" }
+   test_callee (first, &first, third);
+                       ^~~~~~
+{ dg-end-multiline-output "" }
+{ dg-begin-multiline-output "" }
+ extern void test_callee (int first, const char *second, int third);
+             ^~~~~~~~~~~
+{ dg-end-multiline-output "" }
+TODO: again, we ought to highlight the specific param in the decl
+*/
+
+  test_callee ("hello world", "", third); /* { dg-warning "passing argument 1 of 'test_callee' makes integer from pointer without a cast" } */
+
+/*
+{ dg-begin-multiline-output "" }
+   test_callee ("hello world", "", third);
+                ^~~~~~~~~~~~~
+{ dg-end-multiline-output "" }
+{ dg-begin-multiline-output "" }
+ extern void test_callee (int first, const char *second, int third);
+             ^~~~~~~~~~~
+{ dg-end-multiline-output "" }
+TODO: and again, we ought to highlight the specific param in the decl
+*/
+
+}
-- 
1.8.5.3

