c-parse.in (array_declarator): New.

* c-parse.in (array_declarator): New.  Handle C99 constructs.
	Don't restrict [*] declarators to C only.
	(after_type_declarator, parm_declarator_starttypename,
	parm_declarator_nostarttypename, notype_declarator,
	direct_absdcl1): Use it.
	* c-decl.c (build_array_declarator, set_array_declarator_type):
	New functions.  Warn that [*] isn't properly implemented; pedwarn
	for [*] outside C99 mode if pedantic rather than giving a hard
	error.
	(grokdeclarator): Handle static and type qualifiers in parameter
	array declarators.
	* c-tree.h (build_array_declarator, set_array_declarator_type):
	Declare.
	* extend.texi (Attribute Syntax): Document attributes in parameter
	array declarators.

testsuite:
	* gcc.dg/c90-arraydecl-1.c, gcc.dg/c99-arraydecl-1.c: New tests.

From-SVN: r42574
This commit is contained in:
Joseph Myers 2001-05-25 12:12:47 +01:00 committed by Joseph Myers
parent b60868e00c
commit 0e03329a6f
8 changed files with 329 additions and 44 deletions

View File

@ -1,3 +1,21 @@
2001-05-25 Joseph S. Myers <jsm28@cam.ac.uk>
* c-parse.in (array_declarator): New. Handle C99 constructs.
Don't restrict [*] declarators to C only.
(after_type_declarator, parm_declarator_starttypename,
parm_declarator_nostarttypename, notype_declarator,
direct_absdcl1): Use it.
* c-decl.c (build_array_declarator, set_array_declarator_type):
New functions. Warn that [*] isn't properly implemented; pedwarn
for [*] outside C99 mode if pedantic rather than giving a hard
error.
(grokdeclarator): Handle static and type qualifiers in parameter
array declarators.
* c-tree.h (build_array_declarator, set_array_declarator_type):
Declare.
* extend.texi (Attribute Syntax): Document attributes in parameter
array declarators.
2001-05-25 Mark <mark@codesourcery.com>
* config/i386/i386.md: Make sure cmpstr peepholes do not

View File

