aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-parser.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2009-03-29 19:13:43 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2009-03-29 19:13:43 +0100
commit928c19bbb001967c7ab83a9f856c740680b6661f (patch)
treea06c7550ad4d8d100141b10b1c0d61bf7548b888 /gcc/c-parser.c
parent5babbcc0fceb0aa66547feb61124ff548929cbfc (diff)
downloadgcc-928c19bbb001967c7ab83a9f856c740680b6661f.zip
gcc-928c19bbb001967c7ab83a9f856c740680b6661f.tar.gz
gcc-928c19bbb001967c7ab83a9f856c740680b6661f.tar.bz2
re PR c/456 (constant expressions constraints (gcc.dg/c90-const-expr-1))
PR c/456 PR c/5675 PR c/19976 PR c/29116 PR c/31871 PR c/35198 fixincludes: * inclhack.def (glibc_tgmath): New fix. * fixincl.x: Regenerate. * tests/base/tgmath.h: New. gcc: * builtins.c (fold_builtin_sincos): Build COMPOUND_EXPR in void_type_node. (fold_call_expr): Return a NOP_EXPR from folding rather than the contained expression. * c-common.c (c_fully_fold, c_fully_fold_internal, c_save_expr): New. (c_common_truthvalue_conversion): Use c_save_expr. Do not fold conditional expressions for C. (decl_constant_value_for_optimization): Move from decl_constant_value_for_broken_optimization in c-typeck.c. Check whether optimizing and that the expression is a VAR_DECL not of array type instead of doing such checks in the caller. Do not check pedantic. Call gcc_unreachable for C++. * c-common.def (C_MAYBE_CONST_EXPR): New. * c-common.h (c_fully_fold, c_save_expr, decl_constant_value_for_optimization): New prototypes. (C_MAYBE_CONST_EXPR_PRE, C_MAYBE_CONST_EXPR_EXPR, C_MAYBE_CONST_EXPR_INT_OPERANDS, C_MAYBE_CONST_EXPR_NON_CONST, EXPR_INT_CONST_OPERANDS): Define. * c-convert.c (convert): Strip nops from expression. * c-decl.c (groktypename): Take extra parameters expr and expr_const_operands. Update call to grokdeclarator. (start_decl): Update call to grokdeclarator. Add statement for expressions used in type of decl. (grokparm): Update call to grokdeclarator. (push_parm_decl): Update call to grokdeclarator. (build_compound_literal): Add parameter non_const and build a C_MAYBE_COSNT_EXPR if applicable. (grokdeclarator): Take extra parameters expr and expr_const_operands. Track expressions used in declaration specifiers and declarators. Fold array sizes and track whether they are constant expressions and whether they are integer constant expressions. (parser_xref_tag): Set expr and expr_const_operands fields in return value. (grokfield): Update call to grokdeclarator. (start_function): Update call to grokdeclarator. (build_null_declspecs): Set expr and expr_const_operands fields in return value. (declspecs_add_type): Handle expressions in typeof specifiers. * c-parser.c (c_parser_declspecs): Set expr and expr_const_operands fields for declaration specifiers. (c_parser_enum_specifier): Likewise. (c_parser_struct_or_union_specifier): Likewise. (c_parser_typeof_specifier): Likewise. Update call to groktypename. Fold expression as needed. Return expressions with type instead of adding statements. (c_parser_attributes): Update calls to c_parser_expr_list. (c_parser_statement_after_labels): Fold expression before passing to objc_build_throw_stmt. (c_parser_condition): Fold expression. (c_parser_asm_operands): Fold expression. (c_parser_conditional_expression): Use c_save_expr. Update call to build_conditional_expr. (c_parser_alignof_expression): Update call to groktypename. (c_parser_postfix_expression): Preserve C_MAYBE_CONST_EXPR as original_code. Fold expression argument of va_arg. Create C_MAYBE_CONST_EXPR to preserve side effects of expressions in type argument to va_arg. Update calls to groktypename. Fold array index for offsetof. Verify that first argument to __builtin_choose_expr has integer type. (c_parser_postfix_expression_after_paren_type): Update calls to groktypename and build_compound_literal. Handle expressions with side effects in type name. (c_parser_postfix_expression_after_primary): Update call to c_parser_expr_list. Set original_code for calls to __builtin_constant_p. (c_parser_expr_list): Take extra parameter fold_p. Fold expressions if requested. (c_parser_objc_type_name): Update call to groktypename. (c_parser_objc_synchronized_statement): Fold expression. (c_parser_objc_receiver): Fold expression. (c_parser_objc_keywordexpr): Update call to c_parser_expr_list. (c_parser_omp_clause_num_threads, c_parser_omp_clause_schedule, c_parser_omp_atomic, c_parser_omp_for_loop): Fold expressions. * c-tree.h (CONSTRUCTOR_NON_CONST): Define. (struct c_typespec): Add elements expr and expr_const_operands. (struct c_declspecs): Add elements expr and expr_const_operands. (groktypename, build_conditional_expr, build_compound_literal): Update prototypes. (in_late_binary_op): Declare. * c-typeck.c (note_integer_operands): New function. (in_late_binary_op): New variable. (decl_constant_value_for_broken_optimization): Move to c-common.c and rename to decl_constant_value_for_optimization. (default_function_array_conversion): Do not strip nops. (default_conversion): Do not call decl_constant_value_for_broken_optimization. (build_array_ref): Do not fold result. (c_expr_sizeof_expr): Fold operand. Use C_MAYBE_CONST_EXPR for result when operand is a VLA. (c_expr_sizeof_type): Update call to groktypename. Handle expressions included in type name. Use C_MAYBE_CONST_EXPR for result when operand names a VLA type. (build_function_call): Update call to build_compound_literal. Only fold result for calls to __builtin_* functions. Strip NOP_EXPR from INTEGER_CST returned from such functions. Fold the function designator. (convert_arguments): Fold arguments. Update call to convert_for_assignment. (build_unary_op): Handle increment and decrement of C_MAYBE_CONST_EXPR. Move lvalue checks for increment and decrement earlier. Fold operand of increment and decrement. Handle address of C_MAYBE_CONST_EXPR. Only fold expression being built for integer operand. Wrap returns that are INTEGER_CSTs without being integer constant expressions or that have integer constant operands without being INTEGER_CSTs. (lvalue_p): Handle C_MAYBE_CONST_EXPR. (build_conditional_expr): Add operand ifexp_bcp. Track whether result is an integer constant expression or can be used in unevaluated parts of one and avoid folding and wrap as appropriate. Fold operands before possibly doing -Wsign-compare warnings. (build_compound_expr): Wrap result for C99 if operands can be used in integer constant expressions. (build_c_cast): Update call to digest_init. Do not ignore overflow from casting floating-point constants to integers. Wrap results that could be confused with integer constant expressions, null pointer constants or floating-point constants. (c_cast_expr): Update call to groktypename. Handle expressions included in type name. (build_modify_expr): Handle modifying a C_MAYBE_CONST_EXPR. Fold lhs inside possible SAVE_EXPR. Fold RHS before assignment. Update calls to convert_for_assignment. (convert_for_assignment): Take new parameter null_pointer_constant. Do not strip nops or call decl_constant_value_for_broken_optimization. Set in_late_binary_op for conversions to boolean. (store_init_value): Update call to digest_init. (digest_init): Take new parameter null_pointer_constant. Do not call decl_constant_value_for_broken_optimization. pedwarn for initializers not constant expressions. Update calls to convert_for_assignment. (constructor_nonconst): New. (struct constructor_stack): Add nonconst element. (really_start_incremental_init, push_init_level, pop_init_level): Handle constructor_nonconst and nonconst element. (set_init_index): Call constant_expression_warning for array designators. (output_init_element): Fold value. Set constructor_nonconst as applicable. pedwarn for initializers not constant expressions. Update call to digest_init. Call constant_expression_warning where constant initializers are required. (process_init_element): Use c_save_expr. (c_finish_goto_ptr): Fold expression. (c_finish_return): Fold return value. Update call to convert_for_assignment. (c_start_case): Fold switch expression. (c_process_expr_stmt): Fold expression. (c_finish_stmt_expr): Create C_MAYBE_CONST_EXPR as needed to ensure statement expression is not evaluated in constant expression. (build_binary_op): Track whether results are integer constant expressions or may occur in such, disable folding and wrap results as applicable. Fold operands for -Wsign-compare warnings unless in_late_binary_op. (c_objc_common_truthvalue_conversion): Handle results folded to integer constants that are not integer constant expressions. * doc/extend.texi: Document when typeof operands are evaluated, that condition of __builtin_choose_expr is an integer constant expression, and more about use of __builtin_constant_p in initializers. gcc/objc: * objc-act.c (objc_finish_try_stmt): Set in_late_binary_op. gcc/testsuite: * gcc.c-torture/compile/20081108-1.c, gcc.c-torture/compile/20081108-2.c, gcc.c-torture/compile/20081108-3.c, gcc.dg/bconstp-2.c, gcc.dg/bconstp-3.c, gcc.dg/bconstp-4.c, gcc.dg/c90-const-expr-6.c, gcc.dg/c90-const-expr-7.c, gcc.dg/c90-const-expr-8.c, gcc.dg/c90-const-expr-9.c, gcc.dg/c90-const-expr-10.c, gcc.dg/c90-const-expr-11.c, gcc.dg/c99-const-expr-6.c, gcc.dg/c99-const-expr-7.c, gcc.dg/c99-const-expr-8.c, gcc.dg/c99-const-expr-9.c, gcc.dg/c99-const-expr-10.c, gcc.dg/c99-const-expr-11.c, gcc.dg/c99-const-expr-12.c, gcc.dg/c99-const-expr-13.c, gcc.dg/compare10.c, gcc.dg/gnu89-const-expr-1.c, gcc.dg/gnu89-const-expr-2.c, gcc.dg/gnu99-const-expr-1.c, gcc.dg/gnu99-const-expr-2.c, gcc.dg/gnu99-const-expr-3.c, gcc.dg/vla-12.c, gcc.dg/vla-13.c, gcc.dg/vla-14.c, gcc.dg/vla-15.c, gcc.dg/vla-16.c: New tests. * gcc.dg/c90-const-expr-1.c, gcc.dg/c90-const-expr-2.c, gcc.dg/c90-const-expr-3.c, gcc.dg/c99-const-expr-2.c, gcc.dg/c99-const-expr-3.c, gcc.dg/c99-static-1.c: Remove XFAILs. * gcc.dg/c90-const-expr-2.c: Use ZERO in place of 0 in another case. * gcc.dg/overflow-warn-1.c, gcc.dg/overflow-warn-2.c, gcc.dg/overflow-warn-3.c, gcc.dg/overflow-warn-4.c: Remove XFAILs. Update expected messages. * gcc.dg/pr14649-1.c, gcc.dg/pr19984.c, gcc.dg/pr25682.c: Update expected messages. * gcc.dg/real-const-1.c: Replace with test from original PR. * gcc.dg/vect/pr32230.c: Use intermediate cast to __PTRDIFF_TYPE__ when casting from non-constant integer to pointer. From-SVN: r145254
Diffstat (limited to 'gcc/c-parser.c')
-rw-r--r--gcc/c-parser.c149
1 files changed, 107 insertions, 42 deletions
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index f910128..4d1b4d5 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -915,7 +915,7 @@ static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
struct c_expr);
static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
-static tree c_parser_expr_list (c_parser *, bool);
+static tree c_parser_expr_list (c_parser *, bool, bool);
static void c_parser_omp_construct (c_parser *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
@@ -1455,6 +1455,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
/* For a typedef name, record the meaning, not the name.
In case of 'foo foo, bar;'. */
t.spec = lookup_name (value);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
}
else
{
@@ -1464,6 +1466,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
if (c_parser_next_token_is (parser, CPP_LESS))
proto = c_parser_objc_protocol_refs (parser);
t.spec = objc_get_protocol_qualified_type (value, proto);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
}
declspecs_add_type (specs, t);
continue;
@@ -1479,6 +1483,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
proto = c_parser_objc_protocol_refs (parser);
t.kind = ctsk_objc;
t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
declspecs_add_type (specs, t);
continue;
}
@@ -1526,6 +1532,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
parser->objc_need_raw_identifier = true;
t.kind = ctsk_resword;
t.spec = c_parser_peek_token (parser)->value;
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
declspecs_add_type (specs, t);
c_parser_consume_token (parser);
break;
@@ -1687,6 +1695,8 @@ c_parser_enum_specifier (c_parser *parser)
ret.spec = finish_enum (type, nreverse (values),
chainon (attrs, postfix_attrs));
ret.kind = ctsk_tagdef;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
else if (!ident)
@@ -1694,6 +1704,8 @@ c_parser_enum_specifier (c_parser *parser)
c_parser_error (parser, "expected %<{%>");
ret.spec = error_mark_node;
ret.kind = ctsk_tagref;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
ret = parser_xref_tag (ENUMERAL_TYPE, ident);
@@ -1870,6 +1882,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
ret.spec = finish_struct (type, nreverse (contents),
chainon (attrs, postfix_attrs));
ret.kind = ctsk_tagdef;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
else if (!ident)
@@ -1877,6 +1891,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
c_parser_error (parser, "expected %<{%>");
ret.spec = error_mark_node;
ret.kind = ctsk_tagref;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
ret = parser_xref_tag (code, ident);
@@ -2053,6 +2069,8 @@ c_parser_typeof_specifier (c_parser *parser)
struct c_typespec ret;
ret.kind = ctsk_typeof;
ret.spec = error_mark_node;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
c_parser_consume_token (parser);
skip_evaluation++;
@@ -2070,7 +2088,7 @@ c_parser_typeof_specifier (c_parser *parser)
in_typeof--;
if (type != NULL)
{
- ret.spec = groktypename (type);
+ ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
}
}
@@ -2086,22 +2104,10 @@ c_parser_typeof_specifier (c_parser *parser)
error_at (here, "%<typeof%> applied to a bit-field");
ret.spec = TREE_TYPE (expr.value);
was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
- /* This should be returned with the type so that when the type
- is evaluated, this can be evaluated. For now, we avoid
- evaluation when the context might. */
- if (!skip_evaluation && was_vm)
- {
- tree e = expr.value;
-
- /* If the expression is not of a type to which we cannot assign a line
- number, wrap the thing in a no-op NOP_EXPR. */
- if (DECL_P (e) || CONSTANT_CLASS_P (e))
- e = build1 (NOP_EXPR, void_type_node, e);
-
- protected_set_expr_location (e, here);
-
- add_stmt (e);
- }
+ /* This is returned with the type so that when the type is
+ evaluated, this can be evaluated. */
+ if (was_vm)
+ ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
pop_maybe_used (was_vm);
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -2858,7 +2864,8 @@ c_parser_attributes (c_parser *parser)
{
c_parser_consume_token (parser);
attr_args = tree_cons (NULL_TREE, arg1,
- c_parser_expr_list (parser, false));
+ c_parser_expr_list (parser, false,
+ true));
}
}
else
@@ -2866,7 +2873,7 @@ c_parser_attributes (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
attr_args = NULL_TREE;
else
- attr_args = c_parser_expr_list (parser, false);
+ attr_args = c_parser_expr_list (parser, false, true);
}
attr = build_tree_list (attr_name, attr_args);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
@@ -3748,8 +3755,9 @@ c_parser_statement_after_labels (c_parser *parser)
}
else
{
- stmt
- = objc_build_throw_stmt (c_parser_expression (parser).value);
+ tree expr = c_parser_expression (parser).value;
+ expr = c_fully_fold (expr, false, NULL);
+ stmt = objc_build_throw_stmt (expr);
goto expect_semicolon;
}
break;
@@ -3810,8 +3818,9 @@ c_parser_condition (c_parser *parser)
location_t loc;
tree cond;
loc = c_parser_peek_token (parser)->location;
- cond = c_objc_common_truthvalue_conversion
- (loc, c_parser_expression_conv (parser).value);
+ cond = c_parser_expression_conv (parser).value;
+ cond = c_objc_common_truthvalue_conversion (loc, cond);
+ cond = c_fully_fold (cond, false, NULL);
protected_set_expr_location (cond, loc);
if (warn_sequence_point)
verify_sequence_points (cond);
@@ -4304,6 +4313,7 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
expr = c_parser_expression (parser);
if (convert_p)
expr = default_function_array_conversion (expr);
+ expr.value = c_fully_fold (expr.value, false, NULL);
parser->lex_untranslated_string = true;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
@@ -4458,7 +4468,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
"ISO C forbids omitting the middle term of a ?: expression");
/* Make sure first operand is calculated only once. */
- exp1.value = save_expr (default_conversion (cond.value));
+ exp1.value = c_save_expr (default_conversion (cond.value));
cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
skip_evaluation += cond.value == truthvalue_true_node;
}
@@ -4482,7 +4492,9 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
exp2 = c_parser_conditional_expression (parser, NULL);
exp2 = default_function_array_conversion (exp2);
skip_evaluation -= cond.value == truthvalue_true_node;
- ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
+ ret.value = build_conditional_expr (cond.value,
+ cond.original_code == C_MAYBE_CONST_EXPR,
+ exp1.value, exp2.value);
ret.original_code = ERROR_MARK;
return ret;
}
@@ -5012,7 +5024,7 @@ c_parser_alignof_expression (c_parser *parser)
/* alignof ( type-name ). */
skip_evaluation--;
in_alignof--;
- ret.value = c_alignof (groktypename (type_name));
+ ret.value = c_alignof (groktypename (type_name, NULL, NULL));
ret.original_code = ERROR_MARK;
return ret;
}
@@ -5200,7 +5212,8 @@ c_parser_postfix_expression (c_parser *parser)
expr = c_parser_expression (parser);
if (TREE_CODE (expr.value) == MODIFY_EXPR)
TREE_NO_WARNING (expr.value) = 1;
- expr.original_code = ERROR_MARK;
+ if (expr.original_code != C_MAYBE_CONST_EXPR)
+ expr.original_code = ERROR_MARK;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
}
@@ -5226,6 +5239,7 @@ c_parser_postfix_expression (c_parser *parser)
break;
}
e1 = c_parser_expr_no_commas (parser, NULL);
+ e1.value = c_fully_fold (e1.value, false, NULL);
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -5243,7 +5257,17 @@ c_parser_postfix_expression (c_parser *parser)
}
else
{
- expr.value = build_va_arg (e1.value, groktypename (t1));
+ tree type_expr = NULL_TREE;
+ expr.value = build_va_arg (e1.value, groktypename (t1,
+ &type_expr,
+ NULL));
+ if (type_expr)
+ {
+ expr.value = build2 (C_MAYBE_CONST_EXPR,
+ TREE_TYPE (expr.value), type_expr,
+ expr.value);
+ C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
+ }
expr.original_code = ERROR_MARK;
}
break;
@@ -5270,7 +5294,7 @@ c_parser_postfix_expression (c_parser *parser)
break;
}
{
- tree type = groktypename (t1);
+ tree type = groktypename (t1, NULL, NULL);
tree offsetof_ref;
if (type == error_mark_node)
offsetof_ref = error_mark_node;
@@ -5319,6 +5343,7 @@ c_parser_postfix_expression (c_parser *parser)
loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
idx = c_parser_expression (parser).value;
+ idx = c_fully_fold (idx, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
"expected %<]%>");
offsetof_ref = build_array_ref (offsetof_ref, idx, loc);
@@ -5365,10 +5390,12 @@ c_parser_postfix_expression (c_parser *parser)
tree c;
c = fold (e1.value);
- if (TREE_CODE (c) != INTEGER_CST)
+ if (TREE_CODE (c) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
error_at (loc,
"first argument to %<__builtin_choose_expr%> not"
" a constant");
+ constant_expression_warning (c);
expr = integer_zerop (c) ? e3 : e2;
}
break;
@@ -5406,8 +5433,8 @@ c_parser_postfix_expression (c_parser *parser)
{
tree e1, e2;
- e1 = TYPE_MAIN_VARIANT (groktypename (t1));
- e2 = TYPE_MAIN_VARIANT (groktypename (t2));
+ e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL));
+ e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL));
expr.value = comptypes (e1, e2)
? build_int_cst (NULL_TREE, 1)
@@ -5479,7 +5506,7 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
{
- tree type = groktypename (t1);
+ tree type = groktypename (t1, NULL, NULL);
expr.value = objc_build_encode_expr (type);
expr.original_code = ERROR_MARK;
}
@@ -5529,10 +5556,13 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
{
tree type;
struct c_expr init;
+ bool non_const;
struct c_expr expr;
location_t start_loc;
+ tree type_expr = NULL_TREE;
+ bool type_expr_const = true;
start_init (NULL_TREE, NULL, 0);
- type = groktypename (type_name);
+ type = groktypename (type_name, &type_expr, &type_expr_const);
start_loc = c_parser_peek_token (parser)->location;
if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
{
@@ -5545,8 +5575,26 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
if (!flag_isoc99)
pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
- expr.value = build_compound_literal (type, init.value);
+ non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
+ ? CONSTRUCTOR_NON_CONST (init.value)
+ : init.original_code == C_MAYBE_CONST_EXPR);
+ non_const |= !type_expr_const;
+ expr.value = build_compound_literal (type, init.value, non_const);
expr.original_code = ERROR_MARK;
+ if (type_expr)
+ {
+ if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
+ {
+ gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
+ C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
+ }
+ else
+ {
+ gcc_assert (!non_const);
+ expr.value = build2 (C_MAYBE_CONST_EXPR, type,
+ type_expr, expr.value);
+ }
+ }
return c_parser_postfix_expression_after_primary (parser, expr);
}
@@ -5557,6 +5605,7 @@ static struct c_expr
c_parser_postfix_expression_after_primary (c_parser *parser,
struct c_expr expr)
{
+ struct c_expr orig_expr;
tree ident, idx, exprlist;
location_t loc = c_parser_peek_token (parser)->location;
while (true)
@@ -5579,11 +5628,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
exprlist = NULL_TREE;
else
- exprlist = c_parser_expr_list (parser, true);
+ exprlist = c_parser_expr_list (parser, true, false);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
+ orig_expr = expr;
expr.value = build_function_call (expr.value, exprlist);
expr.original_code = ERROR_MARK;
+ if (TREE_CODE (expr.value) == INTEGER_CST
+ && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+ expr.original_code = C_MAYBE_CONST_EXPR;
break;
case CPP_DOT:
/* Structure element reference. */
@@ -5681,7 +5736,7 @@ c_parser_expression_conv (c_parser *parser)
}
/* Parse a non-empty list of expressions. If CONVERT_P, convert
- functions and arrays to pointers.
+ functions and arrays to pointers. If FOLD_P, fold the expressions.
nonempty-expr-list:
assignment-expression
@@ -5689,13 +5744,15 @@ c_parser_expression_conv (c_parser *parser)
*/
static tree
-c_parser_expr_list (c_parser *parser, bool convert_p)
+c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p)
{
struct c_expr expr;
tree ret, cur;
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
expr = default_function_array_conversion (expr);
+ if (fold_p)
+ expr.value = c_fully_fold (expr.value, false, NULL);
ret = cur = build_tree_list (NULL_TREE, expr.value);
while (c_parser_next_token_is (parser, CPP_COMMA))
{
@@ -5703,6 +5760,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p)
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
expr = default_function_array_conversion (expr);
+ if (fold_p)
+ expr.value = c_fully_fold (expr.value, false, NULL);
cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
}
return ret;
@@ -6288,7 +6347,7 @@ c_parser_objc_type_name (c_parser *parser)
if (c_parser_next_token_starts_typename (parser))
type_name = c_parser_type_name (parser);
if (type_name)
- type = groktypename (type_name);
+ type = groktypename (type_name, NULL, NULL);
return build_tree_list (quals, type);
}
@@ -6394,6 +6453,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr = c_parser_expression (parser).value;
+ expr = c_fully_fold (expr, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
else
@@ -6529,7 +6589,7 @@ c_parser_objc_receiver (c_parser *parser)
c_parser_consume_token (parser);
return objc_get_class_reference (id);
}
- return c_parser_expression (parser).value;
+ return c_fully_fold (c_parser_expression (parser).value, false, NULL);
}
/* Parse objc-message-args.
@@ -6577,7 +6637,7 @@ c_parser_objc_message_args (c_parser *parser)
static tree
c_parser_objc_keywordexpr (c_parser *parser)
{
- tree list = c_parser_expr_list (parser, true);
+ tree list = c_parser_expr_list (parser, true, true);
if (TREE_CHAIN (list) == NULL_TREE)
{
/* Just return the expression, remove a level of
@@ -7053,6 +7113,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
{
location_t expr_loc = c_parser_peek_token (parser)->location;
tree c, t = c_parser_expression (parser).value;
+ t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -7231,6 +7292,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
here = c_parser_peek_token (parser)->location;
t = c_parser_expr_no_commas (parser, NULL).value;
+ t = c_fully_fold (t, false, NULL);
if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
error_at (here, "schedule %<runtime%> does not take "
@@ -7430,6 +7492,7 @@ c_parser_omp_atomic (c_parser *parser)
c_parser_skip_to_pragma_eol (parser);
lhs = c_parser_unary_expression (parser).value;
+ lhs = c_fully_fold (lhs, false, NULL);
switch (TREE_CODE (lhs))
{
case ERROR_MARK:
@@ -7491,6 +7554,7 @@ c_parser_omp_atomic (c_parser *parser)
rhs_expr = c_parser_expression (parser);
rhs_expr = default_function_array_conversion (rhs_expr);
rhs = rhs_expr.value;
+ rhs = c_fully_fold (rhs, false, NULL);
break;
}
stmt = c_finish_omp_atomic (code, lhs, rhs);
@@ -7654,6 +7718,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
cond = cond_expr.value;
cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+ cond = c_fully_fold (cond, false, NULL);
switch (cond_expr.original_code)
{
case GT_EXPR: