[C PATCH] Backport a fix for PR62294 to 4.9

Marek Polacek polacek@redhat.com
Wed Sep 3 12:47:00 GMT 2014


On Tue, Sep 02, 2014 at 05:01:10PM +0000, Joseph S. Myers wrote:
> On Tue, 2 Sep 2014, Marek Polacek wrote:
> 
> > PR62294 reports that 4.9 does not emit an "incompatible pointer type"
> > warning in certain scenario.  I unknowingly broke this in r207335, and
> > then fixed it in r210980, which is a follow-up to the former.  But 4.9
> > doesn't have the latter.  This patch is basically a backport of r210980,
> > only without the traditional conversion stuff.
> > 
> > Bootstrapped/regtested on x86_64-linux, ok for 4.9?
> 
> OK with a testcase specifically for the regression case added on trunk and 
> 4.9 if there isn't one already.

Sure, I managed to create one.  I'll add the testcase onto trunk in a
separate patch.

Bootstrapped/regtested on x86_64-linux, applying to 4.9.

2014-09-03  Marek Polacek  <polacek@redhat.com>

	PR c/62294
	* c-typeck.c (convert_arguments): Get location of a parameter.  Change
	error and warning calls to error_at and warning_at.  Pass location of
	a parameter to it.
	(convert_for_assignment): Add parameter to WARN_FOR_ASSIGNMENT and
	WARN_FOR_QUALIFIERS.  Pass expr_loc to those.

	* gcc.dg/pr56724-1.c: New test.
	* gcc.dg/pr56724-2.c: New test.
	* gcc.dg/pr62294.c: New test.
	* gcc.dg/pr62294.h: New file.

diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index 5838d6a..d096ad4 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -3071,6 +3071,12 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
       bool excess_precision = false;
       bool npc;
       tree parmval;
