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]

[c/c++ PATCH] Fix PR28573, problem with offsetof and overloaded operator[]


The bug in this PR is that offsetof does not give an error when operator[] is overloaded, and the argument to the overloaded array access is a constant. Unfortunately, "not everything that looks like an constant array index is".

Depending on the type returned by the overloaded operator, we either ICE (fold_offsetof_1 does not expect a CALL_EXPR and dies) or return an incorrect result. In the latter case, what happens is that the operator[] returns a reference, and the C++ front-end automatically includes a dereference. fold_offsetof_1 expects a chain of ARRAY_REFs and COMPONENT_REFs that ultimately end with an INDIRECT_REF of NULL, but in this case we have

INDIRECT_REF( CALL_EXPR ( operator[], INDIRECT_REF( NULL ), 0 ) )

fold_offsetof_1 does not expect anything inside the INDIRECT_REF, and blindly returns 0 as soon as it sees the outer INDIRECT_REF.

The fix then has three parts:

1) we need to teach fold_offsetof_1 to reject CALL_EXPRs instead of dying;

2) we need to drill into the INDIRECT_REF until we reach the NULL (so that we give an appropriate error message in cases such as the above) and we also need to skip NOP_EXPRs;

3) we need a small adjustment of the C front-end, which was creating an INDIRECT_REF with a NULL operand, instead of a null_pointer_node like in the C++ front-end.

Bootstrapped/regtested i686-pc-linux-gnu, all languages except Java which was broken at the time. Ok for mainline?

Paolo

:ADDPATCH c/c++:
2006-08-07  Paolo Bonzini  <bonzini@gnu.org>

	PR c++/28573

	* c-common.c (fold_offsetof_1): Recurse down to the INTEGER_CST.
	Fail on a CALL_EXPR.
	* c-parser.c (c_parser_postfix_expression): Don't include a NULL
	operand into an INDIRECT_REF.

Index: c-common.c
===================================================================
--- c-common.c	(revision 115716)
+++ c-common.c	(working copy)
@@ -5996,9 +5996,16 @@ fold_offsetof_1 (tree expr)
       error ("cannot apply %<offsetof%> to static data member %qD", expr);
       return error_mark_node;
 
-    case INDIRECT_REF:
+    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));
+      off = size_zero_node;
+      break;
+
     case COMPONENT_REF:
       base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
       if (base == error_mark_node)
@@ -6031,6 +6037,10 @@ fold_offsetof_1 (tree expr)
       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
       break;
 
+    case CALL_EXPR:
+      error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+      return error_mark_node;
+
     default:
       gcc_unreachable ();
     }
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 115990)
+++ c-parser.c	(working copy)
@@ -5189,7 +5189,7 @@ c_parser_postfix_expression (c_parser *p
 	    if (type == error_mark_node)
 	      offsetof_ref = error_mark_node;
 	    else
-	      offsetof_ref = build1 (INDIRECT_REF, type, NULL);
+	      offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
 	    /* Parse the second argument to __builtin_offsetof.  We
 	       must have one identifier, and beyond that we want to
 	       accept sub structure and sub array references.  */
Index: testsuite/g++.dg/parse/offsetof6.C
===================================================================
--- testsuite/g++.dg/parse/offsetof6.C	(revision 0)
+++ testsuite/g++.dg/parse/offsetof6.C	(revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+// From PR28573
+
+struct A
+{
+  char d[44];
+  char &operator [] ( int indx ) { return d[indx]; }
+};
+
+struct B
+{
+  A a;
+};
+
+int main()
+{
+  return __builtin_offsetof(B, a[0]); /* { dg-error "cannot apply.*offsetof" } */
+}
Index: testsuite/g++.dg/parse/offsetof7.C
===================================================================
--- testsuite/g++.dg/parse/offsetof7.C	(revision 0)
+++ testsuite/g++.dg/parse/offsetof7.C	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+// From PR28573
+
+struct A
+{
+   int operator [] ( int indx ) { return indx; }
+};
+
+struct B
+{
+   A a;
+};
+
+int main()
+{
+  return __builtin_offsetof(B, a[0]); /* { dg-error "cannot apply.*offsetof" } */
+}

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