This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] warning about const multidimensional array as function parameter



This patch implements a new proposed behaviour of diagnostics for 
pointers to arrays with qualifiers in C:

- No warning about 'incompatible pointer types' for pointers 
  to arrays with different qualifiers. 

- Instead, there is a new warning activated only with 
  '-pedantic': "pointers to arrays with different qualifiers"

- The usual warnings about loss of qualifiers when converting
  pointers now appear when converting pointers to arrays.


Strictly speaking the C standard considers such pointers to be
incompatible. This seems to be an unintentional consequence 
of how qualifiers are always attached to the element type. 
(I am trying to get the standard revised too.) The new 
behaviour should also be more compatible with C++.


With the patch the following code can be used without warning:

----
extern void transpose(int A, int B, double out[B][A], const double in[A][B]);

double in[A][B];
double out[A][B];

transpose(A, B, out, in);
----

Without the patch a cast would be required to pass in non-const arrays 
as a second argument which breaks type safety (e.g. a float array
could be passed). 



Note that this issue is different than the unsafe conversion from 
'char**' to 'const char** x' which is still not allowed.



The patch should apply cleanly to trunk. The actual changes are limited
to 'gcc/c/-typeck.c' and should affect only diagnostics.

I also changed the test cases and added a new test case. Changes in 
the expected warnings:

testsuite/gcc.dg/qual-component-1.c
testsuite/gcc.dg/Wwrite-strings-1.c
testsuite/gcc.dg/array-quals-2.c

New test case:

testsuite/gcc.dg/pointer-arrays-quals.c


Please let me know what you think.