+      /* Some __atomic_* builtins have additional hidden argument at
+	 position 0.  */
+      location_t ploc
+	= !arg_loc.is_empty () && values->length () == arg_loc.length ()
+	  ? expansion_point_location_if_in_system_header (arg_loc[parmnum])
+	  : input_location;
 
       if (type == void_type_node)
 	{
@@ -3113,7 +3119,8 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 
 	  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
 	    {
-	      error ("type of formal parameter %d is incomplete", parmnum + 1);
+	      error_at (ploc, "type of formal parameter %d is incomplete",
+			parmnum + 1);
 	      parmval = val;
 	    }
 	  else
@@ -3128,34 +3135,34 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 
 		  if (INTEGRAL_TYPE_P (type)
 		      && TREE_CODE (valtype) == REAL_TYPE)
-		    warning (0, "passing argument %d of %qE as integer "
-			     "rather than floating due to prototype",
-			     argnum, rname);
+		    warning_at (ploc, 0, "passing argument %d of %qE as "
+				"integer rather than floating due to "
+				"prototype", argnum, rname);
 		  if (INTEGRAL_TYPE_P (type)
 		      && TREE_CODE (valtype) == COMPLEX_TYPE)
-		    warning (0, "passing argument %d of %qE as integer "
-			     "rather than complex due to prototype",
-			     argnum, rname);
+		    warning_at (ploc, 0, "passing argument %d of %qE as "
+				"integer rather than complex due to "
+				"prototype", argnum, rname);
 		  else if (TREE_CODE (type) == COMPLEX_TYPE
 			   && TREE_CODE (valtype) == REAL_TYPE)
-		    warning (0, "passing argument %d of %qE as complex "
-			     "rather than floating due to prototype",
-			     argnum, rname);
+		    warning_at (ploc, 0, "passing argument %d of %qE as "
+				"complex rather than floating due to "
+				"prototype", argnum, rname);
 		  else if (TREE_CODE (type) == REAL_TYPE
 			   && INTEGRAL_TYPE_P (valtype))
-		    warning (0, "passing argument %d of %qE as floating "
-			     "rather than integer due to prototype",
-			     argnum, rname);
+		    warning_at (ploc, 0, "passing argument %d of %qE as "
+				"floating rather than integer due to "
+				"prototype", argnum, rname);
 		  else if (TREE_CODE (type) == COMPLEX_TYPE
 			   && INTEGRAL_TYPE_P (valtype))
-		    warning (0, "passing argument %d of %qE as complex "
-			     "rather than integer due to prototype",
-			     argnum, rname);
+		    warning_at (ploc, 0, "passing argument %d of %qE as "
+				"complex rather than integer due to "
+				"prototype", argnum, rname);
 		  else if (TREE_CODE (type) == REAL_TYPE
 			   && TREE_CODE (valtype) == COMPLEX_TYPE)
-		    warning (0, "passing argument %d of %qE as floating "
-			     "rather than complex due to prototype",
-			     argnum, rname);
+		    warning_at (ploc, 0, "passing argument %d of %qE as "
+				"floating rather than complex due to "
+				"prototype", argnum, rname);
 		  /* ??? At some point, messages should be written about
 		     conversions between complex types, but that's too messy
 		     to do now.  */
@@ -3166,9 +3173,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 			 since without a prototype it would be `double'.  */
 		      if (formal_prec == TYPE_PRECISION (float_type_node)
 			  && type != dfloat32_type_node)
-			warning (0, "passing argument %d of %qE as %<float%> "
-				 "rather than %<double%> due to prototype",
-				 argnum, rname);
+			warning_at (ploc, 0,
+				    "passing argument %d of %qE as %<float%> "
+				    "rather than %<double%> due to prototype",
+				    argnum, rname);
 
 		      /* Warn if mismatch between argument and prototype
 			 for decimal float types.  Warn of conversions with
@@ -3191,9 +3199,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 				   || (type == dfloat64_type_node
 				       && (valtype
 					   != dfloat32_type_node))))
-			warning (0, "passing argument %d of %qE as %qT "
-				 "rather than %qT due to prototype",
-				 argnum, rname, type, valtype);
+			warning_at (ploc, 0,
+				    "passing argument %d of %qE as %qT "
+				    "rather than %qT due to prototype",
+				    argnum, rname, type, valtype);
 
 		    }
 		  /* Detect integer changing in width or signedness.
@@ -3212,10 +3221,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 			   and the actual arg is that enum type.  */
 			;
 		      else if (formal_prec != TYPE_PRECISION (type1))
-			warning (OPT_Wtraditional_conversion,
-				 "passing argument %d of %qE "
-				 "with different width due to prototype",
-				 argnum, rname);
+			warning_at (ploc, OPT_Wtraditional_conversion,
+				    "passing argument %d of %qE "
+				    "with different width due to prototype",
+				    argnum, rname);
 		      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
 			;
 		      /* Don't complain if the formal parameter type
@@ -3236,14 +3245,15 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 			       && TYPE_UNSIGNED (valtype))
 			;
 		      else if (TYPE_UNSIGNED (type))
-			warning (OPT_Wtraditional_conversion,
-				 "passing argument %d of %qE "
-				 "as unsigned due to prototype",
-				 argnum, rname);
+			warning_at (ploc, OPT_Wtraditional_conversion,
+				    "passing argument %d of %qE "
+				    "as unsigned due to prototype",
+				    argnum, rname);
 		      else
-			warning (OPT_Wtraditional_conversion,
-				 "passing argument %d of %qE "
-				 "as signed due to prototype", argnum, rname);
+			warning_at (ploc, OPT_Wtraditional_conversion,
+				    "passing argument %d of %qE "
+				    "as signed due to prototype",
+				    argnum, rname);
 		    }
 		}
 
@@ -3252,13 +3262,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 	      if (excess_precision)
 		val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
 	      origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum];
-	      bool arg_loc_ok = !arg_loc.is_empty ()
-				/* Some __atomic_* builtins have additional
-				   hidden argument at position 0.  */
-				&& values->length () == arg_loc.length ();
-	      parmval = convert_for_assignment (loc,
-						arg_loc_ok ? arg_loc[parmnum]
-						: UNKNOWN_LOCATION, type,
+	      parmval = convert_for_assignment (loc, ploc, type,
 						val, origtype, ic_argpass,
 						npc, fundecl, function,
 						parmnum + 1);
@@ -3282,10 +3286,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 	    {
 	      /* Convert `float' to `double'.  */
 	      if (warn_double_promotion && !c_inhibit_evaluation_warnings)
-		warning_at (arg_loc[parmnum], OPT_Wdouble_promotion,
-			 "implicit conversion from %qT to %qT when passing "
-			 "argument to function",
-			 valtype, double_type_node);
+		warning_at (ploc, OPT_Wdouble_promotion,
+			    "implicit conversion from %qT to %qT when passing "
+			    "argument to function",
+			    valtype, double_type_node);
 	      parmval = convert (double_type_node, val);
 	    }
 	}
