diff options
author | Mike Stump <mrs@apple.com> | 2006-05-18 18:22:12 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 2006-05-18 18:22:12 +0000 |
commit | 52ffd86eb62d0320ccf64138e5d7d37ab7a6f7c5 (patch) | |
tree | 3393aa88e335ad0c151ee642c9e17e8807ed52e9 /gcc/c-decl.c | |
parent | 4f9533c7722fa07511a94d005227961f4a4dec23 (diff) | |
download | gcc-52ffd86eb62d0320ccf64138e5d7d37ab7a6f7c5.zip gcc-52ffd86eb62d0320ccf64138e5d7d37ab7a6f7c5.tar.gz gcc-52ffd86eb62d0320ccf64138e5d7d37ab7a6f7c5.tar.bz2 |
Fix up vla, vm and [*] sematics.
PR c/18740
PR c/7948
PR c/25802
* c-tree.h (struct c_arg_info): Add had_vla_unspec.
(c_vla_unspec_p): Add.
(c_vla_type_p): Add.
* c-decl.c (struct c_scope): Add had_vla_unspec.
(build_array_declarator): Add support for [*].
(grokdeclarator): Likewise.
(grokparms): Likewise.
(get_parm_info): Likewise.
* c-objc-common.c (c_vla_unspec_p): Likewise.
* c-objc-common.h (LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P): Likewise.
* c-parser.c (c_parser_typeof_specifier): Evaluate arguments to
typeof when argument is a variably modified type not inside sizeof or alignof.
(c_parser_direct_declarator_inner): Propagate errors.
(c_parser_sizeof_expression): Add support for [*].
* c-typeck.c (c_vla_type_p): Add.
(composite_type): Add support for vla compositing.
(comptypes_internal): Add support for vla compatibility.
(c_expr_sizeof_expr): Evaluate vla arguments.
* tree.c (variably_modified_type_p): Update comment for [*].
testsuite:
* gcc.dg/c90-arraydecl-1.c: Update for vla, vm [*] fixups.
* gcc.dg/vla-4.c: Add.
* gcc.dg/vla-5.c: Add.
* gcc.dg/vla-6.c: Add.
From-SVN: r113888
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index f4d3330..ea1a8c4 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -331,6 +331,10 @@ struct c_scope GTY((chain_next ("%h.outer"))) declarations. */ BOOL_BITFIELD parm_flag : 1; + /* True if we saw [*] in this scope. Used to give an error messages + if these appears in a function definition. */ + BOOL_BITFIELD had_vla_unspec : 1; + /* True if we already complained about forward parameter decls in this scope. This prevents double warnings on foo (int a; int b; ...) */ @@ -3007,14 +3011,14 @@ quals_from_declspecs (const struct c_declspecs *specs) return quals; } -/* Construct an array declarator. EXPR is the expression inside [], or - NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied - to the pointer to which a parameter array is converted). STATIC_P is - true if "static" is inside the [], false otherwise. VLA_UNSPEC_P - is true if the array is [*], a VLA of unspecified length which is - nevertheless a complete type (not currently implemented by GCC), - false otherwise. The field for the contained declarator is left to be - filled in by set_array_declarator_inner. */ +/* Construct an array declarator. EXPR is the expression inside [], + or NULL_TREE. QUALS are the type qualifiers inside the [] (to be + applied to the pointer to which a parameter array is converted). + STATIC_P is true if "static" is inside the [], false otherwise. + VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified + length which is nevertheless a complete type, false otherwise. The + field for the contained declarator is left to be filled in by + set_array_declarator_inner. */ struct c_declarator * build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, @@ -3046,7 +3050,16 @@ build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, pedwarn ("ISO C90 does not support %<[*]%> array declarators"); } if (vla_unspec_p) - warning (0, "GCC does not yet properly implement %<[*]%> array declarators"); + { + if (!current_scope->parm_flag) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than function prototype scope"); + declarator->u.array.vla_unspec_p = false; + return NULL; + } + current_scope->had_vla_unspec = true; + } return declarator; } @@ -3858,20 +3871,21 @@ grokdeclarator (const struct c_declarator *declarator, int type_quals = TYPE_UNQUALIFIED; const char *name, *orig_name; tree typedef_type = 0; - int funcdef_flag = 0; + bool funcdef_flag = false; bool funcdef_syntax = false; int size_varies = 0; tree decl_attr = declspecs->decl_attr; int array_ptr_quals = TYPE_UNQUALIFIED; tree array_ptr_attrs = NULL_TREE; int array_parm_static = 0; + bool array_parm_vla_unspec_p = false; tree returned_attrs = NULL_TREE; bool bitfield = width != NULL; tree element_type; struct c_arg_info *arg_info = 0; if (decl_context == FUNCDEF) - funcdef_flag = 1, decl_context = NORMAL; + funcdef_flag = true, decl_context = NORMAL; /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ @@ -4137,7 +4151,8 @@ grokdeclarator (const struct c_declarator *declarator, array_ptr_quals = declarator->u.array.quals; array_ptr_attrs = declarator->u.array.attrs; array_parm_static = declarator->u.array.static_p; - + array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p; + declarator = declarator->declarator; /* Check for some types that there cannot be arrays of. */ @@ -4262,6 +4277,20 @@ grokdeclarator (const struct c_declarator *declarator, identical to GCC's zero-length array extension. */ itype = build_range_type (sizetype, size_zero_node, NULL_TREE); } + else if (decl_context == PARM) + { + if (array_parm_vla_unspec_p) + { + if (! orig_name) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than a declaration"); + } + + itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + size_varies = 1; + } + } /* Complain about arrays of incomplete types. */ if (!COMPLETE_TYPE_P (type)) @@ -4275,7 +4304,7 @@ grokdeclarator (const struct c_declarator *declarator, if (type != error_mark_node) { if (size_varies) - C_TYPE_VARIABLE_SIZE (type) = 1; + C_TYPE_VARIABLE_SIZE (type) = 1; /* The GCC extension for zero-length arrays differs from ISO flexible array members in that sizeof yields @@ -4285,6 +4314,12 @@ grokdeclarator (const struct c_declarator *declarator, TYPE_SIZE (type) = bitsize_zero_node; TYPE_SIZE_UNIT (type) = size_zero_node; } + if (array_parm_vla_unspec_p) + { + /* The type is complete. C99 6.7.5.2p4 */ + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + } } if (decl_context != PARM @@ -4472,6 +4507,13 @@ grokdeclarator (const struct c_declarator *declarator, return type; } + if (pedantic && decl_context == FIELD + && variably_modified_type_p (type, NULL_TREE)) + { + /* C99 6.7.2.1p8 */ + pedwarn ("a member of a structure or union cannot have a variably modified type"); + } + /* Aside from typedefs and type names (handle above), `void' at top level (not within pointer) is allowed only in public variables. @@ -4737,6 +4779,13 @@ grokdeclarator (const struct c_declarator *declarator, } } + if (storage_class == csc_extern + && variably_modified_type_p (type, NULL_TREE)) + { + /* C99 6.7.5.2p2 */ + error ("object with variably modified type must have no linkage"); + } + /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ @@ -4778,7 +4827,7 @@ grokdeclarator (const struct c_declarator *declarator, } /* Decode the parameter-list info for a function type or function definition. - The argument is the value returned by `get_parm_info' (or made in parse.y + The argument is the value returned by `get_parm_info' (or made in c-parse.c if there is an identifier list instead of a parameter decl list). These two functions are separate because when a function returns or receives functions then each is called multiple times but the order @@ -4796,6 +4845,13 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) { tree arg_types = arg_info->types; + if (funcdef_flag && arg_info->had_vla_unspec) + { + /* A function definition isn't function prototype scope C99 6.2.1p4. */ + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than function prototype scope"); + } + if (arg_types == 0 && !funcdef_flag && !in_system_header) warning (OPT_Wstrict_prototypes, "function declaration isn%'t a prototype"); @@ -4892,6 +4948,7 @@ get_parm_info (bool ellipsis) arg_info->tags = 0; arg_info->types = 0; arg_info->others = 0; + arg_info->had_vla_unspec = current_scope->had_vla_unspec; /* The bindings in this scope must not get put into a block. We will take care of deleting the binding nodes. */ @@ -5541,7 +5598,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) /* If we're inside a function proper, i.e. not file-scope and not still parsing parameters, then arrange for the size of a variable sized type to be bound now. */ - if (cur_stmt_list && variably_modified_type_p (t, NULL)) + if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE)) add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t))); return t; |