diff options
author | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-09-09 01:25:48 +0000 |
---|---|---|
committer | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-09-09 01:25:48 +0000 |
commit | 9553111d52cbe9f5dcfcc65e2a251d9e7803e521 (patch) | |
tree | 9281b8a84cb7f58197f54b2a640390953626fb55 /gcc/c-decl.c | |
parent | ac206aff0574a7d02a44278c0ab08420efa6fca8 (diff) | |
download | gcc-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.c | 591 |
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. */ |