From e48de2e5d0fdb4e01447f7b02415fd14ec96729c Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 3 Sep 2015 15:12:05 -0400
Subject: [PATCH 35/63] FIXME: C FE: Use ranges for rhs in
 convert_for_assignment (compiles, testcases fail for some reason, no
 ChangeLog)

(also had: "Bulletproof c-typeck.c:convert_for_assignment (was using for callsite args, but other users might not have a range")

Now has: FIXME: inform_declaration: use DECL_LOCATION_RANGE rather than DECL_SOURCE_LOCATION

I'd thought that the testcase failures were due to missing range of
inform_declaration, but it has it now, and the test outputs look right;
maybe some regex issue?
---
 gcc/c/c-typeck.c                                   | 59 ++++++++++++----------
 gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c | 43 ++++++++++++++++
 2 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 7178b0b..f984ee9 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2851,7 +2851,7 @@ static void
 inform_declaration (tree decl)
 {
   if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_IS_BUILTIN (decl)))
-    inform (DECL_SOURCE_LOCATION (decl), "declared here");
+    inform (DECL_LOCATION_RANGE (decl), "declared here");
 }
 
 /* Build a function call to function FUNCTION with parameters PARAMS.
@@ -5712,6 +5712,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
+  source_range rhs_range;
+
+  if (CAN_HAVE_RANGE_P (rhs))
+    rhs_range = EXPR_LOCATION_RANGE (rhs);
+  else
+    rhs_range = source_range::from_location (expr_loc);
+
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -5734,14 +5741,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   /* This macro is used to emit diagnostics to ensure that all format
      strings are complete sentences, visible to gettext and checked at
      compile time.  */
-#define PEDWARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE)	 \
+#define PEDWARN_FOR_ASSIGNMENT(LOCATION, RANGE, OPT, AR, AS, IN, RE)	 \
   do {                                                                   \
     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 (RANGE, OPT, AR, parmnum, rname))                    \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
+                 ? DECL_SOURCE_LOCATION (fundecl) : RANGE.m_start,       \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -5763,14 +5770,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
      strings are complete sentences, visible to gettext and checked at
      compile time.  It is the same as PEDWARN_FOR_ASSIGNMENT but with an
      extra parameter to enumerate qualifiers.  */
-#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+#define PEDWARN_FOR_QUALIFIERS(LOCATION, RANGE, OPT, AR, AS, IN, RE, QUALS) \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS))		 \
-          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))	         \
-		  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,		 \
+        if (pedwarn (RANGE, OPT, AR, parmnum, rname, QUALS))		 \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
+                 ? DECL_SOURCE_LOCATION (fundecl) : RANGE.m_start,       \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -5792,14 +5799,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
      strings are complete sentences, visible to gettext and checked at
      compile time.  It is the same as PEDWARN_FOR_QUALIFIERS but uses
      warning_at instead of pedwarn.  */
-#define WARNING_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+#define WARNING_FOR_QUALIFIERS(LOCATION, RANGE, OPT, AR, AS, IN, RE, QUALS) \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS))           \
+        if (warning_at (RANGE, OPT, AR, parmnum, rname, QUALS))          \
           inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
-                  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,               \
+                  ? DECL_SOURCE_LOCATION (fundecl) : RANGE.m_start,      \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -5859,7 +5866,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	  && TREE_CODE (type) == ENUMERAL_TYPE
 	  && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
 	{
-	  PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
+	  PEDWARN_FOR_ASSIGNMENT (location, rhs_range, OPT_Wc___compat,
 			          G_("enum conversion when passing argument "
 				     "%d of %qE is invalid in C++"),
 			          G_("enum conversion in assignment is "
@@ -6024,7 +6031,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 		     vice-versa.  */
 		  if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
 		      & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-		    PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+		    PEDWARN_FOR_QUALIFIERS (location, rhs_range,
 					    OPT_Wdiscarded_qualifiers,
 					    G_("passing argument %d of %qE "
 					       "makes %q#v qualified function "
@@ -6041,7 +6048,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 		}
 	      else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
 		       & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
-		PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+		PEDWARN_FOR_QUALIFIERS (location, rhs_range,
 				        OPT_Wdiscarded_qualifiers,
 				        G_("passing argument %d of %qE discards "
 					   "%qv qualifier from pointer target type"),
@@ -6132,7 +6139,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	  switch (errtype)
 	    {
 	    case ic_argpass:
-	      error_at (expr_loc, "passing argument %d of %qE from pointer to "
+	      error_at (rhs_range, "passing argument %d of %qE from pointer to "
 			"non-enclosed address space", parmnum, rname);
 	      break;
 	    case ic_assign:
@@ -6161,7 +6168,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	  switch (errtype)
 	  {
 	  case ic_argpass:
-	    warning_at (expr_loc, OPT_Wsuggest_attribute_format,
+	    warning_at (rhs_range, OPT_Wsuggest_attribute_format,
 			"argument %d of %qE might be "
 			"a candidate for a format attribute",
 			parmnum, rname);
@@ -6208,7 +6215,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 
 	      if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
 		  & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
-		WARNING_FOR_QUALIFIERS (location, expr_loc,
+		WARNING_FOR_QUALIFIERS (location, rhs_range,
 				        OPT_Wdiscarded_array_qualifiers,
 				        G_("passing argument %d of %qE discards "
 					   "%qv qualifier from pointer target type"),
@@ -6226,7 +6233,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 		  (VOID_TYPE_P (ttr)
 		   && !null_pointer_constant
 		   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-	    PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
+	    PEDWARN_FOR_ASSIGNMENT (location, rhs_range, OPT_Wpedantic,
 				    G_("ISO C forbids passing argument %d of "
 				       "%qE between function pointer "
 				       "and %<void *%>"),
@@ -6251,7 +6258,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	      if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
 		  & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
 		{
-		  PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+		  PEDWARN_FOR_QUALIFIERS (location, rhs_range,
 				          OPT_Wdiscarded_qualifiers,
 				          G_("passing argument %d of %qE discards "
 					     "%qv qualifier from pointer target type"),
@@ -6270,7 +6277,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 		;
 	      /* If there is a mismatch, do warn.  */
 	      else if (warn_pointer_sign)
-		 PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
+		 PEDWARN_FOR_ASSIGNMENT (location, rhs_range, OPT_Wpointer_sign,
 				         G_("pointer targets in passing argument "
 					    "%d of %qE differ in signedness"),
 				         G_("pointer targets in assignment "
@@ -6289,7 +6296,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 		 where an ordinary one is wanted, but not vice-versa.  */
 	      if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
 		  & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-		PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+		PEDWARN_FOR_QUALIFIERS (location, rhs_range,
 				        OPT_Wdiscarded_qualifiers,
 				        G_("passing argument %d of %qE makes "
 					   "%q#v qualified function pointer "
@@ -6306,7 +6313,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
       else
 	/* Avoid warning about the volatile ObjC EH puts on decls.  */
 	if (!objc_ok)
-	  PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+	  PEDWARN_FOR_ASSIGNMENT (location, rhs_range,
 			          OPT_Wincompatible_pointer_types,
 			          G_("passing argument %d of %qE from "
 				     "incompatible pointer type"),
@@ -6330,7 +6337,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	 or one that results from arithmetic, even including
 	 a cast to integer type.  */
       if (!null_pointer_constant)
-	PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+	PEDWARN_FOR_ASSIGNMENT (location, rhs_range,
 			        OPT_Wint_conversion,
 			        G_("passing argument %d of %qE makes "
 				   "pointer from integer without a cast"),
@@ -6345,7 +6352,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+      PEDWARN_FOR_ASSIGNMENT (location, rhs_range,
 			      OPT_Wint_conversion,
 			      G_("passing argument %d of %qE makes integer "
 			         "from pointer without a cast"),
@@ -6370,7 +6377,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 (rhs_range, "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-tree-expr-ranges.c b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
index 80fc2d1..9a2f77b 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
@@ -14,3 +14,46 @@ void test_nonconst_static_assert (int i)
 { dg-end-multiline-output "" }
 */
 }
+
+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);
+                       ^~~~~~~~~~~~~~~~~~~~~~
+ extern void test_callee (int first, const char *second, int third);
+             ^
+{ dg-end-multiline-output "" }
+FIXME: we ought to highlight the specific param in the decl
+*/
+
+  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);
+                       ^~~~~~
+ extern void test_callee (int first, const char *second, int third);
+             ^
+{ dg-end-multiline-output "" }
+FIXME: 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);
+                ^~~~~~~~~~~~~
+ extern void test_callee (int first, const char *second, int third);
+             ^
+{ dg-end-multiline-output "" }
+FIXME: and again, we ought to highlight the specific param in the decl
+*/
+
+
+}
-- 
1.8.5.3

