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]

Re: [RFA] PR c++/38699


On Mon, Nov 02, 2009 at 04:36:09PM -0500, Jason Merrill wrote:
> Much like, though I'd avoid having the integer_zerop call in two places  
> by stripping INDIRECT_REF and NOP_EXPR as appropriate.  You don't even  
> need to strip NOP_EXPR really, since integer_zerop does that.  And once  
> you're checking integer_zerop you might as well remove the recursion and  
> INTEGER_CST case and return size_zero_node directly if it's correct.

Indeed. The whole thing looks much better now, thanks.
Here is the patch I am testing currently.

commit 2925962a5f75db70f2d1646bf8e142145a3a2aa6
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Thu Oct 29 10:50:57 2009 +0100

    Fix PR c++/38699
    
    gcc/ChangeLog:
    
    	PR c++/38699
    	* c-common.c (fold_offsetof_1): Issue errors when the member designator of
    	the offsetoff expression is not legitimate.
    
    gcc/testsuite/ChangeLog:
    
    	* g++.dg/other/offsetof6.C: New test.
    	* g++.dg/other/offsetof7.C: Likewise.
    	* gcc.dg/torture/builtin-offsetof.c: Likewise.

diff --git a/gcc/c-common.c b/gcc/c-common.c
index 8a6d15b..b025516 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -8335,15 +8335,14 @@ fold_offsetof_1 (tree expr, tree stop_ref)
       error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
       return error_mark_node;
 
-    case INTEGER_CST:
-      gcc_assert (integer_zerop (expr));
-      return size_zero_node;
-
     case NOP_EXPR:
     case INDIRECT_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
-      gcc_assert (base == error_mark_node || base == size_zero_node);
-      return base;
+      if (!integer_zerop (TREE_OPERAND (expr, 0)))
+	{
+	  error ("cannot apply %<offsetof%> to a non constant address");
+	  return error_mark_node;
+	}
+      return size_zero_node;
 
     case COMPONENT_REF:
       base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
@@ -8376,6 +8375,16 @@ fold_offsetof_1 (tree expr, tree stop_ref)
 	}
       t = convert (sizetype, t);
       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+
+      /* Check if the offset goes beyond the upper bound of the array.  */
+      {
+	tree nelts = array_type_nelts (TREE_TYPE (TREE_OPERAND (expr, 0)));
+        HOST_WIDE_INT index = int_cst_value (t);
+	if (index > int_cst_value (nelts))
+	  warning (OPT_Warray_bounds,
+		   "index %ld denotes an offset greater than size of %qT",
+		   index, TREE_TYPE (TREE_OPERAND (expr, 0)));
+      }
       break;
 
     case COMPOUND_EXPR:
diff --git a/gcc/testsuite/g++.dg/other/offsetof6.C b/gcc/testsuite/g++.dg/other/offsetof6.C
new file mode 100644
index 0000000..2ddb9a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/offsetof6.C
@@ -0,0 +1,30 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/38699
+// { dg-options "-Warray-bounds" }
+// { dg-do compile }
+
+struct A
+{
+  const char *p;
+};
+
+struct B
+{
+    char p[10];
+    A a;
+};
+
+void
+f0 ()
+{
+  __builtin_offsetof(A, p); // OK
+  __builtin_offsetof(A, p[0]); // { dg-error "non constant address" }
+  __builtin_offsetof(B, p[0]); // OK
+  __builtin_offsetof(B, p[9]); // OK
+  __builtin_offsetof(B, p[10]); // { dg-warning "greater than size" }
+  __builtin_offsetof(B, a.p); // OK
+  __builtin_offsetof(B, p[0]); // OK
+  __builtin_offsetof(B, a.p[0]); // { dg-error "non constant address" }
+}
+
+
diff --git a/gcc/testsuite/g++.dg/other/offsetof7.C b/gcc/testsuite/g++.dg/other/offsetof7.C
new file mode 100644
index 0000000..b77d1b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/offsetof7.C
@@ -0,0 +1,26 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/38699
+// { dg-do compile }
+
+template<class T>
+struct A
+{
+  const T *p;
+};
+
+struct B
+{
+  A<int> a;
+};
+
+template class A<char>;
+
+void
+f0 ()
+{
+  __builtin_offsetof(A<char>, p); // OK
+  __builtin_offsetof(A<char>, p[1]); // { dg-error "non constant address" }
+  __builtin_offsetof(B, a.p); // OK
+  __builtin_offsetof(B, a.p[1]); // { dg-error "non constant address" }
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-offsetof.c b/gcc/testsuite/gcc.dg/torture/builtin-offsetof.c
new file mode 100644
index 0000000..0ab498a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-offsetof.c
@@ -0,0 +1,29 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/38699
+// { dg-options "-Warray-bounds" }
+// { dg-do compile }
+
+struct A
+{
+  const char *p;
+};
+
+struct B
+{
+    char p[10];
+    struct A a;
+};
+
+void
+f0 ()
+{
+  __builtin_offsetof(struct A, p); // OK
+  __builtin_offsetof(struct A, p[0]); // { dg-error "non constant address" }
+  __builtin_offsetof(struct B, p[0]); // OK
+  __builtin_offsetof(struct B, p[9]); // OK
+  __builtin_offsetof(struct B, p[10]); // { dg-warning "greater than size" }
+  __builtin_offsetof(struct B, a.p); // OK
+  __builtin_offsetof(struct B, p[0]); // OK
+  __builtin_offsetof(struct B, a.p[0]); // { dg-error "non constant address" }
+}
+


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