diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4c0ff4b47944ec472d4da796413de1227ec2d88..d2bc8c54cd004eccdfa42fb29eb8c5a3c456b5c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2006-08-17 Paolo Bonzini <bonzini@gnu.org> + + PR c++/28573 + * c-common.c (fold_offsetof_1): Add an argument and recurse down to it + or the INTEGER_CST. Fail on a CALL_EXPR. + (fold_offsetof): Pass new argument to fold_offsetof_1. + * c-parser.c (c_parser_postfix_expression): Don't include a NULL + operand into an INDIRECT_REF. + * c-typeck.c (build_unary_op): Adjust call to fold_offsetof. + 2006-08-16 Zdenek Dvorak <dvorakz@suse.cz> PR gcov/profile/26570 diff --git a/gcc/c-common.c b/gcc/c-common.c index 167d04b81ff09f08c1a4f2f6942892dde3c0c804..17643f0b5abc5dcd930e0411f174e10613f0da98 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5982,16 +5982,19 @@ c_common_to_target_charset (HOST_WIDE_INT c) } /* 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: @@ -6001,11 +6004,22 @@ fold_offsetof_1 (tree expr) 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; @@ -6022,7 +6036,7 @@ fold_offsetof_1 (tree expr) 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; @@ -6044,10 +6058,10 @@ fold_offsetof_1 (tree expr) } 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 diff --git a/gcc/c-common.h b/gcc/c-common.h index 4f4919e9b0b76f45fcc30a60e402e3c682470a0d..633990a3a35bc47c409db4f81d135413f063bab1 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -830,7 +830,7 @@ extern void c_warn_unused_result (tree *); extern void verify_sequence_points (tree); -extern tree fold_offsetof (tree); +extern tree fold_offsetof (tree, 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 6e243dff58a5d000cdaed0512e4c984349470f2b..9031e5b4d2f2aba953f4172f682c4bf4e9100d70 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -5203,7 +5203,7 @@ c_parser_postfix_expression (c_parser *parser) 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. */ @@ -5245,7 +5245,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); + expr.value = fold_offsetof (offsetof_ref, NULL_TREE); expr.original_code = ERROR_MARK; } break; diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index dee7414e43aea402cb5dd1af358d439f9b807fa9..c55bcad89c98b37b836040f8169411cc62fa4ed9 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -3057,7 +3057,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (val && TREE_CODE (val) == INDIRECT_REF && TREE_CONSTANT (TREE_OPERAND (val, 0))) { - tree op0 = fold_convert (argtype, fold_offsetof (arg)), op1; + tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1; op1 = fold_convert (argtype, TREE_OPERAND (val, 0)); return fold_build2 (PLUS_EXPR, argtype, op0, op1); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cde739dbb95a9fcfd39f91425cb7bdb6a531720a..7048c5f1411ecdf70bbcb6d613ac23c774abb8ba 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,8 +1,13 @@ +2006-08-17 Paolo Bonzini <bonzini@gnu.org> + + PR c++/28573 + * semantics.c (finish_offsetof): Add new argument to fold_offsetof. + 2006-08-16 Andrew Pinski <pinskia@physics.uc.edu> PR c++/28302 * typeck.c (build_unary_op <case BIT_NOT_EXPR:>): Don't call - perform_integral_promotions for non integral type + perform_integral_promotions for non integral type. 2006-08-16 Jason Merrill <jason@redhat.com> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index d36eba76e4143b717e49cb45448c968cd2b55237..fb4ea0a79dfa5efe928ad41083026c1bfa9d1339 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2904,7 +2904,7 @@ finish_offsetof (tree expr) error ("cannot apply %<offsetof%> to member function %qD", expr); return error_mark_node; } - return fold_offsetof (expr); + return fold_offsetof (expr, NULL_TREE); } /* Called from expand_body via walk_tree. Replace all AGGR_INIT_EXPRs diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3da59b8a44e5b47c168aa7c00e092982cdcd1d0c..624a2f23d73efa61cd5d4036acb77f3d38344840 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2006-08-17 Paolo Bonzini <bonzini@gnu.org> + + * PR c++/28573 + * g++.dg/parse/offsetof6.C: New test. + * g++.dg/parse/offsetof6.C: New test. + * g++.dg/parse/offsetof7.C: New test. + 2006-08-16 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> PR testsuite/28602 @@ -6,7 +13,7 @@ 2006-08-16 Andrew Pinski <pinskia@physics.uc.edu> - PR C++/28302 + PR c++/28302 * g++.dg/ext/vector3.C: New test. 2006-08-16 Zdenek Dvorak <dvorakz@suse.cz> diff --git a/gcc/testsuite/g++.dg/parse/offsetof6.C b/gcc/testsuite/g++.dg/parse/offsetof6.C new file mode 100644 index 0000000000000000000000000000000000000000..0e07a538009c05aa641421f7caade6ef1850304c --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/offsetof6.C @@ -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" } */ +} diff --git a/gcc/testsuite/g++.dg/parse/offsetof7.C b/gcc/testsuite/g++.dg/parse/offsetof7.C new file mode 100644 index 0000000000000000000000000000000000000000..113a7954726d74ff534169c34375598d22db25df --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/offsetof7.C @@ -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" } */ +}