summaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-09 01:25:48 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-09 01:25:48 +0000
commit9553111d52cbe9f5dcfcc65e2a251d9e7803e521 (patch)
tree9281b8a84cb7f58197f54b2a640390953626fb55 /gcc/c-decl.c
parentac206aff0574a7d02a44278c0ab08420efa6fca8 (diff)
downloadgcc-9553111d52cbe9f5dcfcc65e2a251d9e7803e521.tar.gz
PR c/8420
* c-tree.h (struct c_declspecs): New. (struct c_declarator, struct c_type_name, struct c_parm): Update element types. (build_array_declarator, grokfield, shadow_tag, shadow_tag_warned, start_function, start_decl, build_c_parm, make_pointer_declarator): Update prototypes. (build_null_declspecs, declspecs_add_qual, declspecs_add_type, declspecs_add_scspec, declspecs_add_attrs): New. (split_specs_attrs): Remove. * c-parse.in (%union): Add dsptype. (declspecs_nosc_nots_nosa_noea, declspecs_nosc_nots_nosa_ea, declspecs_nosc_nots_sa_noea, declspecs_nosc_nots_sa_ea, declspecs_nosc_ts_nosa_noea, declspecs_nosc_ts_nosa_ea, declspecs_nosc_ts_sa_noea, declspecs_nosc_ts_sa_ea, declspecs_sc_nots_nosa_noea, declspecs_sc_nots_nosa_ea, declspecs_sc_nots_sa_noea, declspecs_sc_nots_sa_ea, declspecs_sc_ts_nosa_noea, declspecs_sc_ts_nosa_ea, declspecs_sc_ts_sa_noea, declspecs_sc_ts_sa_ea, declspecs_ts, declspecs_nots, declspecs_ts_nosa, declspecs_nots_nosa, declspecs_nosc_ts, declspecs_nosc_nots, declspecs_nosc, declspecs, maybe_type_quals_attrs): Change to dsptype. (struct c_declspec_stack): New. (current_declspecs, declspec_stack): Change type. (PUSH_DECLSPEC_STACK, POP_DECLSPEC_STACK): Update to new structures. (extdefs): Likewise. (setspecs): Likewise. (fndef): Use current_declspecs for empty declspecs list. (declspecs_nosc_nots_nosa_noea, declspecs_nosc_nots_nosa_ea, declspecs_nosc_nots_sa_noea, declspecs_nosc_nots_sa_ea, declspecs_nosc_ts_nosa_noea, declspecs_nosc_ts_nosa_ea, declspecs_nosc_ts_sa_noea, declspecs_nosc_ts_sa_ea, declspecs_sc_nots_nosa_noea, declspecs_sc_nots_nosa_ea, declspecs_sc_nots_sa_noea, declspecs_sc_nots_sa_ea, declspecs_sc_ts_nosa_noea, declspecs_sc_ts_nosa_ea, declspecs_sc_ts_sa_noea, declspecs_sc_ts_sa_ea): Update to new structures and helper functions. Update comments. (typespec_nonattr): Correct comment. (maybe_type_quals_attrs, typename): Update to new structures. * c-decl.c (grokdeclarator, build_array_declarator, grokfield, shadow_tag, shadow_tag_warned, start_function, start_decl, build_c_parm, make_pointer_declarator, set_array_declarator_inner, groktypename): Update to new structures. (build_null_declspecs, declspecs_add_qual, declspecs_add_type, declspecs_add_scspec, declspecs_add_attrs): New. (split_specs_attrs): Remove. (shadow_tag_warned): Make warning for useless type names a pedwarn. Give hard error for long, short, signed, unsigned or _Complex used with struct, union or enum in empty declaration. Make found_tag a bool. (grokdeclarator): Remove checks now done at parse time. testsuite: * gcc.dg/anon-struct-4.c, gcc.dg/declspec-1.c, gcc.dg/declspec-2.c, gcc.dg/declspec-3.c, gcc.dg/declspec-4.c, gcc.dg/declspec-5.c, gcc.dg/declspec-6.c, gcc.dg/long-long-typespec-1.c: New tests. * gcc.dg/tls/diag-2.c: Update expected diagnostics git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@87218 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c591
1 files changed, 264 insertions, 327 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 2f0334414db..12e27a0053d 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -398,7 +398,8 @@ static GTY(()) tree static_dtors;
/* Forward declarations. */
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 *, tree,
+static tree grokdeclarator (const struct c_declarator *,
+ struct c_declspecs *,
enum decl_context, bool, tree *);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
@@ -2666,7 +2667,7 @@ builtin_function (const char *name, tree type, int function_code,
Otherwise, it is an error. */
void
-shadow_tag (tree declspecs)
+shadow_tag (const struct c_declspecs *declspecs)
{
shadow_tag_warned (declspecs, 0);
}
@@ -2674,21 +2675,15 @@ shadow_tag (tree declspecs)
/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
but no pedwarn. */
void
-shadow_tag_warned (tree declspecs, int warned)
+shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
{
- int found_tag = 0;
- tree link;
- tree specs, attrs;
+ bool found_tag = false;
pending_invalid_xref = 0;
- /* Remove the attributes from declspecs, since they will confuse the
- following code. */
- split_specs_attrs (declspecs, &specs, &attrs);
-
- for (link = specs; link; link = TREE_CHAIN (link))
+ if (declspecs->type && !declspecs->typedef_decl)
{
- tree value = TREE_VALUE (link);
+ tree value = declspecs->type;
enum tree_code code = TREE_CODE (value);
if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
@@ -2698,7 +2693,7 @@ shadow_tag_warned (tree declspecs, int warned)
tree name = TYPE_NAME (value);
tree t;
- found_tag++;
+ found_tag = true;
if (name == 0)
{
@@ -2722,20 +2717,39 @@ shadow_tag_warned (tree declspecs, int warned)
}
else
{
- if (!warned && ! in_system_header)
+ if (warned != 1 && !in_system_header)
{
- warning ("useless keyword or type name in empty declaration");
- warned = 2;
+ pedwarn ("useless type name in empty declaration");
+ warned = 1;
}
}
}
+ else if (warned != 1 && !in_system_header && declspecs->typedef_decl)
+ {
+ pedwarn ("useless type name in empty declaration");
+ warned = 1;
+ }
+
+ if (found_tag && (declspecs->specbits & ((1 << (int) RID_LONG)
+ | (1 << (int) RID_SHORT)
+ | (1 << (int) RID_UNSIGNED)
+ | (1 << (int) RID_SIGNED)
+ | (1 << (int) RID_COMPLEX))))
+ {
+ error ("long, short, signed, unsigned or complex used invalidly "
+ "in empty declaration");
+ warned = 1;
+ }
- if (found_tag > 1)
- error ("two types specified in one empty declaration");
+ if (!warned && !in_system_header && declspecs->specbits)
+ {
+ warning ("useless keyword or type name in empty declaration");
+ warned = 2;
+ }
if (warned != 1)
{
- if (found_tag == 0)
+ if (!found_tag)
pedwarn ("empty declaration");
}
}
@@ -2750,7 +2764,7 @@ shadow_tag_warned (tree declspecs, int warned)
filled in by set_array_declarator_inner. */
struct c_declarator *
-build_array_declarator (tree expr, tree quals, bool static_p,
+build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
bool vla_unspec_p)
{
struct c_declarator *declarator = XOBNEW (&parser_obstack,
@@ -2763,7 +2777,7 @@ build_array_declarator (tree expr, tree quals, bool static_p,
declarator->u.array.vla_unspec_p = vla_unspec_p;
if (pedantic && !flag_isoc99)
{
- if (static_p || quals != NULL_TREE)
+ if (static_p || quals != NULL)
pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
if (vla_unspec_p)
pedwarn ("ISO C90 does not support `[*]' array declarators");
@@ -2785,103 +2799,24 @@ set_array_declarator_inner (struct c_declarator *decl,
struct c_declarator *inner, bool abstract_p)
{
decl->declarator = inner;
- if (abstract_p && (decl->u.array.quals != NULL_TREE
+ if (abstract_p && (decl->u.array.quals != NULL
|| decl->u.array.static_p))
error ("static or type qualifiers in abstract declarator");
return decl;
}
-/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
- lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
-
- The head of the declspec list is stored in DECLSPECS.
- The head of the attribute list is stored in PREFIX_ATTRIBUTES.
-
- Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
- the list elements. We drop the containing TREE_LIST nodes and link the
- resulting attributes together the way decl_attributes expects them. */
-
-void
-split_specs_attrs (tree specs_attrs, tree *declspecs, tree *prefix_attributes)
-{
- tree t, s, a, next, specs, attrs;
-
- /* This can happen after an __extension__ in pedantic mode. */
- if (specs_attrs != NULL_TREE
- && TREE_CODE (specs_attrs) == INTEGER_CST)
- {
- *declspecs = NULL_TREE;
- *prefix_attributes = NULL_TREE;
- return;
- }
-
- /* This can happen in c++ (eg: decl: typespec initdecls ';'). */
- if (specs_attrs != NULL_TREE
- && TREE_CODE (specs_attrs) != TREE_LIST)
- {
- *declspecs = specs_attrs;
- *prefix_attributes = NULL_TREE;
- return;
- }
-
- /* Remember to keep the lists in the same order, element-wise. */
-
- specs = s = NULL_TREE;
- attrs = a = NULL_TREE;
- for (t = specs_attrs; t; t = next)
- {
- next = TREE_CHAIN (t);
- /* Declspecs have a non-NULL TREE_VALUE. */
- if (TREE_VALUE (t) != NULL_TREE)
- {
- if (specs == NULL_TREE)
- specs = s = t;
- else
- {
- TREE_CHAIN (s) = t;
- s = t;
- }
- }
- /* The TREE_PURPOSE may also be empty in the case of
- __attribute__(()). */
- else if (TREE_PURPOSE (t) != NULL_TREE)
- {
- if (attrs == NULL_TREE)
- attrs = a = TREE_PURPOSE (t);
- else
- {
- TREE_CHAIN (a) = TREE_PURPOSE (t);
- a = TREE_PURPOSE (t);
- }
- /* More attrs can be linked here, move A to the end. */
- while (TREE_CHAIN (a) != NULL_TREE)
- a = TREE_CHAIN (a);
- }
- }
-
- /* Terminate the lists. */
- if (s != NULL_TREE)
- TREE_CHAIN (s) = NULL_TREE;
- if (a != NULL_TREE)
- TREE_CHAIN (a) = NULL_TREE;
-
- /* All done. */
- *declspecs = specs;
- *prefix_attributes = attrs;
-}
-
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
groktypename (struct c_type_name *type_name)
{
tree type;
- tree specs, attrs;
+ tree attrs = type_name->specs->attrs;
- split_specs_attrs (type_name->specs, &specs, &attrs);
+ type_name->specs->attrs = NULL_TREE;
- type = grokdeclarator (type_name->declarator, specs, TYPENAME, false,
- NULL);
+ type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
+ false, NULL);
/* Apply attributes. */
decl_attributes (&type, attrs, 0);
@@ -2905,7 +2840,7 @@ groktypename (struct c_type_name *type_name)
grokfield and not through here. */
tree
-start_decl (struct c_declarator *declarator, tree declspecs,
+start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
bool initialized, tree attributes)
{
tree decl;
@@ -3632,8 +3567,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
(In one case we can return a ..._TYPE node instead.
For invalid input we sometimes return 0.)
- DECLSPECS is a chain of tree_list nodes whose value fields
- are the storage classes and type specifiers.
+ DECLSPECS is a c_declspecs structure for the declaration specifiers.
DECL_CONTEXT says which syntactic context this declaration is in:
NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
@@ -3657,29 +3591,25 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
and `extern' are interpreted. */
static tree
-grokdeclarator (const struct c_declarator *declarator, tree declspecs,
+grokdeclarator (const struct c_declarator *declarator,
+ struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width)
{
- int specbits = 0;
- tree spec;
- tree type = NULL_TREE;
- int longlong = 0;
+ int specbits = declspecs->specbits;
+ tree type = declspecs->type;
int constp;
int restrictp;
int volatilep;
int type_quals = TYPE_UNQUALIFIED;
int inlinep;
- int explicit_int = 0;
- int explicit_char = 0;
int defaulted_int = 0;
- tree typedef_decl = 0;
const char *name, *orig_name;
tree typedef_type = 0;
int funcdef_flag = 0;
bool funcdef_syntax = false;
int size_varies = 0;
tree decl_attr = NULL_TREE;
- tree array_ptr_quals = NULL_TREE;
+ struct c_declspecs *array_ptr_quals = 0;
int array_parm_static = 0;
tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL;
@@ -3735,116 +3665,10 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
- /* Look through the decl specs and record which ones appear.
- Some typespecs are defined as built-in typenames.
- Others, the ones that are modifiers of other types,
- are represented by bits in SPECBITS: set the bits for
- the modifiers that appear. Storage class keywords are also in SPECBITS.
-
- If there is a typedef name or a type, store the type in TYPE.
- This includes builtin typedefs such as `int'.
-
- Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char'
- and did not come from a user typedef.
-
- Set LONGLONG if `long' is mentioned twice. */
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
- {
- tree id = TREE_VALUE (spec);
-
- /* If the entire declaration is itself tagged as deprecated then
- suppress reports of deprecated items. */
- if (id && TREE_DEPRECATED (id))
- {
- if (deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (id);
- }
-
- if (id == ridpointers[(int) RID_INT])
- explicit_int = 1;
- if (id == ridpointers[(int) RID_CHAR])
- explicit_char = 1;
-
- if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
- {
- enum rid i = C_RID_CODE (id);
- if ((int) i <= (int) RID_LAST_MODIFIER)
- {
- if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
- {
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- {
- if (pedantic && !flag_isoc99 && ! in_system_header
- && warn_long_long)
- pedwarn ("ISO C90 does not support `long long'");
- longlong = 1;
- }
- }
- else if (specbits & (1 << (int) i))
- {
- if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
- {
- if (pedantic && !flag_isoc99)
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- }
- else
- error ("duplicate `%s'", IDENTIFIER_POINTER (id));
- }
-
- /* Diagnose "__thread extern". Recall that this list
- is in the reverse order seen in the text. */
- if (i == RID_THREAD
- && (specbits & (1 << (int) RID_EXTERN
- | 1 << (int) RID_STATIC)))
- {
- if (specbits & 1 << (int) RID_EXTERN)
- error ("`__thread' before `extern'");
- else
- error ("`__thread' before `static'");
- }
-
- specbits |= 1 << (int) i;
- goto found;
- }
- }
- if (type)
- error ("two or more data types in declaration of `%s'", name);
- /* Actual typedefs come to us as TYPE_DECL nodes. */
- else if (TREE_CODE (id) == TYPE_DECL)
- {
- if (TREE_TYPE (id) == error_mark_node)
- ; /* Allow the type to default to int to avoid cascading errors. */
- else
- {
- type = TREE_TYPE (id);
- decl_attr = DECL_ATTRIBUTES (id);
- typedef_decl = id;
- }
- }
- /* Built-in types come as identifiers. */
- else if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- tree t = lookup_name (id);
- if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("`%s' fails to be a typedef or built in type",
- IDENTIFIER_POINTER (id));
- else if (TREE_TYPE (t) == error_mark_node)
- ;
- else
- {
- type = TREE_TYPE (t);
- typedef_decl = t;
- }
- }
- else if (TREE_CODE (id) != ERROR_MARK)
- type = id;
-
- found:
- ;
- }
+ if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (declspecs->typedef_decl
+ ? declspecs->typedef_decl
+ : declspecs->type);
typedef_type = type;
if (type)
@@ -3883,7 +3707,7 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
/* Long double is a special combination. */
- if ((specbits & 1 << (int) RID_LONG) && ! longlong
+ if ((specbits & 1 << (int) RID_LONG) && ! declspecs->long_long_p
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
specbits &= ~(1 << (int) RID_LONG);
@@ -3902,7 +3726,7 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
error ("both long and short specified for `%s'", name);
else if (((specbits & 1 << (int) RID_LONG)
|| (specbits & 1 << (int) RID_SHORT))
- && explicit_char)
+ && declspecs->explicit_char_p)
error ("long or short specified with char for `%s'", name);
else if (((specbits & 1 << (int) RID_LONG)
|| (specbits & 1 << (int) RID_SHORT))
@@ -3925,7 +3749,8 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
else
{
ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char)
+ if (!declspecs->explicit_int_p && !defaulted_int
+ && !declspecs->explicit_char_p)
{
error ("long, short, signed or unsigned used invalidly for `%s'",
name);
@@ -3938,7 +3763,7 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
{
specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED));
- longlong = 0;
+ declspecs->long_long_p = 0;
}
}
@@ -3953,15 +3778,16 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
Optionally treat bit-fields as signed by default. */
if (specbits & 1 << (int) RID_UNSIGNED
|| (bitfield && ! flag_signed_bitfields
- && (explicit_int || defaulted_int || explicit_char
+ && (declspecs->explicit_int_p || defaulted_int
+ || declspecs->explicit_char_p
/* A typedef for plain `int' without `signed'
can be controlled just like plain `int'. */
- || ! (typedef_decl != 0
- && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
+ || ! (declspecs->typedef_decl != 0
+ && C_TYPEDEF_EXPLICITLY_SIGNED (declspecs->typedef_decl)))
&& TREE_CODE (type) != ENUMERAL_TYPE
&& !(specbits & 1 << (int) RID_SIGNED)))
{
- if (longlong)
+ if (declspecs->long_long_p)
type = long_long_unsigned_type_node;
else if (specbits & 1 << (int) RID_LONG)
type = long_unsigned_type_node;
@@ -3969,7 +3795,7 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
- else if (typedef_decl)
+ else if (declspecs->typedef_decl)
type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
@@ -3977,7 +3803,7 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
else if ((specbits & 1 << (int) RID_SIGNED)
&& type == char_type_node)
type = signed_char_type_node;
- else if (longlong)
+ else if (declspecs->long_long_p)
type = long_long_integer_type_node;
else if (specbits & 1 << (int) RID_LONG)
type = long_integer_type_node;
@@ -3993,7 +3819,7 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
- if (defaulted_int && ! longlong
+ if (defaulted_int && ! declspecs->long_long_p
&& ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
| (1 << (int) RID_UNSIGNED))))
@@ -4180,13 +4006,13 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
- if (array_ptr_quals != NULL_TREE || array_parm_static)
+ if (array_ptr_quals != NULL || 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_ptr_quals = NULL;
array_parm_static = 0;
}
@@ -4372,10 +4198,10 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
layout_type (type);
if (decl_context != PARM
- && (array_ptr_quals != NULL_TREE || array_parm_static))
+ && (array_ptr_quals != NULL || array_parm_static))
{
error ("static or type qualifiers in non-parameter array declarator");
- array_ptr_quals = NULL_TREE;
+ array_ptr_quals = NULL;
array_parm_static = 0;
}
break;
@@ -4469,53 +4295,27 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
type = build_pointer_type (type);
- /* Process a list of type modifier keywords (such as const
- or volatile) that were given inside the `*'. */
+ /* Process type qualifiers (such as const or volatile)
+ that were given inside the `*'. */
if (declarator->u.pointer_quals)
{
- tree typemodlist;
- int erred = 0;
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
- for (typemodlist = declarator->u.pointer_quals; typemodlist;
- typemodlist = TREE_CHAIN (typemodlist))
- {
- tree qualifier = TREE_VALUE (typemodlist);
-
- 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 pointer declarator");
- if (pedantic && !flag_isoc99)
- {
- if (constp > 1)
- pedwarn ("duplicate `const'");
- if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
- if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
- }
-
+ int pbits = declarator->u.pointer_quals->specbits;
+
+ /* The grammar should only permit qualifiers here. */
+ gcc_assert (!declarator->u.pointer_quals->type
+ && !(pbits & ~((1 << (int) RID_CONST)
+ | (1 << (int) RID_VOLATILE)
+ | (1 << (int) RID_RESTRICT))));
+
+ constp = !!(pbits & (1 << (int) RID_CONST));
+ volatilep = !!(pbits & (1 << (int) RID_VOLATILE));
+ restrictp = !!(pbits & (1 << (int) RID_RESTRICT));
+
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
-
+
declarator = declarator->declarator;
break;
}
@@ -4552,7 +4352,8 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator->u.id, type);
if ((specbits & (1 << (int) RID_SIGNED))
- || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
+ || (declspecs->typedef_decl
+ && C_TYPEDEF_EXPLICITLY_SIGNED (declspecs->typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
decl_attributes (&decl, returned_attrs, 0);
return decl;
@@ -4630,37 +4431,21 @@ grokdeclarator (const struct c_declarator *declarator, tree declspecs,
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);
+ int apqbits = array_ptr_quals->specbits;
+
/* We don't yet implement attributes in this context. */
- if (new_ptr_attrs != NULL_TREE)
+ if (array_ptr_quals->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++;
- }
+ /* The grammar should only permit qualifiers here. */
+ gcc_assert (!array_ptr_quals->type
+ && !(apqbits & ~((1 << (int) RID_CONST)
+ | (1 << (int) RID_VOLATILE)
+ | (1 << (int) RID_RESTRICT))));
- if (erred)
- error ("invalid type modifier within array declarator");
+ constp = !!(apqbits & (1 << (int) RID_CONST));
+ volatilep = !!(apqbits & (1 << (int) RID_VOLATILE));
+ restrictp = !!(apqbits & (1 << (int) RID_RESTRICT));
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
@@ -5282,7 +5067,8 @@ start_struct (enum tree_code code, tree name)
are ultimately passed to `build_struct' to make the RECORD_TYPE node. */
tree
-grokfield (struct c_declarator *declarator, tree declspecs, tree width)
+grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
+ tree width)
{
tree value;
@@ -5308,11 +5094,12 @@ grokfield (struct c_declarator *declarator, tree declspecs, tree width)
took this from Plan 9 or if it was an accident of implementation
that took root before someone noticed the bug... */
- tree type = TREE_VALUE (declspecs);
+ tree type = declspecs->type;
- if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
+ if (type
+ && (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ && (flag_ms_extensions || !declspecs->typedef_decl))
{
if (flag_ms_extensions)
; /* ok */
@@ -5916,7 +5703,7 @@ build_enumerator (tree name, tree value)
yyparse to report a parse error. */
int
-start_function (tree declspecs, struct c_declarator *declarator,
+start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
tree attributes)
{
tree decl1, old_decl;
@@ -6857,7 +6644,8 @@ build_void_list_node (void)
/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR. */
struct c_parm *
-build_c_parm (tree specs, tree attrs, struct c_declarator *declarator)
+build_c_parm (struct c_declspecs *specs, tree attrs,
+ struct c_declarator *declarator)
{
struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
ret->specs = specs;
@@ -6909,25 +6697,174 @@ build_id_declarator (tree ident)
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
- TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
- to apply to the pointer type, represented as identifiers, possible mixed
- with attributes. */
+ TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes
+ to apply to the pointer type. */
struct c_declarator *
-make_pointer_declarator (tree type_quals_attrs, struct c_declarator *target)
+make_pointer_declarator (struct c_declspecs *type_quals_attrs,
+ struct c_declarator *target)
{
- tree quals, attrs;
+ tree attrs;
struct c_declarator *itarget = target;
struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
- split_specs_attrs (type_quals_attrs, &quals, &attrs);
- if (attrs != NULL_TREE)
- itarget = build_attrs_declarator (attrs, target);
+ if (type_quals_attrs)
+ {
+ attrs = type_quals_attrs->attrs;
+ type_quals_attrs->attrs = NULL_TREE;
+ if (attrs != NULL_TREE)
+ itarget = build_attrs_declarator (attrs, target);
+ }
ret->kind = cdk_pointer;
ret->declarator = itarget;
- ret->u.pointer_quals = quals;
+ ret->u.pointer_quals = type_quals_attrs;
+ return ret;
+}
+
+/* Return a pointer to a structure for an empty list of declaration
+ specifiers. */
+
+struct c_declspecs *
+build_null_declspecs (void)
+{
+ struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+ ret->type = 0;
+ ret->typedef_decl = 0;
+ ret->decl_attr = 0;
+ ret->attrs = 0;
+ ret->specbits = 0;
+ ret->non_sc_seen_p = false;
+ ret->deprecated_p = false;
+ ret->explicit_int_p = false;
+ ret->explicit_char_p = false;
+ ret->long_long_p = false;
return ret;
}
+/* Add the type qualifier QUAL to the declaration specifiers SPECS,
+ returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_qual (struct c_declspecs *specs, tree qual)
+{
+ enum rid i;
+ specs->non_sc_seen_p = true;
+ gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (qual));
+ i = C_RID_CODE (qual);
+ gcc_assert (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT);
+ if ((specs->specbits & (1 << (int) i)) && pedantic && !flag_isoc99)
+ pedwarn ("duplicate %qs", IDENTIFIER_POINTER (qual));
+ specs->specbits |= 1 << (int) i;
+ return specs;
+}
+
+/* Add the type specifier TYPE to the declaration specifiers SPECS,
+ returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_type (struct c_declspecs *specs, tree type)
+{
+ specs->non_sc_seen_p = true;
+ if (TREE_DEPRECATED (type))
+ specs->deprecated_p = true;
+ if (type == ridpointers[(int) RID_INT])
+ specs->explicit_int_p = true;
+ if (type == ridpointers[(int) RID_CHAR])
+ specs->explicit_char_p = true;
+
+ if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type))
+ {
+ enum rid i = C_RID_CODE (type);
+ if ((int) i <= (int) RID_LAST_MODIFIER)
+ {
+ if (i == RID_LONG && (specs->specbits & (1 << (int) RID_LONG)))
+ {
+ if (specs->long_long_p)
+ error ("%<long long long%> is too long for GCC");
+ else
+ {
+ if (pedantic && !flag_isoc99 && !in_system_header
+ && warn_long_long)
+ pedwarn ("ISO C90 does not support %<long long%>");
+ specs->long_long_p = 1;
+ }
+ }
+ else if (specs->specbits & (1 << (int) i))
+ error ("duplicate %qs", IDENTIFIER_POINTER (type));
+
+ specs->specbits |= 1 << (int) i;
+ return specs;
+ }
+ }
+ if (specs->type)
+ error ("two or more data types in declaration specifiers");
+ /* Actual typedefs come to us as TYPE_DECL nodes. */
+ else if (TREE_CODE (type) == TYPE_DECL)
+ {
+ if (TREE_TYPE (type) == error_mark_node)
+ ; /* Allow the type to default to int to avoid cascading errors. */
+ else
+ {
+ specs->type = TREE_TYPE (type);
+ specs->decl_attr = DECL_ATTRIBUTES (type);
+ specs->typedef_decl = type;
+ }
+ }
+ /* Built-in types come as identifiers. */
+ else if (TREE_CODE (type) == IDENTIFIER_NODE)
+ {
+ tree t = lookup_name (type);
+ if (!t || TREE_CODE (t) != TYPE_DECL)
+ error ("%qs fails to be a typedef or built in type",
+ IDENTIFIER_POINTER (type));
+ else if (TREE_TYPE (t) == error_mark_node)
+ ;
+ else
+ specs->type = TREE_TYPE (t);
+ }
+ else if (TREE_CODE (type) != ERROR_MARK)
+ specs->type = type;
+
+ return specs;
+}
+
+/* Add the storage class specifier or function specifier SCSPEC to the
+ declaration specifiers SPECS, returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
+{
+ enum rid i;
+ gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (scspec));
+ i = C_RID_CODE (scspec);
+ if (extra_warnings && specs->non_sc_seen_p)
+ warning ("%qs is not at beginning of declaration",
+ IDENTIFIER_POINTER (scspec));
+ if (specs->specbits & (1 << (int) i))
+ error ("duplicate %qs", IDENTIFIER_POINTER (scspec));
+ /* Diagnose "__thread extern" and "__thread static". */
+ if (specs->specbits & (1 << (int) RID_THREAD))
+ {
+ if (i == RID_EXTERN)
+ error ("%<__thread%> before %<extern%>");
+ else if (i == RID_STATIC)
+ error ("%<__thread%> before %<static%>");
+ }
+ specs->specbits |= 1 << (int) i;
+ return specs;
+}
+
+/* Add the attributes ATTRS to the declaration specifiers SPECS,
+ returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+{
+ specs->attrs = chainon (attrs, specs->attrs);
+ return specs;
+}
+
/* Synthesize a function which calls all the global ctors or global
dtors in this file. This is only used for targets which do not
support .ctors/.dtors sections. FIXME: Migrate into cgraph. */