}
/* Build the result of __builtin_offsetof. EXPR is a nested sequence of
- component references, with an INDIRECT_REF at the bottom; much like
- the traditional rendering of offsetof as a macro. Returns the folded
- and properly cast result. */
+ component references, with STOP_REF, or alternatively an INDIRECT_REF of
+ NULL, at the bottom; much like the traditional rendering of offsetof as a
+ macro. Returns the folded and properly cast result. */
static tree
-fold_offsetof_1 (tree expr)
+fold_offsetof_1 (tree expr, tree stop_ref)
{
enum tree_code code = PLUS_EXPR;
tree base, off, t;
+ if (expr == stop_ref && TREE_CODE (expr) != ERROR_MARK)
+ return size_zero_node;
+
switch (TREE_CODE (expr))
{
case ERROR_MARK:
error ("cannot apply %<offsetof%> to static data member %qD", expr);
return error_mark_node;
- case INDIRECT_REF:
+ case CALL_EXPR:
+ 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;
+
case COMPONENT_REF:
- base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+ base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
if (base == error_mark_node)
return base;
break;
case ARRAY_REF:
- base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+ base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
if (base == error_mark_node)
return base;
}
tree
-fold_offsetof (tree expr)
+fold_offsetof (tree expr, tree stop_ref)
{
/* Convert back from the internal sizetype to size_t. */
- return convert (size_type_node, fold_offsetof_1 (expr));
+ return convert (size_type_node, fold_offsetof_1 (expr, stop_ref));
}
/* Print an error message for an invalid lvalue. USE says