Don't fold -(constant) or -0.
authorJason Merrill <jason@redhat.com>
Tue, 17 Nov 2015 21:44:08 +0000 (16:44 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 17 Nov 2015 21:44:08 +0000 (16:44 -0500)
* parser.c (cp_parser_unary_expression): Fold -constant here.
* typeck.c (cp_build_unary_op): Not here.

From-SVN: r230506

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/typeck.c

index e41030042864a8ce1e7c6a03a35c327e049a1d4f..536fee0b1baac113945bea1e3b25ce27cdad4dc1 100644 (file)
@@ -1,5 +1,8 @@
 2015-11-17  Jason Merrill  <jason@redhat.com>
 
+       * parser.c (cp_parser_unary_expression): Fold -constant here.
+       * typeck.c (cp_build_unary_op): Not here.
+
        PR bootstrap/68361
        * cvt.c (cp_convert_and_check): Use warning_sentinel to suppress
        -Wparentheses.
index 286c8db54c9507c84d43709c85924f27585b777a..c5f95301e344b032c8c239a1f55336bddd623367 100644 (file)
@@ -7662,6 +7662,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
       /* Consume the operator token.  */
       token = cp_lexer_consume_token (parser->lexer);
+      enum cpp_ttype op_ttype = cp_lexer_peek_token (parser->lexer)->type;
+
       /* Parse the cast-expression.  */
       cast_expression
        = cp_parser_cast_expression (parser,
@@ -7693,8 +7695,25 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
          non_constant_p = unary_operator == PREINCREMENT_EXPR
                           ? NIC_PREINCREMENT : NIC_PREDECREMENT;
          /* Fall through.  */
-       case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
+         /* Immediately fold negation of a constant, unless the constant is 0
+            (since -0 == 0) or it would overflow.  */
+         if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER
+             && CONSTANT_CLASS_P (cast_expression)
+             && !integer_zerop (cast_expression)
+             && !TREE_OVERFLOW (cast_expression))
+           {
+             tree folded = fold_build1 (unary_operator,
+                                        TREE_TYPE (cast_expression),
+                                        cast_expression);
+             if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+               {
+                 expression = folded;
+                 break;
+               }
+           }
+         /* Fall through.  */
+       case UNARY_PLUS_EXPR:
        case TRUTH_NOT_EXPR:
          expression = finish_unary_op_expr (loc, unary_operator,
                                             cast_expression, complain);
index 6541e97cca5efe67483decc94af4d6a8df5ec25a..b7395cf072a418e468776be2d3d31dfa302d155f 100644 (file)
@@ -5768,10 +5768,6 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
            /* Make sure the result is not an lvalue: a unary plus or minus
               expression is always a rvalue.  */
            arg = rvalue (arg);
-
-           if (code == NEGATE_EXPR && CONSTANT_CLASS_P (arg))
-             /* Immediately fold negation of a constant.  */
-             return fold_build1 (code, TREE_TYPE (arg), arg);
          }
       }
       break;