This is the mail archive of the gcc-patches@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 to clean up build_array_ref


This patch cleans up build_array_ref in the C front end.  This
improves diagnostics and their consistency in various cases, ensuring
that x[y] and y[x] are handled identically except that for some reason
-Wchar-subscripts is designed only to warn for the char in one place.
The dead code testing for index == 0 is removed, and I didn't feel the
need to replace it with an assert.  This patch is more conservative
than previously discussed: there are no changes to the handling of
array dereferences involving incomplete types.

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    joseph@codesourcery.com (CodeSourcery mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

2004-11-20  Joseph S. Myers  <joseph@codesourcery.com>

	* c-typeck.c (build_array_ref): Don't check for index == 0.  Make
	checks for neither argument being an array or pointer (swapping
	the arguments if necessary), the array argument being a pointer to
	or array of functions and for -Wchar-subscripts warnings upfront.

testsuite:
2004-11-20  Joseph S. Myers  <joseph@codesourcery.com>

	* gcc.dg/Wchar-subscripts-1.c, gcc.dg/array-8.c: New tests.
	* gcc.dg/pointer-arith-1.c, gcc.dg/pointer-arith-2.c,
	gcc.dg/pointer-arith-3.c, gcc.dg/pointer-arith-4.c: Update
	expected diagnostics.

diff -rupN GCC.orig/gcc/c-typeck.c GCC/gcc/c-typeck.c
--- GCC.orig/gcc/c-typeck.c	2004-11-12 10:04:59.000000000 +0000
+++ GCC/gcc/c-typeck.c	2004-11-20 15:03:42.000000000 +0000
@@ -1594,39 +1594,58 @@ build_indirect_ref (tree ptr, const char
 tree
 build_array_ref (tree array, tree index)
 {
-  if (index == 0)
-    {
-      error ("subscript missing in array reference");
-      return error_mark_node;
-    }
-
+  bool swapped = false;
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (index) == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+  if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
     {
-      tree rval, type;
-
-      /* Subscripting with type char is likely to lose
-	 on a machine where chars are signed.
-	 So warn on any machine, but optionally.
-	 Don't warn for unsigned char since that type is safe.
-	 Don't warn for signed char because anyone who uses that
-	 must have done so deliberately.  */
-      if (warn_char_subscripts
-	  && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-	warning ("array subscript has type %<char%>");
-
-      /* Apply default promotions *after* noticing character types.  */
-      index = default_conversion (index);
-
-      /* Require integer *after* promotion, for sake of enums.  */
-      if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE)
+      tree temp;
+      if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
+	  && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
 	{
-	  error ("array subscript is not an integer");
+	  error ("subscripted value is neither array nor pointer");
 	  return error_mark_node;
 	}
+      temp = array;
+      array = index;
+      index = temp;
+      swapped = true;
+    }
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
+    {
+      error ("array subscript is not an integer");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
+    {
+      error ("subscripted value is pointer to function");
+      return error_mark_node;
+    }
+
+  /* Subscripting with type char is likely to lose on a machine where
+     chars are signed.  So warn on any machine, but optionally.  Don't
+     warn for unsigned char since that type is safe.  Don't warn for
+     signed char because anyone who uses that must have done so
+     deliberately.  ??? Existing practice has also been to warn only
+     when the char index is syntactically the index, not for
+     char[array].  */
+  if (warn_char_subscripts && !swapped
+      && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
+    warning ("array subscript has type %<char%>");
+
+  /* Apply default promotions *after* noticing character types.  */
+  index = default_conversion (index);
+
+  gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+
+  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+    {
+      tree rval, type;
 
       /* An array that is indexed by a non-constant
 	 cannot be stored in a register; we must be able to do
@@ -1681,45 +1700,19 @@ build_array_ref (tree array, tree index)
 	    | TREE_THIS_VOLATILE (array));
       return require_complete_type (fold (rval));
     }
+  else
+    {
+      tree ar = default_conversion (array);
 
-  {
-    tree ar = default_conversion (array);
-    tree ind = default_conversion (index);
-
-    /* Do the same warning check as above, but only on the part that's
-       syntactically the index and only if it is also semantically
-       the index.  */
-    if (warn_char_subscripts
-	&& TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
-	&& TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-      warning ("subscript has type %<char%>");
-
-    /* Put the integer in IND to simplify error checking.  */
-    if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
-      {
-	tree temp = ar;
-	ar = ind;
-	ind = temp;
-      }
-
-    if (ar == error_mark_node)
-      return ar;
+      if (ar == error_mark_node)
+	return ar;
 
-    if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE
-	|| TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE)
-      {
-	error ("subscripted value is neither array nor pointer");
-	return error_mark_node;
-      }
-    if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
-      {
-	error ("array subscript is not an integer");
-	return error_mark_node;
-      }
+      gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
+      gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
 
-    return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind, 0),
-			       "array indexing");
-  }
+      return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
+				 "array indexing");
+    }
 }
 
 /* Build an external reference to identifier ID.  FUN indicates
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/Wchar-subscripts-1.c GCC/gcc/testsuite/gcc.dg/Wchar-subscripts-1.c
--- GCC.orig/gcc/testsuite/gcc.dg/Wchar-subscripts-1.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/Wchar-subscripts-1.c	2004-11-14 23:59:24.000000000 +0000
@@ -0,0 +1,29 @@
+/* Test -Wchar-subscripts.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "-Wchar-subscripts" } */
+
+extern int a[];
+int *p;
+char c;
+signed char sc;
+unsigned char uc;
+
+void
+f (void)
+{
+  a[sc];
+  a[uc];
+  sc[a];
+  uc[a];
+  p[sc];
+  p[uc];
+  sc[p];
+  uc[p];
+  a[c]; /* { dg-warning "warning: array subscript has type 'char'" } */
+  p[c]; /* { dg-warning "warning: array subscript has type 'char'" } */
+  /* -Wchar-subscripts does not warn if the char is not syntactically
+      the subscript.  */
+  c[a];
+  c[p];
+}
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/array-8.c GCC/gcc/testsuite/gcc.dg/array-8.c
--- GCC.orig/gcc/testsuite/gcc.dg/array-8.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/array-8.c	2004-11-20 13:40:50.000000000 +0000
@@ -0,0 +1,49 @@
+/* Test diagnostics for array references.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu89" } */
+
+struct s { char c[1]; };
+struct s f (void);
+_Bool b;
+char c;
+enum e { E } e;
+extern int a[];
+int *p;
+void *pv;
+void (*fp)(void);
+struct si *sip;
+
+void
+g (void)
+{
+  a[b];
+  a[c];
+  a[e];
+  p[b];
+  p[c];
+  p[e];
+  b[a];
+  c[a];
+  e[a];
+  b[p];
+  c[p];
+  e[p];
+  /* These two should be treated the same.  In particular, a "neither
+     array nor pointer" bogus warning used to be given for the
+     second.  */
+  f().c[0];
+  0[f().c];
+  /* Various invalid cases.  */
+  c[c]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
+  p[1.0]; /* { dg-error "error: array subscript is not an integer" } */
+  1.0[a]; /* { dg-error "error: array subscript is not an integer" } */
+  fp[0]; /* { dg-error "error: subscripted value is pointer to function" } */
+  0[fp]; /* { dg-error "error: subscripted value is pointer to function" } */
+  pv[0]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
+  0[pv]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
+  sip[0]; /* { dg-error "error: invalid use of undefined type 'struct si'" } */
+  /* { dg-error "error: dereferencing pointer to incomplete type" "" { target *-*-* } 45 } */
+  0[sip]; /* { dg-error "error: invalid use of undefined type 'struct si'" } */
+  /* { dg-error "error: dereferencing pointer to incomplete type" "" { target *-*-* } 47 } */
+}
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-1.c GCC/gcc/testsuite/gcc.dg/pointer-arith-1.c
--- GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-1.c	2004-11-14 22:09:38.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/pointer-arith-1.c	2004-11-15 13:58:23.000000000 +0000
@@ -32,8 +32,8 @@ g (void)
   f -= 1;
   p[0]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
   0[p]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
