Message ID | Y5RSeiXwNVUa7+dw@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Ensure !!var is not an lvalue [PR107065] | expand |
On 12/10/22 04:33, Jakub Jelinek wrote: > Hi! > > The TRUTH_NOT_EXPR case in cp_build_unary_op is one of the spots where > we somewhat fold immediately using invert_truthvalue_loc. > I've tried using > return build1_loc (location, TRUTH_NOT_EXPR, boolean_type_node, arg); > in there instead, but unfortunately that regressed > Wlogical-not-parentheses-*.c pr49706.c pr62199.c pr65120.c sequence-pt-1.C > tests, so at least for backporting that doesn't seem to be a way to go. > > So, this patch instead wraps it into NON_LVALUE_EXPR if needed (which also > need a tweak for some tests in the pr47906.c test, but nothing major), > with the intent to make it backportable, and later I'll try to do further > steps to avoid folding here prematurely. Most of the problems with > build1 TRUTH_NOT_EXPR are that it doesn't even invert comparisons as most > common case and lots of warning code isn't able to deal with ! around > comparisons; so perhaps one way to do this would be fold by hand only > invertable comparisons and for the rest create TRUTH_NOT_EXPR. > > Anyway, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk > (for now) and for release branches (after a while on the trunk)? OK. > 2022-12-10 Jakub Jelinek <jakub@redhat.com> > > PR c++/107065 > gcc/cp/ > * typeck.cc (cp_build_unary_op) <case TRUTH_NOT_EXPR>: If > invert_truthvalue_loc returns obvalue_p, wrap it into NON_LVALUE_EXPR. > * parser.cc (cp_parser_binary_expression): Don't call > warn_logical_not_parentheses if current.lhs is a NON_LVALUE_EXPR > of a decl with boolean type. > gcc/testsuite/ > * g++.dg/cpp0x/pr107065.C: New test. > > --- gcc/cp/typeck.cc.jj 2022-11-30 10:29:42.024701797 +0100 > +++ gcc/cp/typeck.cc 2022-12-09 17:47:54.132856233 +0100 > @@ -7396,9 +7396,13 @@ cp_build_unary_op (enum tree_code code, > build_zero_cst (TREE_TYPE (arg)), complain); > arg = perform_implicit_conversion (boolean_type_node, arg, > complain); > - val = invert_truthvalue_loc (location, arg); > if (arg != error_mark_node) > - return val; > + { > + val = invert_truthvalue_loc (location, arg); > + if (obvalue_p (val)) > + val = non_lvalue_loc (location, val); > + return val; > + } > errstring = _("in argument to unary !"); > break; > > --- gcc/cp/parser.cc.jj 2022-12-09 11:02:35.871444993 +0100 > +++ gcc/cp/parser.cc 2022-12-09 19:14:26.698847734 +0100 > @@ -10224,7 +10224,10 @@ cp_parser_binary_expression (cp_parser* > || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0))) > != BOOLEAN_TYPE)))) > /* Avoid warning for !!b == y where b is boolean. */ > - && (!DECL_P (tree_strip_any_location_wrapper (current.lhs)) > + && (!(DECL_P (tree_strip_any_location_wrapper (current.lhs)) > + || (TREE_CODE (current.lhs) == NON_LVALUE_EXPR > + && DECL_P (tree_strip_any_location_wrapper > + (TREE_OPERAND (current.lhs, 0))))) > || TREE_TYPE (current.lhs) == NULL_TREE > || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE)) > warn_logical_not_parentheses (current.loc, current.tree_type, > --- gcc/testsuite/g++.dg/cpp0x/pr107065.C.jj 2022-12-09 16:22:59.686548071 +0100 > +++ gcc/testsuite/g++.dg/cpp0x/pr107065.C 2022-12-09 16:22:59.686548071 +0100 > @@ -0,0 +1,14 @@ > +// PR c++/107065 > +// { dg-do compile { target c++11 } } > + > +template<class, class> struct is_same { static constexpr bool value = false; }; > +template<class T> struct is_same<T, T> { static constexpr bool value = true; }; > + > +int > +main () > +{ > + bool b = true; > + static_assert (is_same<decltype (!(!b)), bool>::value, ""); > + auto bb = (!(!b)); > + static_assert (is_same<decltype (bb), bool>::value, ""); > +} > > Jakub >
--- gcc/cp/typeck.cc.jj 2022-11-30 10:29:42.024701797 +0100 +++ gcc/cp/typeck.cc 2022-12-09 17:47:54.132856233 +0100 @@ -7396,9 +7396,13 @@ cp_build_unary_op (enum tree_code code, build_zero_cst (TREE_TYPE (arg)), complain); arg = perform_implicit_conversion (boolean_type_node, arg, complain); - val = invert_truthvalue_loc (location, arg); if (arg != error_mark_node) - return val; + { + val = invert_truthvalue_loc (location, arg); + if (obvalue_p (val)) + val = non_lvalue_loc (location, val); + return val; + } errstring = _("in argument to unary !"); break; --- gcc/cp/parser.cc.jj 2022-12-09 11:02:35.871444993 +0100 +++ gcc/cp/parser.cc 2022-12-09 19:14:26.698847734 +0100 @@ -10224,7 +10224,10 @@ cp_parser_binary_expression (cp_parser* || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0))) != BOOLEAN_TYPE)))) /* Avoid warning for !!b == y where b is boolean. */ - && (!DECL_P (tree_strip_any_location_wrapper (current.lhs)) + && (!(DECL_P (tree_strip_any_location_wrapper (current.lhs)) + || (TREE_CODE (current.lhs) == NON_LVALUE_EXPR + && DECL_P (tree_strip_any_location_wrapper + (TREE_OPERAND (current.lhs, 0))))) || TREE_TYPE (current.lhs) == NULL_TREE || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE)) warn_logical_not_parentheses (current.loc, current.tree_type, --- gcc/testsuite/g++.dg/cpp0x/pr107065.C.jj 2022-12-09 16:22:59.686548071 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr107065.C 2022-12-09 16:22:59.686548071 +0100 @@ -0,0 +1,14 @@ +// PR c++/107065 +// { dg-do compile { target c++11 } } + +template<class, class> struct is_same { static constexpr bool value = false; }; +template<class T> struct is_same<T, T> { static constexpr bool value = true; }; + +int +main () +{ + bool b = true; + static_assert (is_same<decltype (!(!b)), bool>::value, ""); + auto bb = (!(!b)); + static_assert (is_same<decltype (bb), bool>::value, ""); +}