re PR c++/50608 (cannot apply 'offsetof' to a non-constant address)
2011-11-04 Eric Botcazou <ebotcazou@adacore.com> PR c++/50608 * c-parser.c (c_parser_postfix_expression) <RID_OFFSETOF>: Adjust call to fold_offsetof. * c-typeck.c (build_unary_op) <ADDR_EXPR>: Call fold_offsetof_1. c-family/ * c-common.c (c_fully_fold_internal) <ADDR_EXPR>: Call fold_offsetof_1. (fold_offsetof_1): Make global. Remove STOP_REF argument and adjust. <INDIRECT_REF>: Return the argument. <ARRAY_REF>: Remove special code for negative offset. Call fold_build_pointer_plus instead of size_binop. (fold_offsetof): Remove STOP_REF argument and adjust. * c-common.h (fold_offsetof_1): Declare. (fold_offsetof): Remove STOP_REF argument. cp/ * semantics.c (finish_offsetof): Adjust call to fold_offsetof. * typeck.c (cp_build_addr_expr_1): Call fold_offsetof_1. From-SVN: r180986
This commit is contained in:
parent
c62c54419c
commit
cf9e9959d1
11 changed files with 75 additions and 46 deletions
|
@ -1,16 +1,23 @@
|
|||
2011-11-05 Alan Modra <amodra@gmail.com>
|
||||
2011-11-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR c++/50608
|
||||
* c-parser.c (c_parser_postfix_expression) <RID_OFFSETOF>: Adjust call
|
||||
to fold_offsetof.
|
||||
* c-typeck.c (build_unary_op) <ADDR_EXPR>: Call fold_offsetof_1.
|
||||
|
||||
2011-11-04 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* reload1.c (gen_reload): Don't use REGNO on SUBREGs.
|
||||
* print-rtl.c (print_rtx): Don't segfault on negative regno.
|
||||
|
||||
2011-11-03 David S. Miller <davem@davemloft.net>
|
||||
2011-11-04 David S. Miller <davem@davemloft.net>
|
||||
|
||||
PR target/49965
|
||||
* config/sparc/sparc.c (sparc_expand_conditional_move): Handle the
|
||||
fact that sparc_emit_float_lib_cmp modifies the comparison in
|
||||
operands[1].
|
||||
|
||||
2011-11-05 Ralf Corsépius <ralf.corsepius@rtems.org>
|
||||
2011-11-04 Ralf Corsépius <ralf.corsepius@rtems.org>
|
||||
|
||||
* config/lm32/t-rtems: New.
|
||||
* config.gcc (lm32-*-rtems*): Add t-rtems.
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
2011-11-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR c++/50608
|
||||
* c-common.c (c_fully_fold_internal) <ADDR_EXPR>: Call fold_offsetof_1.
|
||||
(fold_offsetof_1): Make global. Remove STOP_REF argument and adjust.
|
||||
<INDIRECT_REF>: Return the argument.
|
||||
<ARRAY_REF>: Remove special code for negative offset.
|
||||
Call fold_build_pointer_plus instead of size_binop.
|
||||
(fold_offsetof): Remove STOP_REF argument and adjust.
|
||||
* c-common.h (fold_offsetof_1): Declare.
|
||||
(fold_offsetof): Remove STOP_REF argument.
|
||||
|
||||
2011-11-02 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/50810
|
||||
|
|
|
@ -1274,12 +1274,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
|||
&& (op1 = get_base_address (op0)) != NULL_TREE
|
||||
&& TREE_CODE (op1) == INDIRECT_REF
|
||||
&& TREE_CONSTANT (TREE_OPERAND (op1, 0)))
|
||||
{
|
||||
tree offset = fold_offsetof (op0, op1);
|
||||
op1
|
||||
= fold_convert_loc (loc, TREE_TYPE (expr), TREE_OPERAND (op1, 0));
|
||||
ret = fold_build_pointer_plus_loc (loc, op1, offset);
|
||||
}
|
||||
ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0));
|
||||
else if (op0 != orig_op0 || in_init)
|
||||
ret = in_init
|
||||
? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
|
||||
|
@ -8538,20 +8533,15 @@ c_common_to_target_charset (HOST_WIDE_INT c)
|
|||
return uc;
|
||||
}
|
||||
|
||||
/* Build the result of __builtin_offsetof. EXPR is a nested sequence of
|
||||
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. */
|
||||
/* Fold an offsetof-like expression. EXPR is a nested sequence of component
|
||||
references with an INDIRECT_REF of a constant at the bottom; much like the
|
||||
traditional rendering of offsetof as a macro. Return the folded result. */
|
||||
|
||||
static tree
|
||||
fold_offsetof_1 (tree expr, tree stop_ref)
|
||||
tree
|
||||
fold_offsetof_1 (tree expr)
|
||||
{
|
||||
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:
|
||||
|
@ -8568,15 +8558,15 @@ fold_offsetof_1 (tree expr, tree stop_ref)
|
|||
|
||||
case NOP_EXPR:
|
||||
case INDIRECT_REF:
|
||||
if (!integer_zerop (TREE_OPERAND (expr, 0)))
|
||||
if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
|
||||
{
|
||||
error ("cannot apply %<offsetof%> to a non constant address");
|
||||
return error_mark_node;
|
||||
}
|
||||
return size_zero_node;
|
||||
return TREE_OPERAND (expr, 0);
|
||||
|
||||
case COMPONENT_REF:
|
||||
base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
|
||||
base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
|
||||
if (base == error_mark_node)
|
||||
return base;
|
||||
|
||||
|
@ -8594,21 +8584,14 @@ fold_offsetof_1 (tree expr, tree stop_ref)
|
|||
break;
|
||||
|
||||
case ARRAY_REF:
|
||||
base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
|
||||
base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
|
||||
if (base == error_mark_node)
|
||||
return base;
|
||||
|
||||
t = TREE_OPERAND (expr, 1);
|
||||
if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
|
||||
{
|
||||
code = MINUS_EXPR;
|
||||
t = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (t), t);
|
||||
}
|
||||
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. */
|
||||
if (code == PLUS_EXPR && TREE_CODE (t) == INTEGER_CST)
|
||||
if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
|
||||
{
|
||||
tree upbound = array_ref_up_bound (expr);
|
||||
if (upbound != NULL_TREE
|
||||
|
@ -8648,26 +8631,30 @@ fold_offsetof_1 (tree expr, tree stop_ref)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
t = convert (sizetype, t);
|
||||
off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
|
||||
break;
|
||||
|
||||
case COMPOUND_EXPR:
|
||||
/* Handle static members of volatile structs. */
|
||||
t = TREE_OPERAND (expr, 1);
|
||||
gcc_assert (TREE_CODE (t) == VAR_DECL);
|
||||
return fold_offsetof_1 (t, stop_ref);
|
||||
return fold_offsetof_1 (t);
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
return size_binop (code, base, off);
|
||||
return fold_build_pointer_plus (base, off);
|
||||
}
|
||||
|
||||
/* Likewise, but convert it to the return type of offsetof. */
|
||||
|
||||
tree
|
||||
fold_offsetof (tree expr, tree stop_ref)
|
||||
fold_offsetof (tree expr)
|
||||
{
|
||||
/* Convert back from the internal sizetype to size_t. */
|
||||
return convert (size_type_node, fold_offsetof_1 (expr, stop_ref));
|
||||
return convert (size_type_node, fold_offsetof_1 (expr));
|
||||
}
|
||||
|
||||
/* Warn for A ?: C expressions (with B omitted) where A is a boolean
|
||||
|
|
|
@ -956,7 +956,8 @@ extern bool c_dump_tree (void *, tree);
|
|||
|
||||
extern void verify_sequence_points (tree);
|
||||
|
||||
extern tree fold_offsetof (tree, tree);
|
||||
extern tree fold_offsetof_1 (tree);
|
||||
extern tree fold_offsetof (tree);
|
||||
|
||||
/* Places where an lvalue, or modifiable lvalue, may be required.
|
||||
Used to select diagnostic messages in lvalue_error and
|
||||
|
|
|
@ -6388,7 +6388,7 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
c_parser_error (parser, "expected identifier");
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
|
||||
expr.value = fold_offsetof (offsetof_ref);
|
||||
}
|
||||
break;
|
||||
case RID_CHOOSE_EXPR:
|
||||
|
|
|
@ -3890,10 +3890,7 @@ build_unary_op (location_t location,
|
|||
if (val && TREE_CODE (val) == INDIRECT_REF
|
||||
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
|
||||
{
|
||||
tree op0 = fold_offsetof (arg, val), op1;
|
||||
|
||||
op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
|
||||
ret = fold_build_pointer_plus_loc (location, op1, op0);
|
||||
ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
|
||||
goto return_build_unary_op;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2011-11-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
PR c++/50608
|
||||
* semantics.c (finish_offsetof): Adjust call to fold_offsetof.
|
||||
* typeck.c (cp_build_addr_expr_1): Call fold_offsetof_1.
|
||||
|
||||
2011-11-04 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
* typeck.c (build_indirect_ref): Use ATTRIBUTE_UNUSED.
|
||||
|
|
|
@ -3568,7 +3568,7 @@ finish_offsetof (tree expr)
|
|||
if (!complete_type_or_else (TREE_TYPE (object), object))
|
||||
return error_mark_node;
|
||||
}
|
||||
return fold_offsetof (expr, NULL_TREE);
|
||||
return fold_offsetof (expr);
|
||||
}
|
||||
|
||||
/* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR. This
|
||||
|
|
|
@ -4881,9 +4881,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
|
|||
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
|
||||
{
|
||||
tree type = build_pointer_type (argtype);
|
||||
tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
|
||||
tree op1 = fold_offsetof (arg, val);
|
||||
return fold_build_pointer_plus (op0, op1);
|
||||
return fold_convert (type, fold_offsetof_1 (arg));
|
||||
}
|
||||
|
||||
/* Handle complex lvalues (when permitted)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2011-11-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* g++.dg/other/offsetof7.C: New test.
|
||||
|
||||
2011-11-04 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* lib/gcc-dg.exp (gcc_force_conventional_output): New global
|
||||
|
|
17
gcc/testsuite/g++.dg/other/offsetof7.C
Normal file
17
gcc/testsuite/g++.dg/other/offsetof7.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// PR c++/50608
|
||||
// Testcase by <dberger@oubliette.org>
|
||||
// { dg-do compile }
|
||||
|
||||
struct A {
|
||||
int offset;
|
||||
};
|
||||
|
||||
struct B: public A {
|
||||
};
|
||||
|
||||
struct C {
|
||||
A a;
|
||||
B b;
|
||||
};
|
||||
|
||||
int fails = __builtin_offsetof (C, b.offset);
|
Loading…
Add table
Reference in a new issue