On Tue, May 08, 2018 at 01:03:00PM -0400, Jason Merrill wrote: > On Sun, May 6, 2018 at 1:56 PM, Jakub Jelinek <ja...@redhat.com> wrote: > > --- gcc/c-family/c-common.c.jj 2018-03-27 21:58:55.598502113 +0200 > > +++ gcc/c-family/c-common.c 2018-05-05 10:55:47.951600802 +0200 > > @@ -6171,7 +6171,7 @@ c_common_to_target_charset (HOST_WIDE_IN > > traditional rendering of offsetof as a macro. Return the folded > > result. */ > > > > tree > > -fold_offsetof_1 (tree expr, enum tree_code ctx) > > +fold_offsetof_1 (tree expr, bool nonptr, enum tree_code ctx) > > The comment needs to document the NONPTR parameter.
Ok. > > @@ -6287,7 +6291,7 @@ fold_offsetof_1 (tree expr, enum tree_co > > tree > > fold_offsetof (tree expr) > > { > > - return convert (size_type_node, fold_offsetof_1 (expr)); > > + return convert (size_type_node, fold_offsetof_1 (expr, true)); > > } > > Since all the uses of fold_offset_1 involve converting to a particular > type, I wonder about wrapping it so that the argument for nonptr is > determined from that type. So like this? 2018-05-08 Jakub Jelinek <ja...@redhat.com> PR c++/85662 * c-common.h (fold_offsetof_1): Add TYPE argument. * c-common.c (fold_offsetof_1): Add TYPE argument, if it is not a pointer type, convert the pointer constant to TYPE and use size_binop with PLUS_EXPR instead of fold_build_pointer_plus. Adjust recursive calls. (fold_offsetof): Pass size_type_node as TYPE to fold_offsetof_1. * c-fold.c (c_fully_fold_internal): Pass TREE_TYPE (expr) as TYPE to fold_offsetof_1. * c-typeck.c (build_unary_op): Pass argtype as TYPE to fold_offsetof_1. * cp-gimplify.c (cp_fold): Pass TREE_TYPE (x) as TYPE to fold_offsetof_1. * g++.dg/ext/offsetof2.C: New test. --- gcc/c-family/c-common.h.jj 2018-05-06 23:12:49.185619717 +0200 +++ gcc/c-family/c-common.h 2018-05-08 21:47:40.976737821 +0200 @@ -1033,7 +1033,7 @@ extern bool c_dump_tree (void *, tree); extern void verify_sequence_points (tree); -extern tree fold_offsetof_1 (tree, tree_code ctx = ERROR_MARK); +extern tree fold_offsetof_1 (tree, tree, tree_code ctx = ERROR_MARK); extern tree fold_offsetof (tree); extern int complete_array_type (tree *, tree, bool); --- gcc/c-family/c-common.c.jj 2018-05-06 23:12:49.135619681 +0200 +++ gcc/c-family/c-common.c 2018-05-08 21:56:24.635088315 +0200 @@ -6168,10 +6168,12 @@ c_common_to_target_charset (HOST_WIDE_IN /* 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. */ + traditional rendering of offsetof as a macro. TYPE is the desired type of + the whole expression to which it will be converted afterwards. + Return the folded result. */ tree -fold_offsetof_1 (tree expr, enum tree_code ctx) +fold_offsetof_1 (tree type, tree expr, enum tree_code ctx) { tree base, off, t; tree_code code = TREE_CODE (expr); @@ -6196,10 +6198,12 @@ fold_offsetof_1 (tree expr, enum tree_co error ("cannot apply %<offsetof%> to a non constant address"); return error_mark_node; } + if (!POINTER_TYPE_P (type)) + return convert (type, TREE_OPERAND (expr, 0)); return TREE_OPERAND (expr, 0); case COMPONENT_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code); + base = fold_offsetof_1 (type, TREE_OPERAND (expr, 0), code); if (base == error_mark_node) return base; @@ -6216,7 +6220,7 @@ fold_offsetof_1 (tree expr, enum tree_co break; case ARRAY_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code); + base = fold_offsetof_1 (type, TREE_OPERAND (expr, 0), code); if (base == error_mark_node) return base; @@ -6273,12 +6277,14 @@ fold_offsetof_1 (tree expr, enum tree_co /* Handle static members of volatile structs. */ t = TREE_OPERAND (expr, 1); gcc_checking_assert (VAR_P (get_base_address (t))); - return fold_offsetof_1 (t); + return fold_offsetof_1 (type, t); default: gcc_unreachable (); } + if (!POINTER_TYPE_P (type)) + return size_binop (PLUS_EXPR, base, convert (type, off)); return fold_build_pointer_plus (base, off); } @@ -6287,7 +6293,7 @@ fold_offsetof_1 (tree expr, enum tree_co tree fold_offsetof (tree expr) { - return convert (size_type_node, fold_offsetof_1 (expr)); + return convert (size_type_node, fold_offsetof_1 (size_type_node, expr)); } --- gcc/c/c-fold.c.jj 2018-01-17 22:00:12.310228253 +0100 +++ gcc/c/c-fold.c 2018-05-08 21:52:43.303940175 +0200 @@ -473,7 +473,8 @@ c_fully_fold_internal (tree expr, bool i && (op1 = get_base_address (op0)) != NULL_TREE && INDIRECT_REF_P (op1) && TREE_CONSTANT (TREE_OPERAND (op1, 0))) - ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0)); + ret = fold_convert_loc (loc, TREE_TYPE (expr), + fold_offsetof_1 (TREE_TYPE (expr), op0)); else if (op0 != orig_op0 || in_init) ret = in_init ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0) --- gcc/c/c-typeck.c.jj 2018-04-25 11:35:11.974267304 +0200 +++ gcc/c/c-typeck.c 2018-05-08 21:53:04.582954414 +0200 @@ -4676,7 +4676,8 @@ build_unary_op (location_t location, enu if (val && INDIRECT_REF_P (val) && TREE_CONSTANT (TREE_OPERAND (val, 0))) { - ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg)); + ret = fold_convert_loc (location, argtype, + fold_offsetof_1 (argtype, arg)); goto return_build_unary_op; } --- gcc/cp/cp-gimplify.c.jj 2018-04-19 15:57:36.784482581 +0200 +++ gcc/cp/cp-gimplify.c 2018-05-08 21:53:45.439981764 +0200 @@ -2232,7 +2232,8 @@ cp_fold (tree x) val = TREE_OPERAND (val, 0); STRIP_NOPS (val); if (TREE_CODE (val) == INTEGER_CST) - return fold_convert (TREE_TYPE (x), fold_offsetof_1 (op0)); + return fold_convert (TREE_TYPE (x), + fold_offsetof_1 (TREE_TYPE (x), op0)); } } goto finish_unary; --- gcc/testsuite/g++.dg/ext/offsetof2.C.jj 2018-05-08 21:47:20.406724048 +0200 +++ gcc/testsuite/g++.dg/ext/offsetof2.C 2018-05-08 21:47:20.406724048 +0200 @@ -0,0 +1,6 @@ +// PR c++/85662 +// { dg-do compile { target c++11 } } + +struct S { unsigned long x[31]; }; +struct T { bool b; S f; }; +static_assert (__builtin_offsetof (T, f.x[31 - 1]) == __builtin_offsetof (T, f.x[30]), ""); Jakub