@ -3278,6 +3278,60 @@ shadow_tag_warned (declspecs, warned)
}
}
/* 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
non-zero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
is non-zero is the array is [*], a VLA of unspecified length which is
nevertheless a complete type (not currently implemented by GCC),
zero otherwise. The declarator is constructed as an ARRAY_REF
(to be decoded by grokdeclarator), whose operand 0 is what's on the
left of the [] (filled by in set_array_declarator_type) and operand 1
is the expression inside; whose TREE_TYPE is the type qualifiers and
which has TREE_STATIC set if "static" is used. */
tree
build_array_declarator (expr, quals, static_p, vla_unspec_p)
tree expr;
tree quals;
int static_p;
int vla_unspec_p;
{
tree decl;
decl = build_nt (ARRAY_REF, NULL_TREE, expr);
TREE_TYPE (decl) = quals;
TREE_STATIC (decl) = (static_p ? 1 : 0);
if (pedantic && !flag_isoc99)
{
if (static_p || quals != NULL_TREE)
pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
if (vla_unspec_p)
pedwarn ("ISO C89 does not support `[*]' array declarators");
}
if (vla_unspec_p)
warning ("GCC does not yet properly implement `[*]' array declarators");
return decl;
}
/* Set the type of an array declarator. DECL is the declarator, as
constructed by build_array_declarator; TYPE is what appears on the left
of the [] and goes in operand 0. ABSTRACT_P is non-zero if it is an
abstract declarator, zero otherwise; this is used to reject static and
type qualifiers in abstract declarators, where they are not in the
C99 grammar. */
tree
set_array_declarator_type (decl, type, abstract_p)
tree decl;
tree type;
int abstract_p;
{
TREE_OPERAND (decl, 0) = type;
if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
error ("static or type qualifiers in abstract declarator");
return decl;
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
@ -3861,6 +3915,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
int bitfield = 0;
int size_varies = 0;
tree decl_machine_attr = NULL_TREE;
tree array_ptr_quals = NULL_TREE;
int array_parm_static = 0;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
@ -4289,6 +4345,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
if (array_ptr_quals != NULL_TREE || array_parm_static)
{
/* Only the innermost declarator (making a parameter be of
array type which is converted to pointer type)
may have static or type qualifiers. */
error ("static or type qualifiers in non-parameter array declarator");
array_ptr_quals = NULL_TREE;
array_parm_static = 0;
}
if (TREE_CODE (declarator) == ARRAY_REF)
{
register tree itype = NULL_TREE;
@ -4296,6 +4362,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* The index is a signed object `sizetype' bits wide. */
tree index_type = signed_type (sizetype);
array_ptr_quals = TREE_TYPE (declarator);
array_parm_static = TREE_STATIC (declarator);
declarator = TREE_OPERAND (declarator, 0);
/* Check for some types that there cannot be arrays of. */
@ -4445,6 +4514,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
if (decl_context != PARM
&& (array_ptr_quals != NULL_TREE || array_parm_static))
{
error ("static or type qualifiers in non-parameter array declarator");
array_ptr_quals = NULL_TREE;
array_parm_static = 0;
}
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
@ -4696,6 +4772,44 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
if (array_ptr_quals)
{
tree new_ptr_quals, new_ptr_attrs;
int erred = 0;
split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
/* We don't yet implement attributes in this context. */
if (new_ptr_attrs != NULL_TREE)
warning ("attributes in parameter array declarator ignored");
constp = 0;
volatilep = 0;
restrictp = 0;
for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
{
tree qualifier = TREE_VALUE (new_ptr_quals);
if (C_IS_RESERVED_WORD (qualifier))
{
if (C_RID_CODE (qualifier) == RID_CONST)
constp++;
else if (C_RID_CODE (qualifier) == RID_VOLATILE)
volatilep++;
else if (C_RID_CODE (qualifier) == RID_RESTRICT)
restrictp++;
else
erred++;
}
else
erred++;
}
if (erred)
error ("invalid type modifier within array declarator");
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)

View File

@ -198,6 +198,7 @@ end ifc
%type <ttype> notype_declarator after_type_declarator
%type <ttype> parm_declarator
%type <ttype> parm_declarator_starttypename parm_declarator_nostarttypename
%type <ttype> array_declarator
%type <ttype> structsp_attr structsp_nonattr
%type <ttype> component_decl_list component_decl_list2
@ -1668,10 +1669,8 @@ after_type_declarator:
/* | after_type_declarator '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
| after_type_declarator '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| after_type_declarator '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| after_type_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| '*' maybe_type_quals_setattrs after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| TYPENAME
@ -1695,17 +1694,8 @@ parm_declarator_starttypename:
/* | parm_declarator_starttypename '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
ifc
| parm_declarator_starttypename '[' '*' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
if (! flag_isoc99)
error ("`[*]' in parameter declaration only allowed in ISO C 99");
}
end ifc
| parm_declarator_starttypename '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| parm_declarator_starttypename '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| parm_declarator_starttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| TYPENAME
;
@ -1715,17 +1705,8 @@ parm_declarator_nostarttypename:
/* | parm_declarator_nostarttypename '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
ifc
| parm_declarator_nostarttypename '[' '*' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
if (! flag_isoc99)
error ("`[*]' in parameter declaration only allowed in ISO C 99");
}
end ifc
| parm_declarator_nostarttypename '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| parm_declarator_nostarttypename '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| parm_declarator_nostarttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| '*' maybe_type_quals_setattrs parm_declarator_starttypename %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| '*' maybe_type_quals_setattrs parm_declarator_nostarttypename %prec UNARY
@ -1747,17 +1728,8 @@ notype_declarator:
{ $$ = $3; }
| '*' maybe_type_quals_setattrs notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
ifc
| notype_declarator '[' '*' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
if (! flag_isoc99)
error ("`[*]' in parameter declaration only allowed in ISO C 99");
}
end ifc
| notype_declarator '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| notype_declarator '[' ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| notype_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| IDENTIFIER
;
@ -2035,16 +2007,42 @@ direct_absdcl1:
{ $$ = $3; }
| direct_absdcl1 '(' parmlist
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
| direct_absdcl1 '[' expr ']'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| direct_absdcl1 '[' ']'
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
| direct_absdcl1 array_declarator
{ $$ = set_array_declarator_type ($2, $1, 1); }
| '(' parmlist
{ $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); }
| '[' expr ']'
{ $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
| array_declarator
{ $$ = set_array_declarator_type ($1, NULL_TREE, 1); }
;
/* The [...] part of a declarator for an array type. */
array_declarator:
'[' expr ']'
{ $$ = build_array_declarator ($2, NULL_TREE, 0, 0); }
| '[' declspecs_nosc expr ']'
{ $$ = build_array_declarator ($3, $2, 0, 0); }
| '[' ']'
{ $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
{ $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 0); }
| '[' declspecs_nosc ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
| '[' '*' ']'
{ $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 1); }
| '[' declspecs_nosc '*' ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
| '[' SCSPEC expr ']'
{ if (C_RID_CODE ($2) != RID_STATIC)
error ("storage class specifier in array declarator");
$$ = build_array_declarator ($3, NULL_TREE, 1, 0); }
| '[' SCSPEC declspecs_nosc expr ']'
{ if (C_RID_CODE ($2) != RID_STATIC)
error ("storage class specifier in array declarator");
$$ = build_array_declarator ($4, $3, 1, 0); }
| '[' declspecs_nosc SCSPEC expr ']'
{ if (C_RID_CODE ($3) != RID_STATIC)
error ("storage class specifier in array declarator");
$$ = build_array_declarator ($4, $2, 1, 0); }
;
/* A nonempty series of declarations and statements (possibly followed by
some labels) that can form the body of a compound statement.

View File

@ -153,6 +153,7 @@ extern int yyparse_1 PARAMS ((void));
extern void gen_aux_info_record PARAMS ((tree, int, int, int));
/* in c-decl.c */
extern tree build_array_declarator PARAMS ((tree, tree, int, int));
extern tree build_enumerator PARAMS ((tree, tree));
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
@ -197,6 +198,7 @@ extern void push_label_level PARAMS ((void));
extern void push_parm_decl PARAMS ((tree));
extern tree pushdecl_top_level PARAMS ((tree));
extern void pushtag PARAMS ((tree, tree));
extern tree set_array_declarator_type PARAMS ((tree, tree, int));
extern tree shadow_label PARAMS ((tree));
extern void shadow_record_fields PARAMS ((tree));
extern void shadow_tag PARAMS ((tree));

