Hi! As discussed in the PR, when __builtin_constant_p is used in the first argument of __builtin_choose_expr, as we require a constant value immediately, we'd better force folding of __builtin_constant_p immediately, as if we don't, and it isn't 1 known immediately, we won't end up with a constant expression. For -O0 we accept code using __builtin_constant_p in __builtin_choose_expr (as we fold it there immediately always), but not for -O1 and above.
The following patch folds it there immediately too. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? BTW, in the PR I've also mentioned what has been reported to the Red Hat bugzilla about __builtin_constant_p in array bounds of static (or extern) arrays in block contexts. Those can't be VLAs, so we want to know the constant bound, but if __builtin_constant_p is used there, we error on it (while at file scope it compiles fine, because if cfun is NULL, we fold __builtin_constant_p immediately). Any suggestions how to fix that? 2013-04-02 Jakub Jelinek <ja...@redhat.com> PR c/19449 * tree.h (force_folding_builtin_constant_p): New decl. * builtins.c (force_folding_builtin_constant_p): New variable. (fold_builtin_constant_p): Fold immediately also if force_folding_builtin_constant_p. * c-parser.c (c_parser_get_builtin_args): Add choose_expr_p argument. If set, or it temporarily for parsing of the first argument into force_folding_builtin_constant_p. (c_parser_postfix_expression): Adjust callers. * gcc.c-torture/execute/pr19449.c: New test. --- gcc/tree.h.jj 2013-03-21 18:34:09.000000000 +0100 +++ gcc/tree.h 2013-03-21 18:34:09.000000000 +0100 @@ -5851,6 +5851,10 @@ fold_build_pointer_plus_hwi_loc (locatio fold_build_pointer_plus_hwi_loc (UNKNOWN_LOCATION, p, o) /* In builtins.c */ + +/* Non-zero if __builtin_constant_p should be folded right away. */ +extern bool force_folding_builtin_constant_p; + extern bool avoid_folding_inline_builtin (tree); extern tree fold_call_expr (location_t, tree, bool); extern tree fold_builtin_fputs (location_t, tree, tree, bool, bool, tree); --- gcc/builtins.c.jj 2013-01-11 09:02:35.000000000 +0100 +++ gcc/builtins.c 2013-03-28 09:26:51.700817655 +0100 @@ -75,6 +75,9 @@ const char * built_in_names[(int) END_BU initialized to NULL_TREE. */ builtin_info_type builtin_info; +/* Non-zero if __builtin_constant_p should be folded right away. */ +bool force_folding_builtin_constant_p; + static const char *c_getstr (tree); static rtx c_readstr (const char *, enum machine_mode); static int target_char_cast (tree, char *); @@ -6974,7 +6977,8 @@ fold_builtin_constant_p (tree arg) || AGGREGATE_TYPE_P (TREE_TYPE (arg)) || POINTER_TYPE_P (TREE_TYPE (arg)) || cfun == 0 - || folding_initializer) + || folding_initializer + || force_folding_builtin_constant_p) return integer_zero_node; return NULL_TREE; --- gcc/c/c-parser.c.jj 2013-03-19 18:42:48.000000000 +0100 +++ gcc/c/c-parser.c 2013-03-28 09:30:17.609546890 +0100 @@ -6114,11 +6114,13 @@ c_parser_alignof_expression (c_parser *p stores the arguments in CEXPR_LIST. */ static bool c_parser_get_builtin_args (c_parser *parser, const char *bname, - vec<c_expr_t, va_gc> **ret_cexpr_list) + vec<c_expr_t, va_gc> **ret_cexpr_list, + bool choose_expr_p) { location_t loc = c_parser_peek_token (parser)->location; vec<c_expr_t, va_gc> *cexpr_list; c_expr_t expr; + bool saved_force_folding_builtin_constant_p; *ret_cexpr_list = NULL; if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) @@ -6135,7 +6137,12 @@ c_parser_get_builtin_args (c_parser *par return true; } + saved_force_folding_builtin_constant_p + = force_folding_builtin_constant_p; + force_folding_builtin_constant_p |= choose_expr_p; expr = c_parser_expr_no_commas (parser, NULL); + force_folding_builtin_constant_p + = saved_force_folding_builtin_constant_p; vec_alloc (cexpr_list, 1); C_EXPR_APPEND (cexpr_list, expr); while (c_parser_next_token_is (parser, CPP_COMMA)) @@ -6509,7 +6516,7 @@ c_parser_postfix_expression (c_parser *p c_parser_consume_token (parser); if (!c_parser_get_builtin_args (parser, "__builtin_choose_expr", - &cexpr_list)) + &cexpr_list, true)) { expr.value = error_mark_node; break; @@ -6591,7 +6598,7 @@ c_parser_postfix_expression (c_parser *p c_parser_consume_token (parser); if (!c_parser_get_builtin_args (parser, "__builtin_complex", - &cexpr_list)) + &cexpr_list, false)) { expr.value = error_mark_node; break; @@ -6653,7 +6660,7 @@ c_parser_postfix_expression (c_parser *p c_parser_consume_token (parser); if (!c_parser_get_builtin_args (parser, "__builtin_shuffle", - &cexpr_list)) + &cexpr_list, false)) { expr.value = error_mark_node; break; --- gcc/testsuite/gcc.c-torture/execute/pr19449.c.jj 2013-04-02 10:01:56.042354508 +0200 +++ gcc/testsuite/gcc.c-torture/execute/pr19449.c 2013-04-02 10:01:38.000000000 +0200 @@ -0,0 +1,20 @@ +/* PR c/19449 */ + +extern void abort (void); + +int y; +int z = __builtin_choose_expr (!__builtin_constant_p (y), 3, 4); + +int +foo (int x) +{ + return __builtin_choose_expr (!__builtin_constant_p (x), 3, y++); +} + +int +main () +{ + if (y || z != 3 || foo (4) != 3) + abort (); + return 0; +} Jakub