Martin




Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c	(Revision 216690)
+++ gcc/c/c-typeck.c	(Arbeitskopie)
@@ -1217,6 +1217,7 @@ static int
 comp_target_types (location_t location, tree ttl, tree ttr)
 {
   int val;
+  int val2;
   tree mvl = TREE_TYPE (ttl);
   tree mvr = TREE_TYPE (ttr);
   addr_space_t asl = TYPE_ADDR_SPACE (mvl);
@@ -1228,19 +1229,31 @@ comp_target_types (location_t location,
   if (!addr_space_superset (asl, asr, &as_common))
     return 0;
 
-  /* Do not lose qualifiers on element types of array types that are
-     pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  if (TREE_CODE (mvl) != ARRAY_TYPE)
-    mvl = (TYPE_ATOMIC (mvl)
-	   ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
-	   : TYPE_MAIN_VARIANT (mvl));
-  if (TREE_CODE (mvr) != ARRAY_TYPE)
-    mvr = (TYPE_ATOMIC (mvr)
-	   ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
-	   : TYPE_MAIN_VARIANT (mvr));
+  /* For -pedantic record result of comptypes on arrays before loosing 
+     qualifiers on the element type below. */
+  val2 = 1;
+
+  if (TREE_CODE (mvl) == ARRAY_TYPE 
+        && TREE_CODE (mvr) == ARRAY_TYPE)
+    val2 = comptypes (mvl, mvr);
+
+  /* Qualifiers on element types of array types that are
+     pointer targets are lost by taking their TYPE_MAIN_VARIANT.  */
+
+  mvl = (TYPE_ATOMIC (mvl)
+	 ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
+	 : TYPE_MAIN_VARIANT (mvl));
+
+  mvr = (TYPE_ATOMIC (mvr)
+	 ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
+	 : TYPE_MAIN_VARIANT (mvr));
+
   enum_and_int_p = false;
   val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
 
+  if (val == 1 && val2 != 1)
+    pedwarn (location, OPT_Wpedantic, "pointers to arrays with different qualifiers");
+
   if (val == 2)
     pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
 
@@ -5961,7 +5974,7 @@ convert_for_assignment (location_t locat
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
       addr_space_t asl;
       addr_space_t asr;
-
+	
       if (TREE_CODE (mvl) != ARRAY_TYPE)
 	mvl = (TYPE_ATOMIC (mvl)
 	       ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl),
@@ -6083,6 +6096,16 @@ convert_for_assignment (location_t locat
 		  == c_common_signed_type (mvr))
 	      && TYPE_ATOMIC (mvl) == TYPE_ATOMIC (mvr)))
 	{
+          /* For arrays consider element type instead. This is required because
+             we warn about conversions for pointers to arrays with different
+             qualifiers on the element type only for -pedantic.  */
+          if (TREE_CODE (ttr) == ARRAY_TYPE
+              && TREE_CODE (ttl) == ARRAY_TYPE)
+            {
+              ttr = TREE_TYPE (ttr);
+              ttl = TREE_TYPE (ttl);
+            } 
+
 	  if (pedantic
 	      && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
 		  ||
Index: gcc/testsuite/gcc.dg/Wwrite-strings-1.c
===================================================================
--- gcc/testsuite/gcc.dg/Wwrite-strings-1.c	(Revision 216690)
+++ gcc/testsuite/gcc.dg/Wwrite-strings-1.c	(Arbeitskopie)
@@ -5,4 +5,4 @@
 /* { dg-do compile } */
 /* { dg-options "-Wwrite-strings" } */
 typedef char T[1];
-T *p = &""; /* { dg-warning "initialization from incompatible pointer type" } */
+T *p = &""; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
Index: gcc/testsuite/gcc.dg/array-quals-2.c
===================================================================
--- gcc/testsuite/gcc.dg/array-quals-2.c	(Revision 216690)
+++ gcc/testsuite/gcc.dg/array-quals-2.c	(Arbeitskopie)
@@ -3,12 +3,12 @@
    lost in forming composite types.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-pedantic" } */
 typedef const char T[1];
 typedef const char T2[1];
 typedef volatile char U[1];
 T *p;
 T2 *p2;
 U *q;
-void *f(void) { return 1 ? p : q; } /* { dg-warning "pointer type mismatch in conditional expression" } */
+void *f(void) { return 1 ? p : q; } /* { dg-warning "pointers to arrays with different qualifiers" } */
 T *g(void) { return 1 ? p : p2; }
Index: gcc/testsuite/gcc.dg/pointer-arrays-quals.c
===================================================================
--- gcc/testsuite/gcc.dg/pointer-arrays-quals.c	(Revision 0)
+++ gcc/testsuite/gcc.dg/pointer-arrays-quals.c	(Arbeitskopie)
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -pedantic" } */
+/* Origin: Martin Uecker <uecker@eecs.berkeley.edu> */
+void transpose1(double out[2][2], const double in[2][2]) { }
+void transpose2(double* out, const double* in) { }
+void test(void)
+{
+	double x[2][2];
+	double o[2][2];
+	double p[4];
+	double y[4];
+	const double z[2][2];
+	transpose1(o, x); /* { dg-warning "pointers to arrays with different qualifiers" } */
+	transpose2(p, y);
+	const double (*xp)[2] = x; /* { dg-warning "pointers to arrays with different qualifiers" } */
+	(void)xp[0][0];
+	double* v = 0;
+	const double* w = 0;
+	w = v;
+	(void)(1 ? x : z); /* { dg-warning "pointers to arrays with different qualifiers" } */
+	(void)(1 ? v : w);
+#pragma GCC diagnostic ignored "-pedantic" 
+	transpose1(o, x);
+	const double (*x2p)[2] = x;
+	(void)x2p[0][0];
+	(void)(1 ? x : z);
+}
+
Index: gcc/testsuite/gcc.dg/qual-component-1.c
===================================================================
--- gcc/testsuite/gcc.dg/qual-component-1.c	(Revision 216690)
+++ gcc/testsuite/gcc.dg/qual-component-1.c	(Arbeitskopie)
@@ -110,24 +110,24 @@ g (void)
     int (*b)[1] = &v1.b;
     int (*c)[2][3] = &v1.c;
     int (*cc)[3] = v1.c;
-    const int (*ff)[3] = v1.c; /* { dg-warning "initialization from incompatible pointer type" } */
+    const int (*ff)[3] = v1.c;
     a = &v1.a;
     b = &v1.b;
     c = &v1.c;
     cc = v1.c;
-    ff = v1.c; /* { dg-warning "assignment from incompatible pointer type" } */
+    ff = v1.c;
   }
   {
     const int *d = &v1.d;
     const int (*e)[1] = &v1.e;
     const int (*f)[2][3] = &v1.f;
     const int (*ff)[3] = v1.f;
-    int (*cc)[3] = v1.f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v1.f; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v1.d;
     e = &v1.e;
     f = &v1.f;
     ff = v1.f;
-    cc = v1.f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v1.f; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
 
   {
@@ -135,24 +135,24 @@ g (void)
     int (*b)[1] = &v2->b;
     int (*c)[2][3] = &v2->c;
     int (*cc)[3] = v2->c;
-    const int (*ff)[3] = v2->c; /* { dg-warning "initialization from incompatible pointer type" } */
+    const int (*ff)[3] = v2->c; 
     a = &v2->a;
     b = &v2->b;
     c = &v2->c;
     cc = v2->c;
-    ff = v2->c; /* { dg-warning "assignment from incompatible pointer type" } */
+    ff = v2->c;
   }
   {
     const int *d = &v2->d;
     const int (*e)[1] = &v2->e;
     const int (*f)[2][3] = &v2->f;
     const int (*ff)[3] = v2->f;
-    int (*cc)[3] = v2->f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v2->f; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v2->d;
     e = &v2->e;
     f = &v2->f;
     ff = v2->f;
-    cc = v2->f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v2->f; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
 
   {
@@ -160,24 +160,24 @@ g (void)
     const int (*e)[1] = &v3->b;
     const int (*f)[2][3] = &v3->c;
     const int (*ff)[3] = v3->c;
-    int (*cc)[3] = v3->c; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v3->c; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v3->a;
     e = &v3->b;
     f = &v3->c;
     ff = v3->c;
-    cc = v3->c; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v3->c; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
   {
     const int *d = &v3->d;
     const int (*e)[1] = &v3->e;
     const int (*f)[2][3] = &v3->f;
     const int (*ff)[3] = v3->f;
-    int (*cc)[3] = v3->f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v3->f; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v3->d;
     e = &v3->e;
     f = &v3->f;
     ff = v3->f;
-    cc = v3->f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v3->f; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
 
   {
@@ -185,24 +185,24 @@ g (void)
     const int (*e)[1] = &v4.b;
     const int (*f)[2][3] = &v4.c;
     const int (*ff)[3] = v4.c;
-    int (*cc)[3] = v4.c; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v4.c; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v4.a;
     e = &v4.b;
     f = &v4.c;
     ff = v4.c;
-    cc = v4.c; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v4.c; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
   {
     const int *d = &v4.d;
     const int (*e)[1] = &v4.e;
     const int (*f)[2][3] = &v4.f;
     const int (*ff)[3] = v4.f;
-    int (*cc)[3] = v4.f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v4.f; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v4.d;
     e = &v4.e;
     f = &v4.f;
     ff = v4.f;
-    cc = v4.f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v4.f; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
 
   {
@@ -210,23 +210,23 @@ g (void)
     const int (*e)[1] = &v5.x.b;
     const int (*f)[2][3] = &v5.x.c;
     const int (*ff)[3] = v5.x.c;
-    int (*cc)[3] = v5.x.c; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v5.x.c; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v5.x.a;
     e = &v5.x.b;
     f = &v5.x.c;
     ff = v5.x.c;
-    cc = v5.x.c; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v5.x.c; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
   {
     const int *d = &v5.x.d;
     const int (*e)[1] = &v5.x.e;
     const int (*f)[2][3] = &v5.x.f;
     const int (*ff)[3] = v5.x.f;
-    int (*cc)[3] = v5.x.f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v5.x.f; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
     d = &v5.x.d;
     e = &v5.x.e;
     f = &v5.x.f;
     ff = v5.x.f;
-    cc = v5.x.f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v5.x.f; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
   }
 }




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]