View File

@ -2182,6 +2182,13 @@ An attribute specifier list may, in future, be permitted to appear after
the declarator in a function definition (before any old-style parameter
declarations or the function body).
Attribute specifiers may be mixed with type qualifiers appearing inside
the @code{[]} of a parameter array declarator, in the C99 construct by
which such qualifiers are applied to the pointer to which the array is
implicitly converted. Such attribute specifiers apply to the pointer,
not to the array, but at present this is not implemented and they are
ignored.
An attribute specifier list may appear at the start of a nested
declarator. At present, there are some limitations in this usage: the
attributes apply to the identifer declared, and to all subsequent

View File

@ -1,3 +1,7 @@
2001-05-25 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c90-arraydecl-1.c, gcc.dg/c99-arraydecl-1.c: New tests.
2001-05-24 Mark Mitchell <mark@codesourcery.com>
G++ no longer defines builtins that do not begin with __builtin.

View File

@ -0,0 +1,31 @@
/* Test for C99 forms of array declarator: rejected in C90. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
/* Use of [*] (possibly with type qualifiers) in an array declarator with
function prototype scope is a C99 feature. GCC does not yet implement
it correctly, so gives a warning about this. so we can't yet test here
that we get just one error and no warnings. */
void foo0 (int a, int b[*]); /* { dg-error "ISO C89" "\[*\] not in C89" } */
/* { dg-warning "implement" "\[*\] not implemented" { target *-*-* } 11 } */
void foo1 (int, int [*]); /* { dg-error "ISO C89" "\[*\] not in C89" } */
/* { dg-warning "implement" "\[*\] not implemented" { target *-*-* } 13 } */
/* 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 C89" "\[quals\] not in C89" { target *-*-* } 19 } */
void bar1 (int a[const 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "ISO C89" "\[quals expr\] not in C89" { target *-*-* } 21 } */
void bar2 (int a[static 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "ISO C89" "\[static expr\] not in C89" { target *-*-* } 23 } */
void bar3 (int a[static const 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "ISO C89" "\[static quals expr\] not in C89" { target *-*-* } 25 } */
void bar4 (int a[const static 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "ISO C89" "\[quals static expr\] not in C89" { target *-*-* } 27 } */
/* Because [*] isn't properly implemented and so warns, we don't test here
for [const *] yet. */

View File

@ -0,0 +1,111 @@
/* Test for C99 forms of array declarator. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
/* Because GCC doesn't yet implement it, we don't yet test for [*] here. */
/* Test each of: [quals], [quals expr], [static expr], [static quals expr],
[quals static expr]. Not yet: [quals *]. */
void f00 (int a[const]);
void f01 (int [const]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "abstract" "\[quals\] in abstract declarator" { target *-*-* } 12 } */
void
f02 (int a[const])
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 17 } */
int *const *c = &a;
}
void
f03 (a)
int a[const];
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 25 } */
int *const *c = &a;
}
void f10 (int a[const 2]);
void f11 (int [const 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "abstract" "\[quals expr\] in abstract declarator" { target *-*-* } 31 } */
void
f12 (int a[const 2])
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 36 } */
int *const *c = &a;
}
void
f13 (a)
int a[const 2];
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 44 } */
int *const *c = &a;
}
void f20 (int a[static 2]);
void f21 (int [static 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "abstract" "\[static expr\] in abstract declarator" { target *-*-* } 50 } */
void
f22 (int a[static 2])
{
int **b = &a;
int *const *c = &a;
}
void
f23 (a)
int a[static 2];
{
int **b = &a;
int *const *c = &a;
}
void f30 (int a[static const 2]);
void f31 (int [static const 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "abstract" "\[static quals expr\] in abstract declarator" { target *-*-* } 67 } */
void
f32 (int a[static const 2])
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 72 } */
int *const *c = &a;
}
void
f33 (a)
int a[static const 2];
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 80 } */
int *const *c = &a;
}
void f40 (int a[const static 2]);
void f41 (int [const static 2]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "abstract" "\[quals static expr\] in abstract declarator" { target *-*-* } 86 } */
void
f42 (int a[const static 2])
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 91 } */
int *const *c = &a;
}
void
f43 (a)
int a[const static 2];
{
int **b = &a; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "discards" "discards quals" { target *-*-* } 99 } */
int *const *c = &a;
}
/* Test rejection of static and type qualifiers in non-parameter contexts. */
int x[const 2]; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "non-parameter" "quals in non-parm array" { target *-*-* } 105 } */
int y[static 2]; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "non-parameter" "static in non-parm array" { target *-*-* } 107 } */
void g (int a[static 2][3]);
void h (int a[2][static 3]); /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "non-parameter" "static in non-final parm array" { target *-*-* } 110 } */