* [C++ PATCH 1/4] Handle location wrappers better in warn_logical_operator. @ 2019-09-16 4:33 Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion Jason Merrill ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Jason Merrill @ 2019-09-16 4:33 UTC (permalink / raw) To: gcc-patches When we introduced location wrappers, we added fold_for_warn to warnings that are interested in a constant value, or wrapper-stripping to warnings that are interested in literal constants. This particular warning is looking for a literal constant, but was wrongly changed to use fold_for_warn; this patch makes it strip instead. Tested x86_64-pc-linux-gnu, applying to trunk. * c-warn.c (warn_logical_operator): Strip location wrappers. Don't fold_for_warn in "|| mask" warning. --- gcc/c-family/c-warn.c | 40 ++++++++++++++++++++-------------------- gcc/c-family/ChangeLog | 5 +++++ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index d671b77a2b0..bee5449bcb1 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -208,32 +208,32 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, programmer. That is, an expression such as op && MASK where op should not be any boolean expression, nor a constant, and mask seems to be a non-boolean integer constant. */ + STRIP_ANY_LOCATION_WRAPPER (op_right); if (TREE_CODE (op_right) == CONST_DECL) /* An enumerator counts as a constant. */ op_right = DECL_INITIAL (op_right); + tree stripped_op_left = tree_strip_any_location_wrapper (op_left); if (!truth_value_p (code_left) && INTEGRAL_TYPE_P (TREE_TYPE (op_left)) - && !CONSTANT_CLASS_P (op_left) - && !TREE_NO_WARNING (op_left)) + && !CONSTANT_CLASS_P (stripped_op_left) + && TREE_CODE (stripped_op_left) != CONST_DECL + && !TREE_NO_WARNING (op_left) + && TREE_CODE (op_right) == INTEGER_CST + && !integer_zerop (op_right) + && !integer_onep (op_right)) { - tree folded_op_right = fold_for_warn (op_right); - if (TREE_CODE (folded_op_right) == INTEGER_CST - && !integer_zerop (folded_op_right) - && !integer_onep (folded_op_right)) - { - bool warned; - if (or_op) - warned - = warning_at (location, OPT_Wlogical_op, - "logical %<or%> applied to non-boolean constant"); - else - warned - = warning_at (location, OPT_Wlogical_op, - "logical %<and%> applied to non-boolean constant"); - if (warned) - TREE_NO_WARNING (op_left) = true; - return; - } + bool warned; + if (or_op) + warned + = warning_at (location, OPT_Wlogical_op, + "logical %<or%> applied to non-boolean constant"); + else + warned + = warning_at (location, OPT_Wlogical_op, + "logical %<and%> applied to non-boolean constant"); + if (warned) + TREE_NO_WARNING (op_left) = true; + return; } /* We do not warn for constants because they are typical of macro diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 2b700c2c4bd..93bdf3e0798 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2019-09-15 Jason Merrill <jason@redhat.com> + + * c-warn.c (warn_logical_operator): Strip location wrappers. Don't + fold_for_warn in "|| mask" warning. + 2019-09-10 Martin Liska <mliska@suse.cz> * c.opt: Use newly added WarnRemoved. base-commit: ce026385ee57427978053620a038bffaac90819e -- 2.21.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion. 2019-09-16 4:33 [C++ PATCH 1/4] Handle location wrappers better in warn_logical_operator Jason Merrill @ 2019-09-16 4:33 ` Jason Merrill 2019-09-21 6:23 ` Jakub Jelinek 2019-09-16 4:33 ` [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 3/4] PR c++/82165 - enum bitfields and operator overloading Jason Merrill 2 siblings, 1 reply; 13+ messages in thread From: Jason Merrill @ 2019-09-16 4:33 UTC (permalink / raw) To: gcc-patches Here, if cp_perform_integral_promotions saw that the TREE_TYPE of a bit-field reference was the same as the type it promotes to, it didn't do anything. But then decay_conversion saw that the bit-field reference was unchanged, and converted it to its declared type. So I needed to add something to make it clear that promotion has been done. But then the 33819 change caused trouble by looking through the NOP_EXPR I just added. This was the wrong fix for that bug; I've now fixed that better by recognizing in cp_perform_integral_promotions that we won't promote a bit-field larger than 32 bits, so we should use the declared type. Tested x86_64-pc-linux-gnu, applying to trunk. PR c++/33819 - long bit-field promotion. * typeck.c (cp_perform_integral_promotions): Handle large bit-fields properly. Handle 32-bit non-int bit-fields properly. (is_bitfield_expr_with_lowered_type): Don't look through NOP_EXPR. --- gcc/cp/typeck.c | 29 ++++++++++++++++---------- gcc/testsuite/g++.dg/expr/bitfield14.C | 17 +++++++++++++++ gcc/cp/ChangeLog | 6 ++++++ 3 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/expr/bitfield14.C diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 620f2c9afdf..c6bf41ee7a4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1971,12 +1971,6 @@ is_bitfield_expr_with_lowered_type (const_tree exp) else return NULL_TREE; - CASE_CONVERT: - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0))) - == TYPE_MAIN_VARIANT (TREE_TYPE (exp))) - return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); - /* Fallthrough. */ - default: return NULL_TREE; } @@ -2189,13 +2183,23 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) if (error_operand_p (expr)) return error_mark_node; + type = TREE_TYPE (expr); + /* [conv.prom] - If the bitfield has an enumerated type, it is treated as any - other value of that type for promotion purposes. */ - type = is_bitfield_expr_with_lowered_type (expr); - if (!type || TREE_CODE (type) != ENUMERAL_TYPE) - type = TREE_TYPE (expr); + A prvalue for an integral bit-field (11.3.9) can be converted to a prvalue + of type int if int can represent all the values of the bit-field; + otherwise, it can be converted to unsigned int if unsigned int can + represent all the values of the bit-field. If the bit-field is larger yet, + no integral promotion applies to it. If the bit-field has an enumerated + type, it is treated as any other value of that type for promotion + purposes. */ + tree bitfield_type = is_bitfield_expr_with_lowered_type (expr); + if (bitfield_type + && (TREE_CODE (bitfield_type) == ENUMERAL_TYPE + || TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node))) + type = bitfield_type; + gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type)); /* Scoped enums don't promote. */ if (SCOPED_ENUM_P (type)) @@ -2203,6 +2207,9 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) promoted_type = type_promotes_to (type); if (type != promoted_type) expr = cp_convert (promoted_type, expr, complain); + else if (bitfield_type && bitfield_type != type) + /* Prevent decay_conversion from converting to bitfield_type. */ + expr = build_nop (type, expr); return expr; } diff --git a/gcc/testsuite/g++.dg/expr/bitfield14.C b/gcc/testsuite/g++.dg/expr/bitfield14.C new file mode 100644 index 00000000000..546af85ba10 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield14.C @@ -0,0 +1,17 @@ +// PR c++/30277 +// { dg-do compile { target c++11 } } + +struct S +{ + signed long l: 32; +}; + +void foo(long) = delete; +void foo(int) {} + +int main() +{ + S x = {1}; + foo(x.l+0); + return 0; +} diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bed72c90a2e..7bf28f81fae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2019-09-15 Jason Merrill <jason@redhat.com> + PR c++/30277 - int-width bit-field promotion. + PR c++/33819 - long bit-field promotion. + * typeck.c (cp_perform_integral_promotions): Handle large bit-fields + properly. Handle 32-bit non-int bit-fields properly. + (is_bitfield_expr_with_lowered_type): Don't look through NOP_EXPR. + PR c++/82165 - enum bitfields and operator overloading. * call.c (build_new_op_1): Use unlowered_expr_type. -- 2.21.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion. 2019-09-16 4:33 ` [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion Jason Merrill @ 2019-09-21 6:23 ` Jakub Jelinek 2019-09-21 21:51 ` Jason Merrill 0 siblings, 1 reply; 13+ messages in thread From: Jakub Jelinek @ 2019-09-21 6:23 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches On Mon, Sep 16, 2019 at 12:33:28AM -0400, Jason Merrill wrote: > Here, if cp_perform_integral_promotions saw that the TREE_TYPE of a > bit-field reference was the same as the type it promotes to, it didn't do > anything. But then decay_conversion saw that the bit-field reference was > unchanged, and converted it to its declared type. So I needed to add > something to make it clear that promotion has been done. But then the 33819 > change caused trouble by looking through the NOP_EXPR I just added. This > was the wrong fix for that bug; I've now fixed that better by recognizing in > cp_perform_integral_promotions that we won't promote a bit-field larger than > 32 bits, so we should use the declared type. > > Tested x86_64-pc-linux-gnu, applying to trunk. > > PR c++/33819 - long bit-field promotion. > * typeck.c (cp_perform_integral_promotions): Handle large bit-fields > properly. Handle 32-bit non-int bit-fields properly. > (is_bitfield_expr_with_lowered_type): Don't look through NOP_EXPR. > --- /dev/null > +++ b/gcc/testsuite/g++.dg/expr/bitfield14.C > @@ -0,0 +1,17 @@ > +// PR c++/30277 > +// { dg-do compile { target c++11 } } > + > +struct S > +{ > + signed long l: 32; > +}; > + > +void foo(long) = delete; > +void foo(int) {} > + > +int main() > +{ > + S x = {1}; > + foo(x.l+0); > + return 0; > +} This testcase fails on all targets where int and long have the same precision. Is that a bug on the compiler side, or should the testcase just use a type with a larger precision than int (i.e. long long), like following (tested on x86_64-linux and i686-linux): 2019-09-21 Jakub Jelinek <jakub@redhat.com> PR c++/30277 * g++.dg/expr/bitfield14.C (struct S): Use signed long long instead of signed long. (foo): Use long long instead of long. --- gcc/testsuite/g++.dg/expr/bitfield14.C.jj 2019-09-20 12:25:24.833748976 +0200 +++ gcc/testsuite/g++.dg/expr/bitfield14.C 2019-09-21 08:17:18.500234760 +0200 @@ -3,10 +3,10 @@ struct S { - signed long l: 32; + signed long long l: 32; }; -void foo(long) = delete; +void foo(long long) = delete; void foo(int) {} int main() Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion. 2019-09-21 6:23 ` Jakub Jelinek @ 2019-09-21 21:51 ` Jason Merrill 0 siblings, 0 replies; 13+ messages in thread From: Jason Merrill @ 2019-09-21 21:51 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches List On Sat, Sep 21, 2019 at 2:23 AM Jakub Jelinek <jakub@redhat.com> wrote: > > On Mon, Sep 16, 2019 at 12:33:28AM -0400, Jason Merrill wrote: > > Here, if cp_perform_integral_promotions saw that the TREE_TYPE of a > > bit-field reference was the same as the type it promotes to, it didn't do > > anything. But then decay_conversion saw that the bit-field reference was > > unchanged, and converted it to its declared type. So I needed to add > > something to make it clear that promotion has been done. But then the 33819 > > change caused trouble by looking through the NOP_EXPR I just added. This > > was the wrong fix for that bug; I've now fixed that better by recognizing in > > cp_perform_integral_promotions that we won't promote a bit-field larger than > > 32 bits, so we should use the declared type. > > > > Tested x86_64-pc-linux-gnu, applying to trunk. > > > > PR c++/33819 - long bit-field promotion. > > * typeck.c (cp_perform_integral_promotions): Handle large bit-fields > > properly. Handle 32-bit non-int bit-fields properly. > > (is_bitfield_expr_with_lowered_type): Don't look through NOP_EXPR. > > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/expr/bitfield14.C > > @@ -0,0 +1,17 @@ > > +// PR c++/30277 > > +// { dg-do compile { target c++11 } } > > + > > +struct S > > +{ > > + signed long l: 32; > > +}; > > + > > +void foo(long) = delete; > > +void foo(int) {} > > + > > +int main() > > +{ > > + S x = {1}; > > + foo(x.l+0); > > + return 0; > > +} > > This testcase fails on all targets where int and long have the same > precision. Is that a bug on the compiler side, or should the testcase just > use a type with a larger precision than int (i.e. long long), like following > (tested on x86_64-linux and i686-linux): It's a testcase bug. > 2019-09-21 Jakub Jelinek <jakub@redhat.com> > > PR c++/30277 > * g++.dg/expr/bitfield14.C (struct S): Use signed long long instead > of signed long. > (foo): Use long long instead of long. OK, thanks. Jason ^ permalink raw reply [flat|nested] 13+ messages in thread
* [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-16 4:33 [C++ PATCH 1/4] Handle location wrappers better in warn_logical_operator Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion Jason Merrill @ 2019-09-16 4:33 ` Jason Merrill 2019-09-17 14:07 ` Andreas Schwab 2019-09-19 0:19 ` JiangNing OS 2019-09-16 4:33 ` [C++ PATCH 3/4] PR c++/82165 - enum bitfields and operator overloading Jason Merrill 2 siblings, 2 replies; 13+ messages in thread From: Jason Merrill @ 2019-09-16 4:33 UTC (permalink / raw) To: gcc-patches While working on C++20 operator<=>, I noticed that build_new_op_1 was doing too much conversion when a built-in candidate was selected; the standard says it should only perform user-defined conversions, and then leave the normal operator semantics to handle any standard conversions. This is important for operator<=> because a comparison of two different unscoped enums is ill-formed; if we promote the enums to int here, cp_build_binary_op never gets to see the original operand types, so we can't give the error. Tested x86_64-pc-linux-gnu, applying to trunk. * call.c (build_new_op_1): Don't apply any standard conversions to the operands of a built-in operator. Don't suppress conversions in cp_build_unary_op. * typeck.c (cp_build_unary_op): Do integral promotions for enums. --- gcc/cp/call.c | 51 ++++++++++++++++++++++++------------------------ gcc/cp/typeck.c | 4 ++-- gcc/cp/ChangeLog | 7 +++++++ 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c3045d948c5..457fa6605c2 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6139,41 +6139,40 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, break; } - /* We need to strip any leading REF_BIND so that bitfields - don't cause errors. This should not remove any important - conversions, because builtins don't apply to class - objects directly. */ + /* "If a built-in candidate is selected by overload resolution, the + operands of class type are converted to the types of the + corresponding parameters of the selected operation function, + except that the second standard conversion sequence of a + user-defined conversion sequence (12.3.3.1.2) is not applied." */ conv = cand->convs[0]; - if (conv->kind == ck_ref_bind) - conv = next_conversion (conv); - arg1 = convert_like (conv, arg1, complain); + if (conv->user_conv_p) + { + while (conv->kind != ck_user) + conv = next_conversion (conv); + arg1 = convert_like (conv, arg1, complain); + } if (arg2) { conv = cand->convs[1]; - if (conv->kind == ck_ref_bind) - conv = next_conversion (conv); - else - arg2 = decay_conversion (arg2, complain); - - /* We need to call warn_logical_operator before - converting arg2 to a boolean_type, but after - decaying an enumerator to its value. */ - if (complain & tf_warning) - warn_logical_operator (loc, code, boolean_type_node, - code_orig_arg1, arg1, - code_orig_arg2, arg2); - - arg2 = convert_like (conv, arg2, complain); + if (conv->user_conv_p) + { + while (conv->kind != ck_user) + conv = next_conversion (conv); + arg2 = convert_like (conv, arg2, complain); + } } + if (arg3) { conv = cand->convs[2]; - if (conv->kind == ck_ref_bind) - conv = next_conversion (conv); - convert_like (conv, arg3, complain); + if (conv->user_conv_p) + { + while (conv->kind != ck_user) + conv = next_conversion (conv); + arg3 = convert_like (conv, arg3, complain); + } } - } } @@ -6241,7 +6240,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, case REALPART_EXPR: case IMAGPART_EXPR: case ABS_EXPR: - return cp_build_unary_op (code, arg1, candidates != 0, complain); + return cp_build_unary_op (code, arg1, false, complain); case ARRAY_REF: return cp_build_array_ref (input_location, arg1, arg2, complain); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 70094d1b426..620f2c9afdf 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6242,7 +6242,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert, : _("wrong type argument to unary plus")); else { - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus @@ -6267,7 +6267,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert, | WANT_VECTOR_OR_COMPLEX, arg, true))) errstring = _("wrong type argument to bit-complement"); - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) { /* Warn if the expression has boolean value. */ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e92d49f1b76..a03a428109b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-09-15 Jason Merrill <jason@redhat.com> + + * call.c (build_new_op_1): Don't apply any standard conversions to + the operands of a built-in operator. Don't suppress conversions in + cp_build_unary_op. + * typeck.c (cp_build_unary_op): Do integral promotions for enums. + 2019-09-15 Marek Polacek <polacek@redhat.com> PR c++/91740 - ICE with constexpr call and ?: in ARRAY_REF. -- 2.21.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-16 4:33 ` [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates Jason Merrill @ 2019-09-17 14:07 ` Andreas Schwab 2019-09-17 14:19 ` Iain Sandoe 2019-09-19 0:19 ` JiangNing OS 1 sibling, 1 reply; 13+ messages in thread From: Andreas Schwab @ 2019-09-17 14:07 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches This breaks bootstrap on aarch64 (during stage2 build): ../../gcc/expmed.c: In function 'rtx_def* emit_store_flag_1(rtx, rtx_code, rtx, rtx, machine_mode, int, int, machine_mode)': ../../gcc/expmed.c:5602:19: error: 'int_mode' may be used uninitialized in this function [-Werror=maybe-uninitialized] 5602 | scalar_int_mode int_mode; | ^~~~~~~~ Andreas. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-17 14:07 ` Andreas Schwab @ 2019-09-17 14:19 ` Iain Sandoe 0 siblings, 0 replies; 13+ messages in thread From: Iain Sandoe @ 2019-09-17 14:19 UTC (permalink / raw) To: Jason Merrill; +Cc: GCC Patches > On 17 Sep 2019, at 15:06, Andreas Schwab <schwab@suse.de> wrote: > > This breaks bootstrap on aarch64 (during stage2 build): for the record, also on x86_64-darwin1x (attempting some analysis). Iain > > ../../gcc/expmed.c: In function 'rtx_def* emit_store_flag_1(rtx, rtx_code, rtx, rtx, machine_mode, int, int, machine_mode)': > ../../gcc/expmed.c:5602:19: error: 'int_mode' may be used uninitialized in this function [-Werror=maybe-uninitialized] > 5602 | scalar_int_mode int_mode; > | ^~~~~~~~ > > Andreas. > > -- > Andreas Schwab, SUSE Labs, schwab@suse.de > GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 > "And now for something completely different." ^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-16 4:33 ` [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates Jason Merrill 2019-09-17 14:07 ` Andreas Schwab @ 2019-09-19 0:19 ` JiangNing OS 2019-09-19 19:43 ` Jason Merrill 1 sibling, 1 reply; 13+ messages in thread From: JiangNing OS @ 2019-09-19 0:19 UTC (permalink / raw) To: Jason Merrill, gcc-patches; +Cc: Feng Xue OS Hi Jason, This commit caused boot-strap failure on aarch64. Is it a bug? Can this be fixed ASAP? ../../gcc/gcc/expmed.c:5602:19: error: ���int_mode��� may be used uninitialized in this function [-Werror=maybe-uninitialized] 5602 | scalar_int_mode int_mode; | ^~~~~~~~ Thanks, -Jiangning > -----Original Message----- > From: gcc-patches-owner@gcc.gnu.org <gcc-patches-owner@gcc.gnu.org> > On Behalf Of Jason Merrill > Sent: Monday, September 16, 2019 12:33 PM > To: gcc-patches@gcc.gnu.org > Subject: [C++ PATCH 2/4] Fix conversions for built-in operator overloading > candidates. > > While working on C++20 operator<=>, I noticed that build_new_op_1 was > doing too much conversion when a built-in candidate was selected; the > standard says it should only perform user-defined conversions, and then > leave the normal operator semantics to handle any standard conversions. > This is important for operator<=> because a comparison of two different > unscoped enums is ill-formed; if we promote the enums to int here, > cp_build_binary_op never gets to see the original operand types, so we can't > give the error. > > Tested x86_64-pc-linux-gnu, applying to trunk. > > * call.c (build_new_op_1): Don't apply any standard conversions to > the operands of a built-in operator. Don't suppress conversions in > cp_build_unary_op. > * typeck.c (cp_build_unary_op): Do integral promotions for enums. > --- > gcc/cp/call.c | 51 ++++++++++++++++++++++++------------------------ > gcc/cp/typeck.c | 4 ++-- > gcc/cp/ChangeLog | 7 +++++++ > 3 files changed, 34 insertions(+), 28 deletions(-) > > diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c3045d948c5..457fa6605c2 > 100644 > --- a/gcc/cp/call.c > +++ b/gcc/cp/call.c > @@ -6139,41 +6139,40 @@ build_new_op_1 (const op_location_t &loc, > enum tree_code code, int flags, > break; > } > > - /* We need to strip any leading REF_BIND so that bitfields > - don't cause errors. This should not remove any important > - conversions, because builtins don't apply to class > - objects directly. */ > + /* "If a built-in candidate is selected by overload resolution, the > + operands of class type are converted to the types of the > + corresponding parameters of the selected operation function, > + except that the second standard conversion sequence of a > + user-defined conversion sequence (12.3.3.1.2) is not applied." > +*/ > conv = cand->convs[0]; > - if (conv->kind == ck_ref_bind) > - conv = next_conversion (conv); > - arg1 = convert_like (conv, arg1, complain); > + if (conv->user_conv_p) > + { > + while (conv->kind != ck_user) > + conv = next_conversion (conv); > + arg1 = convert_like (conv, arg1, complain); > + } > > if (arg2) > { > conv = cand->convs[1]; > - if (conv->kind == ck_ref_bind) > - conv = next_conversion (conv); > - else > - arg2 = decay_conversion (arg2, complain); > - > - /* We need to call warn_logical_operator before > - converting arg2 to a boolean_type, but after > - decaying an enumerator to its value. */ > - if (complain & tf_warning) > - warn_logical_operator (loc, code, boolean_type_node, > - code_orig_arg1, arg1, > - code_orig_arg2, arg2); > - > - arg2 = convert_like (conv, arg2, complain); > + if (conv->user_conv_p) > + { > + while (conv->kind != ck_user) > + conv = next_conversion (conv); > + arg2 = convert_like (conv, arg2, complain); > + } > } > + > if (arg3) > { > conv = cand->convs[2]; > - if (conv->kind == ck_ref_bind) > - conv = next_conversion (conv); > - convert_like (conv, arg3, complain); > + if (conv->user_conv_p) > + { > + while (conv->kind != ck_user) > + conv = next_conversion (conv); > + arg3 = convert_like (conv, arg3, complain); > + } > } > - > } > } > > @@ -6241,7 +6240,7 @@ build_new_op_1 (const op_location_t &loc, enum > tree_code code, int flags, > case REALPART_EXPR: > case IMAGPART_EXPR: > case ABS_EXPR: > - return cp_build_unary_op (code, arg1, candidates != 0, complain); > + return cp_build_unary_op (code, arg1, false, complain); > > case ARRAY_REF: > return cp_build_array_ref (input_location, arg1, arg2, complain); diff --git > a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 70094d1b426..620f2c9afdf 100644 > --- a/gcc/cp/typeck.c > +++ b/gcc/cp/typeck.c > @@ -6242,7 +6242,7 @@ cp_build_unary_op (enum tree_code code, tree > xarg, bool noconvert, > : _("wrong type argument to unary plus")); > else > { > - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > (TREE_TYPE > +(arg))) > arg = cp_perform_integral_promotions (arg, complain); > > /* Make sure the result is not an lvalue: a unary plus or minus @@ > -6267,7 +6267,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, > bool noconvert, > | > WANT_VECTOR_OR_COMPLEX, > arg, true))) > errstring = _("wrong type argument to bit-complement"); > - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > (TREE_TYPE > + (arg))) > { > /* Warn if the expression has boolean value. */ > if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE diff --git > a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e92d49f1b76..a03a428109b > 100644 > --- a/gcc/cp/ChangeLog > +++ b/gcc/cp/ChangeLog > @@ -1,3 +1,10 @@ > +2019-09-15 Jason Merrill <jason@redhat.com> > + > + * call.c (build_new_op_1): Don't apply any standard conversions to > + the operands of a built-in operator. Don't suppress conversions in > + cp_build_unary_op. > + * typeck.c (cp_build_unary_op): Do integral promotions for enums. > + > 2019-09-15 Marek Polacek <polacek@redhat.com> > > PR c++/91740 - ICE with constexpr call and ?: in ARRAY_REF. > -- > 2.21.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-19 0:19 ` JiangNing OS @ 2019-09-19 19:43 ` Jason Merrill 2019-09-19 20:11 ` Jason Merrill 2019-11-05 23:53 ` Jason Merrill 0 siblings, 2 replies; 13+ messages in thread From: Jason Merrill @ 2019-09-19 19:43 UTC (permalink / raw) To: JiangNing OS; +Cc: gcc-patches, Feng Xue OS I've reverted this patch for the moment. On Wed, Sep 18, 2019 at 8:19 PM JiangNing OS <jiangning@os.amperecomputing.com> wrote: > > Hi Jason, > > This commit caused boot-strap failure on aarch64. Is it a bug? Can this be fixed ASAP? > > ../../gcc/gcc/expmed.c:5602:19: error: ���int_mode��� may be used uninitialized in this function [-Werror=maybe-uninitialized] > 5602 | scalar_int_mode int_mode; > | ^~~~~~~~ > > Thanks, > -Jiangning > > > -----Original Message----- > > From: gcc-patches-owner@gcc.gnu.org <gcc-patches-owner@gcc.gnu.org> > > On Behalf Of Jason Merrill > > Sent: Monday, September 16, 2019 12:33 PM > > To: gcc-patches@gcc.gnu.org > > Subject: [C++ PATCH 2/4] Fix conversions for built-in operator overloading > > candidates. > > > > While working on C++20 operator<=>, I noticed that build_new_op_1 was > > doing too much conversion when a built-in candidate was selected; the > > standard says it should only perform user-defined conversions, and then > > leave the normal operator semantics to handle any standard conversions. > > This is important for operator<=> because a comparison of two different > > unscoped enums is ill-formed; if we promote the enums to int here, > > cp_build_binary_op never gets to see the original operand types, so we can't > > give the error. > > > > Tested x86_64-pc-linux-gnu, applying to trunk. > > > > * call.c (build_new_op_1): Don't apply any standard conversions to > > the operands of a built-in operator. Don't suppress conversions in > > cp_build_unary_op. > > * typeck.c (cp_build_unary_op): Do integral promotions for enums. > > --- > > gcc/cp/call.c | 51 ++++++++++++++++++++++++------------------------ > > gcc/cp/typeck.c | 4 ++-- > > gcc/cp/ChangeLog | 7 +++++++ > > 3 files changed, 34 insertions(+), 28 deletions(-) > > > > diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c3045d948c5..457fa6605c2 > > 100644 > > --- a/gcc/cp/call.c > > +++ b/gcc/cp/call.c > > @@ -6139,41 +6139,40 @@ build_new_op_1 (const op_location_t &loc, > > enum tree_code code, int flags, > > break; > > } > > > > - /* We need to strip any leading REF_BIND so that bitfields > > - don't cause errors. This should not remove any important > > - conversions, because builtins don't apply to class > > - objects directly. */ > > + /* "If a built-in candidate is selected by overload resolution, the > > + operands of class type are converted to the types of the > > + corresponding parameters of the selected operation function, > > + except that the second standard conversion sequence of a > > + user-defined conversion sequence (12.3.3.1.2) is not applied." > > +*/ > > conv = cand->convs[0]; > > - if (conv->kind == ck_ref_bind) > > - conv = next_conversion (conv); > > - arg1 = convert_like (conv, arg1, complain); > > + if (conv->user_conv_p) > > + { > > + while (conv->kind != ck_user) > > + conv = next_conversion (conv); > > + arg1 = convert_like (conv, arg1, complain); > > + } > > > > if (arg2) > > { > > conv = cand->convs[1]; > > - if (conv->kind == ck_ref_bind) > > - conv = next_conversion (conv); > > - else > > - arg2 = decay_conversion (arg2, complain); > > - > > - /* We need to call warn_logical_operator before > > - converting arg2 to a boolean_type, but after > > - decaying an enumerator to its value. */ > > - if (complain & tf_warning) > > - warn_logical_operator (loc, code, boolean_type_node, > > - code_orig_arg1, arg1, > > - code_orig_arg2, arg2); > > - > > - arg2 = convert_like (conv, arg2, complain); > > + if (conv->user_conv_p) > > + { > > + while (conv->kind != ck_user) > > + conv = next_conversion (conv); > > + arg2 = convert_like (conv, arg2, complain); > > + } > > } > > + > > if (arg3) > > { > > conv = cand->convs[2]; > > - if (conv->kind == ck_ref_bind) > > - conv = next_conversion (conv); > > - convert_like (conv, arg3, complain); > > + if (conv->user_conv_p) > > + { > > + while (conv->kind != ck_user) > > + conv = next_conversion (conv); > > + arg3 = convert_like (conv, arg3, complain); > > + } > > } > > - > > } > > } > > > > @@ -6241,7 +6240,7 @@ build_new_op_1 (const op_location_t &loc, enum > > tree_code code, int flags, > > case REALPART_EXPR: > > case IMAGPART_EXPR: > > case ABS_EXPR: > > - return cp_build_unary_op (code, arg1, candidates != 0, complain); > > + return cp_build_unary_op (code, arg1, false, complain); > > > > case ARRAY_REF: > > return cp_build_array_ref (input_location, arg1, arg2, complain); diff --git > > a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 70094d1b426..620f2c9afdf 100644 > > --- a/gcc/cp/typeck.c > > +++ b/gcc/cp/typeck.c > > @@ -6242,7 +6242,7 @@ cp_build_unary_op (enum tree_code code, tree > > xarg, bool noconvert, > > : _("wrong type argument to unary plus")); > > else > > { > > - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > > + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > > (TREE_TYPE > > +(arg))) > > arg = cp_perform_integral_promotions (arg, complain); > > > > /* Make sure the result is not an lvalue: a unary plus or minus @@ > > -6267,7 +6267,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, > > bool noconvert, > > | > > WANT_VECTOR_OR_COMPLEX, > > arg, true))) > > errstring = _("wrong type argument to bit-complement"); > > - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > > + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > > (TREE_TYPE > > + (arg))) > > { > > /* Warn if the expression has boolean value. */ > > if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE diff --git > > a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e92d49f1b76..a03a428109b > > 100644 > > --- a/gcc/cp/ChangeLog > > +++ b/gcc/cp/ChangeLog > > @@ -1,3 +1,10 @@ > > +2019-09-15 Jason Merrill <jason@redhat.com> > > + > > + * call.c (build_new_op_1): Don't apply any standard conversions to > > + the operands of a built-in operator. Don't suppress conversions in > > + cp_build_unary_op. > > + * typeck.c (cp_build_unary_op): Do integral promotions for enums. > > + > > 2019-09-15 Marek Polacek <polacek@redhat.com> > > > > PR c++/91740 - ICE with constexpr call and ?: in ARRAY_REF. > > -- > > 2.21.0 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-19 19:43 ` Jason Merrill @ 2019-09-19 20:11 ` Jason Merrill 2019-09-19 20:28 ` Marek Polacek 2019-11-05 23:53 ` Jason Merrill 1 sibling, 1 reply; 13+ messages in thread From: Jason Merrill @ 2019-09-19 20:11 UTC (permalink / raw) To: JiangNing OS; +Cc: gcc-patches, Feng Xue OS Do any of you have a reproducer for this? On Thu, Sep 19, 2019 at 3:43 PM Jason Merrill <jason@redhat.com> wrote: > > I've reverted this patch for the moment. > > On Wed, Sep 18, 2019 at 8:19 PM JiangNing OS > <jiangning@os.amperecomputing.com> wrote: > > > > Hi Jason, > > > > This commit caused boot-strap failure on aarch64. Is it a bug? Can this be fixed ASAP? > > > > ../../gcc/gcc/expmed.c:5602:19: error: ���int_mode��� may be used uninitialized in this function [-Werror=maybe-uninitialized] > > 5602 | scalar_int_mode int_mode; > > | ^~~~~~~~ > > > > Thanks, > > -Jiangning > > > > > -----Original Message----- > > > From: gcc-patches-owner@gcc.gnu.org <gcc-patches-owner@gcc.gnu.org> > > > On Behalf Of Jason Merrill > > > Sent: Monday, September 16, 2019 12:33 PM > > > To: gcc-patches@gcc.gnu.org > > > Subject: [C++ PATCH 2/4] Fix conversions for built-in operator overloading > > > candidates. > > > > > > While working on C++20 operator<=>, I noticed that build_new_op_1 was > > > doing too much conversion when a built-in candidate was selected; the > > > standard says it should only perform user-defined conversions, and then > > > leave the normal operator semantics to handle any standard conversions. > > > This is important for operator<=> because a comparison of two different > > > unscoped enums is ill-formed; if we promote the enums to int here, > > > cp_build_binary_op never gets to see the original operand types, so we can't > > > give the error. > > > > > > Tested x86_64-pc-linux-gnu, applying to trunk. > > > > > > * call.c (build_new_op_1): Don't apply any standard conversions to > > > the operands of a built-in operator. Don't suppress conversions in > > > cp_build_unary_op. > > > * typeck.c (cp_build_unary_op): Do integral promotions for enums. > > > --- > > > gcc/cp/call.c | 51 ++++++++++++++++++++++++------------------------ > > > gcc/cp/typeck.c | 4 ++-- > > > gcc/cp/ChangeLog | 7 +++++++ > > > 3 files changed, 34 insertions(+), 28 deletions(-) > > > > > > diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c3045d948c5..457fa6605c2 > > > 100644 > > > --- a/gcc/cp/call.c > > > +++ b/gcc/cp/call.c > > > @@ -6139,41 +6139,40 @@ build_new_op_1 (const op_location_t &loc, > > > enum tree_code code, int flags, > > > break; > > > } > > > > > > - /* We need to strip any leading REF_BIND so that bitfields > > > - don't cause errors. This should not remove any important > > > - conversions, because builtins don't apply to class > > > - objects directly. */ > > > + /* "If a built-in candidate is selected by overload resolution, the > > > + operands of class type are converted to the types of the > > > + corresponding parameters of the selected operation function, > > > + except that the second standard conversion sequence of a > > > + user-defined conversion sequence (12.3.3.1.2) is not applied." > > > +*/ > > > conv = cand->convs[0]; > > > - if (conv->kind == ck_ref_bind) > > > - conv = next_conversion (conv); > > > - arg1 = convert_like (conv, arg1, complain); > > > + if (conv->user_conv_p) > > > + { > > > + while (conv->kind != ck_user) > > > + conv = next_conversion (conv); > > > + arg1 = convert_like (conv, arg1, complain); > > > + } > > > > > > if (arg2) > > > { > > > conv = cand->convs[1]; > > > - if (conv->kind == ck_ref_bind) > > > - conv = next_conversion (conv); > > > - else > > > - arg2 = decay_conversion (arg2, complain); > > > - > > > - /* We need to call warn_logical_operator before > > > - converting arg2 to a boolean_type, but after > > > - decaying an enumerator to its value. */ > > > - if (complain & tf_warning) > > > - warn_logical_operator (loc, code, boolean_type_node, > > > - code_orig_arg1, arg1, > > > - code_orig_arg2, arg2); > > > - > > > - arg2 = convert_like (conv, arg2, complain); > > > + if (conv->user_conv_p) > > > + { > > > + while (conv->kind != ck_user) > > > + conv = next_conversion (conv); > > > + arg2 = convert_like (conv, arg2, complain); > > > + } > > > } > > > + > > > if (arg3) > > > { > > > conv = cand->convs[2]; > > > - if (conv->kind == ck_ref_bind) > > > - conv = next_conversion (conv); > > > - convert_like (conv, arg3, complain); > > > + if (conv->user_conv_p) > > > + { > > > + while (conv->kind != ck_user) > > > + conv = next_conversion (conv); > > > + arg3 = convert_like (conv, arg3, complain); > > > + } > > > } > > > - > > > } > > > } > > > > > > @@ -6241,7 +6240,7 @@ build_new_op_1 (const op_location_t &loc, enum > > > tree_code code, int flags, > > > case REALPART_EXPR: > > > case IMAGPART_EXPR: > > > case ABS_EXPR: > > > - return cp_build_unary_op (code, arg1, candidates != 0, complain); > > > + return cp_build_unary_op (code, arg1, false, complain); > > > > > > case ARRAY_REF: > > > return cp_build_array_ref (input_location, arg1, arg2, complain); diff --git > > > a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 70094d1b426..620f2c9afdf 100644 > > > --- a/gcc/cp/typeck.c > > > +++ b/gcc/cp/typeck.c > > > @@ -6242,7 +6242,7 @@ cp_build_unary_op (enum tree_code code, tree > > > xarg, bool noconvert, > > > : _("wrong type argument to unary plus")); > > > else > > > { > > > - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > > > + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > > > (TREE_TYPE > > > +(arg))) > > > arg = cp_perform_integral_promotions (arg, complain); > > > > > > /* Make sure the result is not an lvalue: a unary plus or minus @@ > > > -6267,7 +6267,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, > > > bool noconvert, > > > | > > > WANT_VECTOR_OR_COMPLEX, > > > arg, true))) > > > errstring = _("wrong type argument to bit-complement"); > > > - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > > > + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > > > (TREE_TYPE > > > + (arg))) > > > { > > > /* Warn if the expression has boolean value. */ > > > if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE diff --git > > > a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e92d49f1b76..a03a428109b > > > 100644 > > > --- a/gcc/cp/ChangeLog > > > +++ b/gcc/cp/ChangeLog > > > @@ -1,3 +1,10 @@ > > > +2019-09-15 Jason Merrill <jason@redhat.com> > > > + > > > + * call.c (build_new_op_1): Don't apply any standard conversions to > > > + the operands of a built-in operator. Don't suppress conversions in > > > + cp_build_unary_op. > > > + * typeck.c (cp_build_unary_op): Do integral promotions for enums. > > > + > > > 2019-09-15 Marek Polacek <polacek@redhat.com> > > > > > > PR c++/91740 - ICE with constexpr call and ?: in ARRAY_REF. > > > -- > > > 2.21.0 > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-19 20:11 ` Jason Merrill @ 2019-09-19 20:28 ` Marek Polacek 0 siblings, 0 replies; 13+ messages in thread From: Marek Polacek @ 2019-09-19 20:28 UTC (permalink / raw) To: Jason Merrill; +Cc: JiangNing OS, gcc-patches, Feng Xue OS On Thu, Sep 19, 2019 at 04:11:16PM -0400, Jason Merrill wrote: > Do any of you have a reproducer for this? I've attached it to 91825. Marek ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates. 2019-09-19 19:43 ` Jason Merrill 2019-09-19 20:11 ` Jason Merrill @ 2019-11-05 23:53 ` Jason Merrill 1 sibling, 0 replies; 13+ messages in thread From: Jason Merrill @ 2019-11-05 23:53 UTC (permalink / raw) To: JiangNing OS; +Cc: gcc-patches, Feng Xue OS [-- Attachment #1: Type: text/plain, Size: 7899 bytes --] I'm applying this patch again now, this time with a tweak to expmed.c to prevent the false positive warning from breaking bootstrap. I don't see any problem in the gimple output, so the bug must be in the middle-end somewhere. On Thu, Sep 19, 2019 at 8:43 PM Jason Merrill <jason@redhat.com> wrote: > > I've reverted this patch for the moment. > > On Wed, Sep 18, 2019 at 8:19 PM JiangNing OS > <jiangning@os.amperecomputing.com> wrote: > > > > Hi Jason, > > > > This commit caused boot-strap failure on aarch64. Is it a bug? Can this be fixed ASAP? > > > > ../../gcc/gcc/expmed.c:5602:19: error: ���int_mode��� may be used uninitialized in this function [-Werror=maybe-uninitialized] > > 5602 | scalar_int_mode int_mode; > > | ^~~~~~~~ > > > > Thanks, > > -Jiangning > > > > > -----Original Message----- > > > From: gcc-patches-owner@gcc.gnu.org <gcc-patches-owner@gcc.gnu.org> > > > On Behalf Of Jason Merrill > > > Sent: Monday, September 16, 2019 12:33 PM > > > To: gcc-patches@gcc.gnu.org > > > Subject: [C++ PATCH 2/4] Fix conversions for built-in operator overloading > > > candidates. > > > > > > While working on C++20 operator<=>, I noticed that build_new_op_1 was > > > doing too much conversion when a built-in candidate was selected; the > > > standard says it should only perform user-defined conversions, and then > > > leave the normal operator semantics to handle any standard conversions. > > > This is important for operator<=> because a comparison of two different > > > unscoped enums is ill-formed; if we promote the enums to int here, > > > cp_build_binary_op never gets to see the original operand types, so we can't > > > give the error. > > > > > > Tested x86_64-pc-linux-gnu, applying to trunk. > > > > > > * call.c (build_new_op_1): Don't apply any standard conversions to > > > the operands of a built-in operator. Don't suppress conversions in > > > cp_build_unary_op. > > > * typeck.c (cp_build_unary_op): Do integral promotions for enums. > > > --- > > > gcc/cp/call.c | 51 ++++++++++++++++++++++++------------------------ > > > gcc/cp/typeck.c | 4 ++-- > > > gcc/cp/ChangeLog | 7 +++++++ > > > 3 files changed, 34 insertions(+), 28 deletions(-) > > > > > > diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c3045d948c5..457fa6605c2 > > > 100644 > > > --- a/gcc/cp/call.c > > > +++ b/gcc/cp/call.c > > > @@ -6139,41 +6139,40 @@ build_new_op_1 (const op_location_t &loc, > > > enum tree_code code, int flags, > > > break; > > > } > > > > > > - /* We need to strip any leading REF_BIND so that bitfields > > > - don't cause errors. This should not remove any important > > > - conversions, because builtins don't apply to class > > > - objects directly. */ > > > + /* "If a built-in candidate is selected by overload resolution, the > > > + operands of class type are converted to the types of the > > > + corresponding parameters of the selected operation function, > > > + except that the second standard conversion sequence of a > > > + user-defined conversion sequence (12.3.3.1.2) is not applied." > > > +*/ > > > conv = cand->convs[0]; > > > - if (conv->kind == ck_ref_bind) > > > - conv = next_conversion (conv); > > > - arg1 = convert_like (conv, arg1, complain); > > > + if (conv->user_conv_p) > > > + { > > > + while (conv->kind != ck_user) > > > + conv = next_conversion (conv); > > > + arg1 = convert_like (conv, arg1, complain); > > > + } > > > > > > if (arg2) > > > { > > > conv = cand->convs[1]; > > > - if (conv->kind == ck_ref_bind) > > > - conv = next_conversion (conv); > > > - else > > > - arg2 = decay_conversion (arg2, complain); > > > - > > > - /* We need to call warn_logical_operator before > > > - converting arg2 to a boolean_type, but after > > > - decaying an enumerator to its value. */ > > > - if (complain & tf_warning) > > > - warn_logical_operator (loc, code, boolean_type_node, > > > - code_orig_arg1, arg1, > > > - code_orig_arg2, arg2); > > > - > > > - arg2 = convert_like (conv, arg2, complain); > > > + if (conv->user_conv_p) > > > + { > > > + while (conv->kind != ck_user) > > > + conv = next_conversion (conv); > > > + arg2 = convert_like (conv, arg2, complain); > > > + } > > > } > > > + > > > if (arg3) > > > { > > > conv = cand->convs[2]; > > > - if (conv->kind == ck_ref_bind) > > > - conv = next_conversion (conv); > > > - convert_like (conv, arg3, complain); > > > + if (conv->user_conv_p) > > > + { > > > + while (conv->kind != ck_user) > > > + conv = next_conversion (conv); > > > + arg3 = convert_like (conv, arg3, complain); > > > + } > > > } > > > - > > > } > > > } > > > > > > @@ -6241,7 +6240,7 @@ build_new_op_1 (const op_location_t &loc, enum > > > tree_code code, int flags, > > > case REALPART_EXPR: > > > case IMAGPART_EXPR: > > > case ABS_EXPR: > > > - return cp_build_unary_op (code, arg1, candidates != 0, complain); > > > + return cp_build_unary_op (code, arg1, false, complain); > > > > > > case ARRAY_REF: > > > return cp_build_array_ref (input_location, arg1, arg2, complain); diff --git > > > a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 70094d1b426..620f2c9afdf 100644 > > > --- a/gcc/cp/typeck.c > > > +++ b/gcc/cp/typeck.c > > > @@ -6242,7 +6242,7 @@ cp_build_unary_op (enum tree_code code, tree > > > xarg, bool noconvert, > > > : _("wrong type argument to unary plus")); > > > else > > > { > > > - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > > > + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > > > (TREE_TYPE > > > +(arg))) > > > arg = cp_perform_integral_promotions (arg, complain); > > > > > > /* Make sure the result is not an lvalue: a unary plus or minus @@ > > > -6267,7 +6267,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, > > > bool noconvert, > > > | > > > WANT_VECTOR_OR_COMPLEX, > > > arg, true))) > > > errstring = _("wrong type argument to bit-complement"); > > > - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) > > > + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P > > > (TREE_TYPE > > > + (arg))) > > > { > > > /* Warn if the expression has boolean value. */ > > > if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE diff --git > > > a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e92d49f1b76..a03a428109b > > > 100644 > > > --- a/gcc/cp/ChangeLog > > > +++ b/gcc/cp/ChangeLog > > > @@ -1,3 +1,10 @@ > > > +2019-09-15 Jason Merrill <jason@redhat.com> > > > + > > > + * call.c (build_new_op_1): Don't apply any standard conversions to > > > + the operands of a built-in operator. Don't suppress conversions in > > > + cp_build_unary_op. > > > + * typeck.c (cp_build_unary_op): Do integral promotions for enums. > > > + > > > 2019-09-15 Marek Polacek <polacek@redhat.com> > > > > > > PR c++/91740 - ICE with constexpr call and ?: in ARRAY_REF. > > > -- > > > 2.21.0 > > [-- Attachment #2: conv.diff --] [-- Type: text/x-patch, Size: 6207 bytes --] commit b7924099ce49704c98e19f7385fa8e7daec3beb2 Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon Sep 16 04:34:18 2019 +0000 Fix conversions for built-in operator overloading candidates. While working on C++20 operator<=>, I noticed that build_new_op_1 was doing too much conversion when a built-in candidate was selected; the standard says it should only perform user-defined conversions, and then leave the normal operator semantics to handle any standard conversions. This is important for operator<=> because a comparison of two different unscoped enums is ill-formed; if we promote the enums to int here, cp_build_binary_op never gets to see the original operand types, so we can't give the error. I'm also disabling -Wmaybe-uninitialized for expmed.c to avoid the bootstrap failure from the last time I applied this patch. * call.c (build_new_op_1): Don't apply any standard conversions to the operands of a built-in operator. Don't suppress conversions in cp_build_unary_op. * typeck.c (cp_build_unary_op): Do integral promotions for enums. PR tree-optimization/91825 * expmed.c: Reduce -Wmaybe-uninitialized to warning. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 2a1da3cc4e1..390a4c581e2 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6156,41 +6156,40 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, break; } - /* We need to strip any leading REF_BIND so that bitfields - don't cause errors. This should not remove any important - conversions, because builtins don't apply to class - objects directly. */ + /* "If a built-in candidate is selected by overload resolution, the + operands of class type are converted to the types of the + corresponding parameters of the selected operation function, + except that the second standard conversion sequence of a + user-defined conversion sequence (12.3.3.1.2) is not applied." */ conv = cand->convs[0]; - if (conv->kind == ck_ref_bind) - conv = next_conversion (conv); - arg1 = convert_like (conv, arg1, complain); + if (conv->user_conv_p) + { + while (conv->kind != ck_user) + conv = next_conversion (conv); + arg1 = convert_like (conv, arg1, complain); + } if (arg2) { conv = cand->convs[1]; - if (conv->kind == ck_ref_bind) - conv = next_conversion (conv); - else - arg2 = decay_conversion (arg2, complain); - - /* We need to call warn_logical_operator before - converting arg2 to a boolean_type, but after - decaying an enumerator to its value. */ - if (complain & tf_warning) - warn_logical_operator (loc, code, boolean_type_node, - code_orig_arg1, arg1, - code_orig_arg2, arg2); - - arg2 = convert_like (conv, arg2, complain); + if (conv->user_conv_p) + { + while (conv->kind != ck_user) + conv = next_conversion (conv); + arg2 = convert_like (conv, arg2, complain); + } } + if (arg3) { conv = cand->convs[2]; - if (conv->kind == ck_ref_bind) - conv = next_conversion (conv); - convert_like (conv, arg3, complain); + if (conv->user_conv_p) + { + while (conv->kind != ck_user) + conv = next_conversion (conv); + arg3 = convert_like (conv, arg3, complain); + } } - } } @@ -6258,7 +6257,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, case REALPART_EXPR: case IMAGPART_EXPR: case ABS_EXPR: - return cp_build_unary_op (code, arg1, candidates != 0, complain); + return cp_build_unary_op (code, arg1, false, complain); case ARRAY_REF: return cp_build_array_ref (input_location, arg1, arg2, complain); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bf2502a3686..50240537938 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6298,7 +6298,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert, : _("wrong type argument to unary plus")); else { - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus @@ -6323,7 +6323,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert, | WANT_VECTOR_OR_COMPLEX, arg, true))) errstring = _("wrong type argument to bit-complement"); - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) { /* Warn if the expression has boolean value. */ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE diff --git a/gcc/expmed.c b/gcc/expmed.c index f1975fe33fe..ff8554b1562 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* Work around tree-optimization/91825. */ +#pragma GCC diagnostic warning "-Wmaybe-uninitialized" #include "config.h" #include "system.h" diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4312d125061..8ee23dd5986 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-10-26 Jason Merrill <jason@redhat.com> + + PR tree-optimization/91825 + * expmed.c: Reduce -Wmaybe-uninitialized to warning. + 2019-11-05 Jim Wilson <jimw@sifive.com> PR middle-end/92263 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2085319bbc9..560896a1dd8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-09-15 Jason Merrill <jason@redhat.com> + + * call.c (build_new_op_1): Don't apply any standard conversions to + the operands of a built-in operator. Don't suppress conversions in + cp_build_unary_op. + * typeck.c (cp_build_unary_op): Do integral promotions for enums. + 2019-11-04 Jason Merrill <jason@redhat.com> Use vec instead of raw array for built-in candidates. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [C++ PATCH 3/4] PR c++/82165 - enum bitfields and operator overloading. 2019-09-16 4:33 [C++ PATCH 1/4] Handle location wrappers better in warn_logical_operator Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates Jason Merrill @ 2019-09-16 4:33 ` Jason Merrill 2 siblings, 0 replies; 13+ messages in thread From: Jason Merrill @ 2019-09-16 4:33 UTC (permalink / raw) To: gcc-patches In this testcase, !f.b0 was failing to call the overloaded operator because TREE_TYPE is the magic bitfield integer type, and we weren't using unlowered_expr_type the way we do in other places. It would be nice if we could give bit-field COMPONENT_REFs their declared type until genericization time... Tested x86_64-pc-linux-gnu, applying to trunk. * call.c (build_new_op_1): Use unlowered_expr_type. --- gcc/cp/call.c | 31 ++++++++++++---------- gcc/testsuite/g++.dg/expr/bitfield13.C | 36 ++++++++++++++++++++++++++ gcc/cp/ChangeLog | 3 +++ 3 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/expr/bitfield13.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 457fa6605c2..b780b0af58e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5815,6 +5815,9 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, } tree fnname = ovl_op_identifier (ismodop, ismodop ? code2 : code); + tree arg1_type = unlowered_expr_type (arg1); + tree arg2_type = arg2 ? unlowered_expr_type (arg2) : NULL_TREE; + arg1 = prep_operand (arg1); bool memonly = false; @@ -5846,8 +5849,8 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, case EQ_EXPR: case NE_EXPR: /* These are saved for the sake of maybe_warn_bool_compare. */ - code_orig_arg1 = TREE_CODE (TREE_TYPE (arg1)); - code_orig_arg2 = TREE_CODE (TREE_TYPE (arg2)); + code_orig_arg1 = TREE_CODE (arg1_type); + code_orig_arg2 = TREE_CODE (arg2_type); break; /* =, ->, [], () must be non-static member functions. */ @@ -5870,8 +5873,8 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, if (code == COND_EXPR) /* Use build_conditional_expr instead. */ gcc_unreachable (); - else if (! OVERLOAD_TYPE_P (TREE_TYPE (arg1)) - && (! arg2 || ! OVERLOAD_TYPE_P (TREE_TYPE (arg2)))) + else if (! OVERLOAD_TYPE_P (arg1_type) + && (! arg2 || ! OVERLOAD_TYPE_P (arg2_type))) goto builtin; if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) @@ -5903,11 +5906,11 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, args[2] = NULL_TREE; /* Add class-member operators to the candidate set. */ - if (CLASS_TYPE_P (TREE_TYPE (arg1))) + if (CLASS_TYPE_P (arg1_type)) { tree fns; - fns = lookup_fnfields (TREE_TYPE (arg1), fnname, 1); + fns = lookup_fnfields (arg1_type, fnname, 1); if (fns == error_mark_node) { result = error_mark_node; @@ -5927,7 +5930,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, has an enumeration type, or T2 or reference to cv-qualified-opt T2 for the second argument, if the second argument has an enumeration type. Filter out those that don't match. */ - else if (! arg2 || ! CLASS_TYPE_P (TREE_TYPE (arg2))) + else if (! arg2 || ! CLASS_TYPE_P (arg2_type)) { struct z_candidate **candp, **next; @@ -5947,9 +5950,9 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, if (TYPE_REF_P (parmtype)) parmtype = TREE_TYPE (parmtype); - if (TREE_CODE (TREE_TYPE (args[i])) == ENUMERAL_TYPE + if (TREE_CODE (unlowered_expr_type (args[i])) == ENUMERAL_TYPE && (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (args[i]), parmtype))) + (unlowered_expr_type (args[i]), parmtype))) break; parmlist = TREE_CHAIN (parmlist); @@ -6124,15 +6127,15 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, case LE_EXPR: case EQ_EXPR: case NE_EXPR: - if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE - && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE - && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) - != TYPE_MAIN_VARIANT (TREE_TYPE (arg2))) + if (TREE_CODE (arg1_type) == ENUMERAL_TYPE + && TREE_CODE (arg2_type) == ENUMERAL_TYPE + && (TYPE_MAIN_VARIANT (arg1_type) + != TYPE_MAIN_VARIANT (arg2_type)) && (complain & tf_warning)) { warning (OPT_Wenum_compare, "comparison between %q#T and %q#T", - TREE_TYPE (arg1), TREE_TYPE (arg2)); + arg1_type, arg2_type); } break; default: diff --git a/gcc/testsuite/g++.dg/expr/bitfield13.C b/gcc/testsuite/g++.dg/expr/bitfield13.C new file mode 100644 index 00000000000..3f57d5f0397 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/bitfield13.C @@ -0,0 +1,36 @@ +// PR c++/82165 +// { dg-do compile { target c++11 } } + +struct flags { + enum field { f0, f1, no_field }; + field b0 : 4; + field b1 : 4; + field a0, a1; +}; + +constexpr bool operator!(flags::field f) { + return f == flags::no_field; +} + +#define SA(X) static_assert ((X), #X) + +int main() { + constexpr flags f { flags::f0, flags::f1, flags::f0, flags::f1 }; + + SA( flags::f0 == 0 ); // 0 + SA( flags::f1 == 1 ); // 1 + SA( flags::no_field == 2 ); // 2 + SA( !flags::f0 == 0 ); // (!) 0 + SA( !flags::f1 == 0 ); // (!) 0 + SA( !flags::no_field == 1 ); // (!) 1 + + SA( f.a0 == 0 ); // 0 + SA( f.a1 == 1 ); // 1 + SA( !f.a0 == 0 ); // (!) 0 + SA( !f.a1 == 0 ); // (!) 0 + + SA( f.b0 == 0 ); // 0 + SA( f.b1 == 1 ); // 1 + SA( !f.b0 == 0 ); // expected "(!) 0", but got "1" + SA( !f.b1 == 0 ); // expected "(!) 0", but got "0" +} diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a03a428109b..bed72c90a2e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2019-09-15 Jason Merrill <jason@redhat.com> + PR c++/82165 - enum bitfields and operator overloading. + * call.c (build_new_op_1): Use unlowered_expr_type. + * call.c (build_new_op_1): Don't apply any standard conversions to the operands of a built-in operator. Don't suppress conversions in cp_build_unary_op. -- 2.21.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2019-11-05 23:53 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-09-16 4:33 [C++ PATCH 1/4] Handle location wrappers better in warn_logical_operator Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 4/4] PR c++/30277 - int-width bit-field promotion Jason Merrill 2019-09-21 6:23 ` Jakub Jelinek 2019-09-21 21:51 ` Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 2/4] Fix conversions for built-in operator overloading candidates Jason Merrill 2019-09-17 14:07 ` Andreas Schwab 2019-09-17 14:19 ` Iain Sandoe 2019-09-19 0:19 ` JiangNing OS 2019-09-19 19:43 ` Jason Merrill 2019-09-19 20:11 ` Jason Merrill 2019-09-19 20:28 ` Marek Polacek 2019-11-05 23:53 ` Jason Merrill 2019-09-16 4:33 ` [C++ PATCH 3/4] PR c++/82165 - enum bitfields and operator overloading Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).