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.
/* 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,
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);
/* 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;