aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2006-05-18 18:22:12 +0000
committerMike Stump <mrs@gcc.gnu.org>2006-05-18 18:22:12 +0000
commit52ffd86eb62d0320ccf64138e5d7d37ab7a6f7c5 (patch)
tree3393aa88e335ad0c151ee642c9e17e8807ed52e9 /gcc/c-decl.c
parent4f9533c7722fa07511a94d005227961f4a4dec23 (diff)
downloadgcc-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.c87
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;