aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.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-decl.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-decl.c')
-rw-r--r--gcc/c-decl.c115
1 files changed, 96 insertions, 19 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 885fcdd..588b75c 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -410,8 +410,8 @@ static tree lookup_name_in_scope (tree, struct c_scope *);
static tree c_make_fname_decl (tree, int);
static tree grokdeclarator (const struct c_declarator *,
struct c_declspecs *,
- enum decl_context, bool, tree *, tree *,
- enum deprecated_states);
+ enum decl_context, bool, tree *, tree *, tree *,
+ bool *, enum deprecated_states);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
@@ -3128,10 +3128,15 @@ add_flexible_array_elts_to_size (tree decl, tree init)
}
}
-/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
+/* Decode a "typename", such as "int **", returning a ..._TYPE node.
+ Set *EXPR, if EXPR not NULL, to any expression to be evaluated
+ before the type name, and set *EXPR_CONST_OPERANDS, if
+ EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
+ appear in a constant expression. */
tree
-groktypename (struct c_type_name *type_name)
+groktypename (struct c_type_name *type_name, tree *expr,
+ bool *expr_const_operands)
{
tree type;
tree attrs = type_name->specs->attrs;
@@ -3139,7 +3144,8 @@ groktypename (struct c_type_name *type_name)
type_name->specs->attrs = NULL_TREE;
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
- false, NULL, &attrs, DEPRECATED_NORMAL);
+ false, NULL, &attrs, expr, expr_const_operands,
+ DEPRECATED_NORMAL);
/* Apply attributes. */
decl_attributes (&type, attrs, 0);
@@ -3168,6 +3174,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
{
tree decl;
tree tem;
+ tree expr = NULL_TREE;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
/* An object declared as __attribute__((deprecated)) suppresses
@@ -3176,11 +3183,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized, NULL, &attributes,
+ NORMAL, initialized, NULL, &attributes, &expr, NULL,
deprecated_state);
if (!decl)
return 0;
+ if (expr)
+ add_stmt (expr);
+
if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
warning (OPT_Wmain, "%q+D is usually a function", decl);
@@ -3668,7 +3678,7 @@ grokparm (const struct c_parm *parm)
{
tree attrs = parm->attrs;
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL, &attrs, DEPRECATED_NORMAL);
+ NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, attrs, 0);
@@ -3685,7 +3695,7 @@ push_parm_decl (const struct c_parm *parm)
tree decl;
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
- &attrs, DEPRECATED_NORMAL);
+ &attrs, NULL, NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
@@ -3716,10 +3726,11 @@ mark_forward_parm_decls (void)
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
- literal. */
+ literal. NON_CONST is true if the initializers contain something
+ that cannot occur in a constant expression. */
tree
-build_compound_literal (tree type, tree init)
+build_compound_literal (tree type, tree init, bool non_const)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
@@ -3772,6 +3783,12 @@ build_compound_literal (tree type, tree init)
rest_of_decl_compilation (decl, 1, 0);
}
+ if (non_const)
+ {
+ complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
+ C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
+ }
+
return complit;
}
@@ -3958,6 +3975,11 @@ warn_variable_length_array (const char *name, tree size)
DECL_ATTRS points to the list of attributes that should be added to this
decl. Any nested attributes that belong on the decl itself will be
added to this list.
+ If EXPR is not NULL, any expressions that need to be evaluated as
+ part of evaluating variably modified types will be stored in *EXPR.
+ If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
+ set to indicate whether operands in *EXPR can be used in constant
+ expressions.
DEPRECATED_STATE is a deprecated_states value indicating whether
deprecation warnings should be suppressed.
@@ -3972,7 +3994,8 @@ static tree
grokdeclarator (const struct c_declarator *declarator,
struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width,
- tree *decl_attrs, enum deprecated_states deprecated_state)
+ tree *decl_attrs, tree *expr, bool *expr_const_operands,
+ enum deprecated_states deprecated_state)
{
tree type = declspecs->type;
bool threadp = declspecs->thread_p;
@@ -3994,6 +4017,16 @@ grokdeclarator (const struct c_declarator *declarator,
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
+ tree expr_dummy;
+ bool expr_const_operands_dummy;
+
+ if (expr == NULL)
+ expr = &expr_dummy;
+ if (expr_const_operands == NULL)
+ expr_const_operands = &expr_const_operands_dummy;
+
+ *expr = declspecs->expr;
+ *expr_const_operands = declspecs->expr_const_operands;
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
@@ -4306,6 +4339,11 @@ grokdeclarator (const struct c_declarator *declarator,
if (size)
{
+ bool size_maybe_const = true;
+ bool size_int_const = (TREE_CODE (size) == INTEGER_CST
+ && !TREE_OVERFLOW (size));
+ bool this_size_varies = false;
+
/* Strip NON_LVALUE_EXPRs since we aren't using as an
lvalue. */
STRIP_TYPE_NOPS (size);
@@ -4316,11 +4354,13 @@ grokdeclarator (const struct c_declarator *declarator,
size = integer_one_node;
}
- if (pedantic && integer_zerop (size))
+ size = c_fully_fold (size, false, &size_maybe_const);
+
+ if (pedantic && size_maybe_const && integer_zerop (size))
pedwarn (input_location, OPT_pedantic,
"ISO C forbids zero-size array %qs", name);
- if (TREE_CODE (size) == INTEGER_CST)
+ if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
{
constant_expression_warning (size);
if (tree_int_cst_sgn (size) < 0)
@@ -4328,6 +4368,13 @@ grokdeclarator (const struct c_declarator *declarator,
error ("size of array %qs is negative", name);
size = integer_one_node;
}
+ /* Handle a size folded to an integer constant but
+ not an integer constant expression. */
+ if (!size_int_const)
+ {
+ this_size_varies = size_varies = 1;
+ warn_variable_length_array (orig_name, size);
+ }
}
else if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope)
@@ -4340,11 +4387,11 @@ grokdeclarator (const struct c_declarator *declarator,
/* Make sure the array size remains visibly
nonconstant even if it is (eg) a const variable
with known value. */
- size_varies = 1;
+ this_size_varies = size_varies = 1;
warn_variable_length_array (orig_name, size);
}
- if (integer_zerop (size))
+ if (integer_zerop (size) && !this_size_varies)
{
/* A zero-length array cannot be represented with
an unsigned index type, which is what we'll
@@ -4359,6 +4406,9 @@ grokdeclarator (const struct c_declarator *declarator,
with the +1 that happens when building TYPE_SIZE. */
if (size_varies)
size = variable_size (size);
+ if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
+ size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ integer_zero_node, size);
/* Compute the maximum valid index, that is, size
- 1. Do the calculation in index_type, so that
@@ -4386,6 +4436,15 @@ grokdeclarator (const struct c_declarator *declarator,
itype = build_index_type (itype);
}
+ if (this_size_varies)
+ {
+ if (*expr)
+ *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ *expr, size);
+ else
+ *expr = size;
+ *expr_const_operands &= size_maybe_const;
+ }
}
else if (decl_context == FIELD)
{
@@ -5288,10 +5347,15 @@ struct c_typespec
parser_xref_tag (enum tree_code code, tree name)
{
struct c_typespec ret;
+ tree ref;
+
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
+
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- tree ref = lookup_tag (code, name, 0);
+ ref = lookup_tag (code, name, 0);
/* If this is the right type of tag, return what we found.
(This reference will be shadowed by shadow_tag later if appropriate.)
If this is the wrong type of tag, do not return it. If it was the
@@ -5460,7 +5524,7 @@ grokfield (location_t loc,
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
- width ? &width : NULL, decl_attrs,
+ width ? &width : NULL, decl_attrs, NULL, NULL,
DEPRECATED_NORMAL);
finish_decl (value, NULL_TREE, NULL_TREE);
@@ -6119,7 +6183,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
c_break_label = c_cont_label = size_zero_node;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
- &attributes, DEPRECATED_NORMAL);
+ &attributes, NULL, NULL, DEPRECATED_NORMAL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
@@ -7132,10 +7196,12 @@ build_null_declspecs (void)
{
struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
ret->type = 0;
+ ret->expr = 0;
ret->decl_attr = 0;
ret->attrs = 0;
ret->typespec_word = cts_none;
ret->storage_class = csc_none;
+ ret->expr_const_operands = true;
ret->declspecs_seen_p = false;
ret->type_seen_p = false;
ret->non_sc_seen_p = false;
@@ -7657,7 +7723,18 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
specs->tag_defined_p = true;
if (spec.kind == ctsk_typeof)
- specs->typedef_p = true;
+ {
+ specs->typedef_p = true;
+ if (spec.expr)
+ {
+ if (specs->expr)
+ specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
+ specs->expr, spec.expr);
+ else
+ specs->expr = spec.expr;
+ specs->expr_const_operands &= spec.expr_const_operands;
+ }
+ }
specs->type = type;
}