diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2011-11-04 21:46:07 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2011-11-04 21:46:07 +0000 |
commit | cf9e9959d1a5e8c7ddb506f68017b4f9c9292b94 (patch) | |
tree | 15bbae4a0d50f8d41bd44c607cad67495a7c994c /gcc | |
parent | c62c54419cf1bcdebbe2313b509e1892b85832d0 (diff) | |
download | gcc-cf9e9959d1a5e8c7ddb506f68017b4f9c9292b94.zip gcc-cf9e9959d1a5e8c7ddb506f68017b4f9c9292b94.tar.gz gcc-cf9e9959d1a5e8c7ddb506f68017b4f9c9292b94.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 53 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 3 | ||||
-rw-r--r-- | gcc/c-parser.c | 2 | ||||
-rw-r--r-- | gcc/c-typeck.c | 5 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/offsetof7.C | 17 |
11 files changed, 75 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2b9e5b3..c0bdc1a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 4a452c3..d7ff089 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -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 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 2eefe03..df8dda4 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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 diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 71746a9..7ecb57e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -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 diff --git a/gcc/c-parser.c b/gcc/c-parser.c index af6cc14..8db203a 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -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: diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 7dfdae2..46363c0 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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; } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2a1db7a..ffb085c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index a80aec6..cebb7df 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f4e45b4..386f3b8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e39ed46..218a9d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/other/offsetof7.C b/gcc/testsuite/g++.dg/other/offsetof7.C new file mode 100644 index 0000000..0ce2ee0 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/offsetof7.C @@ -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); |