mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-05 13:51:57 +08:00
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
This commit is contained in:
parent
4f9533c772
commit
52ffd86eb6
@ -1,3 +1,30 @@
|
||||
2006-05-18 Mike Stump <mrs@apple.com>
|
||||
|
||||
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 [*].
|
||||
|
||||
2006-05-18 Michael Matz <matz@suse.de>
|
||||
|
||||
PR target/27599
|
||||
|
87
gcc/c-decl.c
87
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;
|
||||
|
@ -257,3 +257,11 @@ c_types_compatible_p (tree x, tree y)
|
||||
{
|
||||
return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
|
||||
}
|
||||
|
||||
/* Determine if the type is a vla type for the backend. */
|
||||
|
||||
bool
|
||||
c_vla_unspec_p (tree x, tree fn ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return c_vla_type_p (x);
|
||||
}
|
||||
|
@ -137,4 +137,7 @@ extern void c_initialize_diagnostics (diagnostic_context *);
|
||||
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
|
||||
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing
|
||||
|
||||
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
|
||||
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
|
||||
|
||||
#endif /* GCC_C_OBJC_COMMON */
|
||||
|
@ -2148,6 +2148,7 @@ c_parser_typeof_specifier (c_parser *parser)
|
||||
}
|
||||
else
|
||||
{
|
||||
bool was_vm;
|
||||
struct c_expr expr = c_parser_expression (parser);
|
||||
skip_evaluation--;
|
||||
in_typeof--;
|
||||
@ -2155,7 +2156,13 @@ c_parser_typeof_specifier (c_parser *parser)
|
||||
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
|
||||
error ("%<typeof%> applied to a bit-field");
|
||||
ret.spec = TREE_TYPE (expr.value);
|
||||
pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
|
||||
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)
|
||||
c_finish_expr_stmt (expr.value);
|
||||
pop_maybe_used (was_vm);
|
||||
}
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
||||
return ret;
|
||||
@ -2451,6 +2458,8 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
|
||||
}
|
||||
declarator = build_array_declarator (dimen, quals_attrs, static_seen,
|
||||
star_seen);
|
||||
if (declarator == NULL)
|
||||
return NULL;
|
||||
inner = set_array_declarator_inner (declarator, inner, !id_present);
|
||||
return c_parser_direct_declarator_inner (parser, id_present, inner);
|
||||
}
|
||||
@ -4868,6 +4877,12 @@ c_parser_sizeof_expression (c_parser *parser)
|
||||
/* sizeof ( type-name ). */
|
||||
skip_evaluation--;
|
||||
in_sizeof--;
|
||||
if (type_name->declarator->kind == cdk_array
|
||||
&& type_name->declarator->u.array.vla_unspec_p)
|
||||
{
|
||||
/* C99 6.7.5.2p4 */
|
||||
error ("%<[*]%> not allowed in other than a declaration");
|
||||
}
|
||||
return c_expr_sizeof_type (type_name);
|
||||
}
|
||||
else
|
||||
|
@ -309,6 +309,8 @@ struct c_arg_info {
|
||||
/* A list of non-parameter decls (notably enumeration constants)
|
||||
defined with the parameters. */
|
||||
tree others;
|
||||
/* True when these arguments had [*]. */
|
||||
BOOL_BITFIELD had_vla_unspec : 1;
|
||||
};
|
||||
|
||||
/* A declarator. */
|
||||
@ -506,6 +508,7 @@ extern bool c_missing_noreturn_ok_p (tree);
|
||||
extern tree c_objc_common_truthvalue_conversion (tree expr);
|
||||
extern bool c_warn_unused_global_decl (tree);
|
||||
extern void c_initialize_diagnostics (diagnostic_context *);
|
||||
extern bool c_vla_unspec_p (tree x, tree fn);
|
||||
|
||||
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
|
||||
c_build_qualified_type ((TYPE), \
|
||||
@ -524,6 +527,7 @@ extern struct c_label_context_vm *label_context_stack_vm;
|
||||
extern tree require_complete_type (tree);
|
||||
extern int same_translation_unit_p (tree, tree);
|
||||
extern int comptypes (tree, tree);
|
||||
extern bool c_vla_type_p (tree);
|
||||
extern bool c_mark_addressable (tree);
|
||||
extern void c_incomplete_type_error (tree, tree);
|
||||
extern tree c_type_promotes_to (tree);
|
||||
|
@ -253,6 +253,17 @@ qualify_type (tree type, tree like)
|
||||
return c_build_qualified_type (type,
|
||||
TYPE_QUALS (type) | TYPE_QUALS (like));
|
||||
}
|
||||
|
||||
/* Return true iff the given tree T is a variable length array. */
|
||||
|
||||
bool
|
||||
c_vla_type_p (tree t)
|
||||
{
|
||||
if (TREE_CODE (t) == ARRAY_TYPE
|
||||
&& C_TYPE_VARIABLE_SIZE (t))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return the composite type of two compatible types.
|
||||
|
||||
@ -330,6 +341,8 @@ composite_type (tree t1, tree t2)
|
||||
d2_variable = (!d2_zero
|
||||
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|
||||
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
|
||||
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
|
||||
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
|
||||
|
||||
/* Save space: see if the result is identical to one of the args. */
|
||||
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
|
||||
@ -834,6 +847,8 @@ comptypes_internal (tree type1, tree type2)
|
||||
d2_variable = (!d2_zero
|
||||
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|
||||
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
|
||||
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
|
||||
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
|
||||
|
||||
if (d1_variable || d2_variable)
|
||||
break;
|
||||
@ -2116,6 +2131,11 @@ c_expr_sizeof_expr (struct c_expr expr)
|
||||
{
|
||||
ret.value = c_sizeof (TREE_TYPE (expr.value));
|
||||
ret.original_code = ERROR_MARK;
|
||||
if (c_vla_type_p (TREE_TYPE (expr.value)))
|
||||
{
|
||||
/* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */
|
||||
ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value);
|
||||
}
|
||||
pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
|
||||
}
|
||||
return ret;
|
||||
|
@ -1,3 +1,10 @@
|
||||
2006-05-18 Mike Stump <mrs@apple.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2006-05-12 Stuart Hastings <stuart@apple.com>
|
||||
|
||||
* testsuite/gcc.target/i386/20060512-1.c: New.
|
||||
|
@ -9,23 +9,22 @@
|
||||
that we get just one error and no warnings. */
|
||||
|
||||
void foo0 (int a, int b[*]); /* { dg-error "ISO C90" "\[*\] not in C90" } */
|
||||
/* { dg-warning "implement" "\[*\] not implemented" { target *-*-* } 11 } */
|
||||
void foo1 (int, int [*]); /* { dg-error "ISO C90" "\[*\] not in C90" } */
|
||||
/* { dg-warning "implement" "\[*\] not implemented" { target *-*-* } 13 } */
|
||||
/* { dg-error "allowed" "\'\[*\]\' not allowed in other than a declaration" { target *-*-* } 12 } */
|
||||
|
||||
/* Use of static and type qualifiers (not allowed with abstract declarators)
|
||||
is a C99 feature. */
|
||||
|
||||
void bar0 (int a[const]); /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "ISO C90" "\[quals\] not in C90" { target *-*-* } 19 } */
|
||||
/* { dg-error "ISO C90" "\[quals\] not in C90" { target *-*-* } 18 } */
|
||||
void bar1 (int a[const 2]); /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "ISO C90" "\[quals expr\] not in C90" { target *-*-* } 21 } */
|
||||
/* { dg-error "ISO C90" "\[quals expr\] not in C90" { target *-*-* } 20 } */
|
||||
void bar2 (int a[static 2]); /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "ISO C90" "\[static expr\] not in C90" { target *-*-* } 23 } */
|
||||
/* { dg-error "ISO C90" "\[static expr\] not in C90" { target *-*-* } 22 } */
|
||||
void bar3 (int a[static const 2]); /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "ISO C90" "\[static quals expr\] not in C90" { target *-*-* } 25 } */
|
||||
/* { dg-error "ISO C90" "\[static quals expr\] not in C90" { target *-*-* } 24 } */
|
||||
void bar4 (int a[const static 2]); /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "ISO C90" "\[quals static expr\] not in C90" { target *-*-* } 27 } */
|
||||
/* { dg-error "ISO C90" "\[quals static expr\] not in C90" { target *-*-* } 26 } */
|
||||
|
||||
/* Because [*] isn't properly implemented and so warns, we don't test here
|
||||
for [const *] yet. */
|
||||
|
48
gcc/testsuite/gcc.dg/vla-4.c
Normal file
48
gcc/testsuite/gcc.dg/vla-4.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-std=c99 -pedantic-errors" } */
|
||||
/* PR c/18740 */
|
||||
|
||||
static int i;
|
||||
|
||||
int foo(int n)
|
||||
{
|
||||
int (*t)[n];
|
||||
i = 0;
|
||||
int j = 0;
|
||||
char b[1][n+3]; /* Variable length array. */
|
||||
int d[3][n]; /* Variable length array. */
|
||||
sizeof (b[i++ + sizeof(j++)]); /* Outer sizeof is evaluated for vla, but not the inner one. */
|
||||
if (i != 1 || j != 0)
|
||||
return 1;
|
||||
__typeof__(b[i++]) c1; /* typeof is evauluated when given a vm */
|
||||
if (i != 2)
|
||||
return 1;
|
||||
__typeof__(t + (i++,0)) c2; /* typeof is evauluated when given a vm */
|
||||
if (i != 3)
|
||||
return 1;
|
||||
__typeof__(i + (i++,0)) c3; /* typeof is not evauluated when not given a vm */
|
||||
if (i != 3)
|
||||
return 1;
|
||||
sizeof (d[i++]); /* sizeof is evaluated for vla. */
|
||||
if (i != 4)
|
||||
return 1;
|
||||
__alignof__(__typeof__(t + (i++,0))); /* typeof is not evauluated when given a vm inside alignof*/
|
||||
if (i != 4)
|
||||
return 1;
|
||||
sizeof(__typeof__(t + (i++,0))); /* typeof is not evauluated when given a vm inside sizeof*/
|
||||
if (i != 4)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int foo6(int a, int b[a][a], int (*c)[sizeof(*b)]) {
|
||||
return sizeof (*c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int b[10][10];
|
||||
int (*c)[sizeof(int)*10];
|
||||
if (foo6(10, b, c) != 10*sizeof(int)*sizeof(int))
|
||||
return 1;
|
||||
return foo(10);
|
||||
}
|
24
gcc/testsuite/gcc.dg/vla-5.c
Normal file
24
gcc/testsuite/gcc.dg/vla-5.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* { dg-options "-std=c99 -pedantic-errors" } */
|
||||
|
||||
void foo1(int (*o)(int p[*])) { }
|
||||
|
||||
void foo2(int o[*]);
|
||||
void foo3(int o[4][*]);
|
||||
|
||||
void foo4(int j, int a[j]);
|
||||
void foo4(int, int a[*]);
|
||||
void foo4(int, int a[]);
|
||||
void foo4(int j, int a[j]) {
|
||||
}
|
||||
|
||||
int foo5(int a, int b[*][*], int c[static sizeof(*b)]);
|
||||
int foo5(int a, int b[10][10], int c[400]) {
|
||||
return sizeof (c);
|
||||
}
|
||||
|
||||
int foo6(int a, int b[*][*], int c[static sizeof(*b)]);
|
||||
int foo6(int a, int b[a][a], int c[sizeof(*b)]) {
|
||||
return sizeof (c);
|
||||
}
|
||||
|
||||
void foo7(__typeof__ (int (*)(int o[*])) i);
|
26
gcc/testsuite/gcc.dg/vla-6.c
Normal file
26
gcc/testsuite/gcc.dg/vla-6.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* { dg-options "-std=c99 -pedantic-errors" } */
|
||||
|
||||
int a[*]; /* { dg-error "not allowed in other than function prototype scope" } */
|
||||
void foo1() { int a[*]; } /* { dg-error "not allowed in other than function prototype scope" } */
|
||||
void foo2() { int a[*]; } /* { dg-error "not allowed in other than function prototype scope" } */
|
||||
int foo3(int i)[*]; /* { dg-error "not allowed in other than function prototype scope" } */
|
||||
void foo4(int o[*][4]) { } /* { dg-error "not allowed in other than function prototype scope" } */
|
||||
void foo5(int o[4][*]) { } /* { dg-error "not allowed in other than function prototype scope" } */
|
||||
|
||||
/* [*] can't be used in a type that's not a declaration */
|
||||
void foo11(int x[sizeof(int (*)[*])]); /* { dg-error "not allowed in other than a declaration" } */
|
||||
void foo12(int [*]); /* { dg-error "not allowed in other than a declaration" } */
|
||||
|
||||
extern int n;
|
||||
int B[100];
|
||||
void foo10(int m) {
|
||||
typedef int (*vla)[m];
|
||||
struct tag {
|
||||
vla x; /* { dg-error "a member of a structure or union cannot have a variably modified type" } */
|
||||
/* PR c/7948 */
|
||||
int (*y)[n]; /* { dg-error "a member of a structure or union cannot have a variably modified type" } */
|
||||
int z[n]; /* { dg-error "a member of a structure or union cannot have a variably modified type" } */
|
||||
};
|
||||
/* PR c/25802 */
|
||||
extern int (*r)[m]; /* { dg-error "variably modified type must have no linkage" } */
|
||||
}
|
@ -5629,11 +5629,7 @@ variably_modified_type_p (tree type, tree fn)
|
||||
if (type == error_mark_node)
|
||||
return false;
|
||||
|
||||
/* If TYPE itself has variable size, it is variably modified.
|
||||
|
||||
We do not yet have a representation of the C99 '[*]' syntax.
|
||||
When a representation is chosen, this function should be modified
|
||||
to test for that case as well. */
|
||||
/* If TYPE itself has variable size, it is variably modified. */
|
||||
RETURN_TRUE_IF_VAR (TYPE_SIZE (type));
|
||||
RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type));
|
||||
|
||||
@ -5673,7 +5669,7 @@ variably_modified_type_p (tree type, tree fn)
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
case QUAL_UNION_TYPE:
|
||||
/* We can't see if any of the field are variably-modified by the
|
||||
/* We can't see if any of the fields are variably-modified by the
|
||||
definition we normally use, since that would produce infinite
|
||||
recursion via pointers. */
|
||||
/* This is variably modified if some field's type is. */
|
||||
|
Loading…
Reference in New Issue
Block a user