@@ -5591,14 +5595,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 WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)             	 \
+#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE)	 \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (pedwarn (LOCATION, OPT, AR, parmnum, rname))                 \
+        if (pedwarn (PLOC, OPT, AR, parmnum, rname))			 \
           inform ((fundecl && !DECL_IS_BUILTIN (fundecl))	         \
-	      	  ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,		 \
+		  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,		 \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -5621,22 +5625,22 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
      compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
      extra parameter to enumerate qualifiers.  */
 
-#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS)        \
+#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS)  \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS))          \
+        if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS))		 \
           inform ((fundecl && !DECL_IS_BUILTIN (fundecl))	         \
-	      	  ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,		 \
+		  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,		 \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
       case ic_assign:                                                    \
-        pedwarn (LOCATION, OPT, AS, QUALS);                          \
+        pedwarn (LOCATION, OPT, AS, QUALS);				 \
         break;                                                           \
       case ic_init:                                                      \
-        pedwarn (LOCATION, OPT, IN, QUALS);                          \
+        pedwarn (LOCATION, OPT, IN, QUALS);				 \
         break;                                                           \
       case ic_return:                                                    \
         pedwarn (LOCATION, OPT, RE, QUALS);                        	 \
@@ -5688,7 +5692,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))
 	{
-	  WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
+	  WARN_FOR_ASSIGNMENT (input_location, expr_loc, OPT_Wc___compat,
 			       G_("enum conversion when passing argument "
 				  "%d of %qE is invalid in C++"),
 			       G_("enum conversion in assignment is "
@@ -5851,7 +5855,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))
-		    WARN_FOR_QUALIFIERS (location, 0,
+		    WARN_FOR_QUALIFIERS (location, expr_loc, 0,
 					 G_("passing argument %d of %qE "
 					    "makes %q#v qualified function "
 					    "pointer from unqualified"),
@@ -5867,7 +5871,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))
-		WARN_FOR_QUALIFIERS (location, 0,
+		WARN_FOR_QUALIFIERS (location, expr_loc, 0,
 				     G_("passing argument %d of %qE discards "
 					"%qv qualifier from pointer target type"),
 				     G_("assignment discards %qv qualifier "
@@ -6029,7 +6033,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)))
-	    WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic,
+	    WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
 				 G_("ISO C forbids passing argument %d of "
 				    "%qE between function pointer "
 				    "and %<void *%>"),
@@ -6048,7 +6052,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))
 		{
-		  WARN_FOR_QUALIFIERS (location, 0,
+		  WARN_FOR_QUALIFIERS (location, expr_loc, 0,
 				       G_("passing argument %d of %qE discards "
 					  "%qv qualifier from pointer target type"),
 				       G_("assignment discards %qv qualifier "
@@ -6066,7 +6070,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)
-		WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
+		WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
 				     G_("pointer targets in passing argument "
 					"%d of %qE differ in signedness"),
 				     G_("pointer targets in assignment "
@@ -6085,7 +6089,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))
-		WARN_FOR_QUALIFIERS (location, 0,
+		WARN_FOR_QUALIFIERS (location, expr_loc, 0,
 				     G_("passing argument %d of %qE makes "
 					"%q#v qualified function pointer "
 					"from unqualified"),
@@ -6101,7 +6105,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)
-	  WARN_FOR_ASSIGNMENT (location, 0,
+	  WARN_FOR_ASSIGNMENT (location, expr_loc, 0,
 			       G_("passing argument %d of %qE from "
 				  "incompatible pointer type"),
 			       G_("assignment from incompatible pointer type"),
@@ -6124,7 +6128,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)
-	WARN_FOR_ASSIGNMENT (location, 0,
+	WARN_FOR_ASSIGNMENT (location, expr_loc, 0,
 			     G_("passing argument %d of %qE makes "
 				"pointer from integer without a cast"),
 			     G_("assignment makes pointer from integer "
@@ -6138,7 +6142,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (location, 0,
+      WARN_FOR_ASSIGNMENT (location, expr_loc, 0,
 			   G_("passing argument %d of %qE makes integer "
 			      "from pointer without a cast"),
 			   G_("assignment makes integer from pointer "
diff --git gcc/testsuite/gcc.dg/pr56724-1.c gcc/testsuite/gcc.dg/pr56724-1.c
index e69de29..4276c3f 100644
--- gcc/testsuite/gcc.dg/pr56724-1.c
+++ gcc/testsuite/gcc.dg/pr56724-1.c
@@ -0,0 +1,33 @@
+/* PR c/56724 */
+/* { dg-do compile } */
+/* { dg-options "-Wtraditional-conversion" } */
+
+extern void foo (int p[2][]); /* { dg-error "array type has incomplete element type" } */
+extern void foo_i (int, int);
+extern void foo_u (unsigned int);
+extern void foo_f (int, float);
+extern void foo_ll (long long);
+extern void foo_cd (int, int, __complex__ double);
+extern signed char sc;
+extern int i;
+extern unsigned int u;
+extern float f;
+extern double d;
+extern __complex__ double cd;
+
+void
+fn ()
+{
+  int p[1][1];
+  foo (p); /* { dg-error "8:type of formal parameter" } */
+  foo_i (1, f); /* { dg-warning "13:passing argument" } */
+  foo_i (1, cd); /* { dg-warning "13:passing argument" } */
+  foo_cd (1, 2, f); /* { dg-warning "17:passing argument" } */
+  foo_f (9, i); /* { dg-warning "13:passing argument" } */
+  foo_cd (2, 2, i); /* { dg-warning "17:passing argument" } */
+  foo_f (2, cd); /* { dg-warning "13:passing argument" } */
+  foo_f (2, d); /* { dg-warning "13:passing argument" } */
+  foo_ll (sc); /* { dg-warning "11:passing argument" } */
+  foo_u (i); /* { dg-warning "10:passing argument" } */
+  foo_i (1, u); /* { dg-warning "13:passing argument" } */
+}
diff --git gcc/testsuite/gcc.dg/pr56724-2.c gcc/testsuite/gcc.dg/pr56724-2.c
index e69de29..4abb7d8 100644
--- gcc/testsuite/gcc.dg/pr56724-2.c
+++ gcc/testsuite/gcc.dg/pr56724-2.c
@@ -0,0 +1,31 @@
+/* PR c/56724 */
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat -Wpedantic" } */
+
+enum E1 { A };
+enum E2 { B };
+extern void foo_E (enum E1);
+extern void foo_v (void *p);
+extern void foo_sc (int, int, signed char *);
+extern unsigned char *uc;
+extern signed char sc;
+extern const signed char *csc;
+extern float *f;
+
+void
+foo (void)
+{
+  void (*fp)(void);
+  const void (*ffp)(void);
+  foo_v (fp); /* { dg-warning "10:ISO C forbids passing argument" } */
+  foo_E (B); /* { dg-warning "10:enum conversion when passing argument" } */
+  foo_sc (1, 2, uc); /* { dg-warning "17:pointer targets in passing argument" } */
+  foo_sc (1, 2, f); /* { dg-warning "17:passing argument" } */
+  foo_sc (1, 2, sc); /* { dg-warning "17:passing argument" } */
+  foo_sc (uc, 2, &sc); /* { dg-warning "11:passing argument" } */
+  foo_sc (1, 2, csc); /* { dg-warning "17:passing argument" } */
+}
+
+typedef void (*fp)(void);
+typedef void (*nrfp)(void) __attribute__((noreturn));
+void f1 (nrfp); void f2 (fp x) { f1 (x); } extern int e; /* { dg-warning "38:passing argument" } */
diff --git gcc/testsuite/gcc.dg/pr62294.c gcc/testsuite/gcc.dg/pr62294.c
index e69de29..c6ec5a7 100644
--- gcc/testsuite/gcc.dg/pr62294.c
+++ gcc/testsuite/gcc.dg/pr62294.c
@@ -0,0 +1,10 @@
+/* PR c/62294 */
+/* { dg-do compile } */
+
+#include "pr62294.h"
+
+void
+fn (int *u)
+{
+  foo (u); /* { dg-error "passing argument 1 of .bar. from incompatible pointer type" } */
+}
diff --git gcc/testsuite/gcc.dg/pr62294.h gcc/testsuite/gcc.dg/pr62294.h
index e69de29..9be45ad 100644
--- gcc/testsuite/gcc.dg/pr62294.h
+++ gcc/testsuite/gcc.dg/pr62294.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+#define foo bar
+extern void foo (float *);

	Marek



More information about the Gcc-patches mailing list