-  f[0]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
-  0[f]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
+  f[0]; /* { dg-error "error: subscripted value is pointer to function" } */
+  0[f]; /* { dg-error "error: subscripted value is pointer to function" } */
   p - p;
   f - f;
 }
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-2.c GCC/gcc/testsuite/gcc.dg/pointer-arith-2.c
--- GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-2.c	2004-11-14 22:10:20.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/pointer-arith-2.c	2004-11-20 13:41:45.000000000 +0000
@@ -34,8 +34,8 @@ g (void)
   /* { dg-warning "warning: pointer of type 'void \\*' used in arithmetic" "array 1" { target *-*-* } 33 } */
   0[p]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
   /* { dg-warning "warning: pointer of type 'void \\*' used in arithmetic" "array 1" { target *-*-* } 35 } */
-  f[0]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
-  0[f]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
+  f[0]; /* { dg-error "error: subscripted value is pointer to function" } */
+  0[f]; /* { dg-error "error: subscripted value is pointer to function" } */
   p - p; /* { dg-warning "warning: pointer of type 'void \\*' used in subtraction" } */
   f - f; /* { dg-warning "warning: pointer to a function used in subtraction" } */
 }
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-3.c GCC/gcc/testsuite/gcc.dg/pointer-arith-3.c
--- GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-3.c	2004-11-14 22:10:24.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/pointer-arith-3.c	2004-11-20 13:42:01.000000000 +0000
@@ -34,8 +34,8 @@ g (void)
   /* { dg-warning "warning: pointer of type 'void \\*' used in arithmetic" "array 1" { target *-*-* } 33 } */
   0[p]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
   /* { dg-warning "warning: pointer of type 'void \\*' used in arithmetic" "array 1" { target *-*-* } 35 } */
-  f[0]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
-  0[f]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
+  f[0]; /* { dg-error "error: subscripted value is pointer to function" } */
+  0[f]; /* { dg-error "error: subscripted value is pointer to function" } */
   p - p; /* { dg-warning "warning: pointer of type 'void \\*' used in subtraction" } */
   f - f; /* { dg-warning "warning: pointer to a function used in subtraction" } */
 }
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-4.c GCC/gcc/testsuite/gcc.dg/pointer-arith-4.c
--- GCC.orig/gcc/testsuite/gcc.dg/pointer-arith-4.c	2004-11-14 22:10:35.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/pointer-arith-4.c	2004-11-20 13:42:43.000000000 +0000
@@ -34,8 +34,8 @@ g (void)
   /* { dg-error "error: pointer of type 'void \\*' used in arithmetic" "array 1" { target *-*-* } 33 } */
   0[p]; /* { dg-warning "warning: dereferencing 'void \\*' pointer" } */
   /* { dg-error "error: pointer of type 'void \\*' used in arithmetic" "array 1" { target *-*-* } 35 } */
-  f[0]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
-  0[f]; /* { dg-error "error: subscripted value is neither array nor pointer" } */
+  f[0]; /* { dg-error "error: subscripted value is pointer to function" } */
+  0[f]; /* { dg-error "error: subscripted value is pointer to function" } */
   p - p; /* { dg-error "error: pointer of type 'void \\*' used in subtraction" } */
   f - f; /* { dg-error "error: pointer to a function used in subtraction" } */
 }


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