This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[c/c++ PATCH] Fix PR28573, problem with offsetof and overloaded operator[]
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 07 Aug 2006 13:46:31 +0200
- Subject: [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" } */
+}