From af769065ffae4e5f4857f984dd108d3fb504938e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 27 Aug 2015 21:01:48 -0400
Subject: [PATCH 48/66] FIXME: C FE: Use ranges for rhs in
 convert_for_assignment (uses EXPR_LOCATION_RANGE)

---
 gcc/c/c-typeck.c                           | 55 ++++++++++++++++--------------
 gcc/testsuite/gcc.dg/diagnostic-ranges-2.c | 43 +++++++++++++++++++++++
 2 files changed, 73 insertions(+), 25 deletions(-)

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 5ad202a..db63d7a 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2882,6 +2882,9 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
 
+  if (TREE_CODE (function) == SOURCE_RANGE)
+    function = TREE_OPERAND (function, 0);
+
   /* Convert anything with function type to a pointer-to-function.  */
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
@@ -5738,6 +5741,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
+  source_range rhs_range = EXPR_LOCATION_RANGE (rhs);
+
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -5760,14 +5765,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;                                                           \
@@ -5789,14 +5794,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;                                                           \
@@ -5818,14 +5823,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;                                                           \
@@ -5885,7 +5890,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 "
@@ -6050,7 +6055,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 "
@@ -6067,7 +6072,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"),
@@ -6158,7 +6163,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:
@@ -6187,7 +6192,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);
@@ -6234,7 +6239,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"),
@@ -6252,7 +6257,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 *%>"),
@@ -6277,7 +6282,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"),
@@ -6296,7 +6301,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 "
@@ -6315,7 +6320,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 "
@@ -6332,7 +6337,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"),
@@ -6356,7 +6361,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"),
@@ -6371,7 +6376,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"),
@@ -6396,7 +6401,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-ranges-2.c b/gcc/testsuite/gcc.dg/diagnostic-ranges-2.c
index 80fc2d1..9a2f77b 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-ranges-2.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-ranges-2.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

