From: Joseph Myers Date: Fri, 17 Sep 2004 18:18:05 +0000 (+0100) Subject: c-tree.h (enum c_typespec_keyword): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=98c3a782774396163f6bcacf91515131e3abe375;p=gcc.git c-tree.h (enum c_typespec_keyword): New. * c-tree.h (enum c_typespec_keyword): New. (struct c_declspecs): Adjust description of "type". Remove specbits, explicit_int_p and explicit_char_p. Rename typedef_signed_p to explicit_signed_p. Add default_int_p, long_p, short_p, signed_p, unsigned_p and complex_p. (finish_declspecs): New. * c-parse.in (datadef, datadecl, setspecs, decl, component_decl, typename): Call finish_declspecs. * c-decl.c (finish_declspecs): New. (declspecs_add_type): Check for combinations which cannot occur in valid specifier lists. Update comments. (shadow_tag_warned): Remove checks done in finish_declspecs. Don't report useless type name if type defaulted to int. (grokdeclarator): Remove checks and actions done in finish_declspecs. Don't allow for type being NULL. Update for datastructures changes. Initialize decl_attr. (build_null_declspecs, quals_from_declspecs): Update for datastructures changes. testsuite: * gcc.dg/declspec-4.c, gcc.dg/declspec-5.c, gcc.dg/declspec-6.c: Update expected messages. * gcc.dg/declspec-13.c: New test. From-SVN: r87660 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4fea29d23d..04eec4c48d8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2004-09-17 Joseph S. Myers + + * c-tree.h (enum c_typespec_keyword): New. + (struct c_declspecs): Adjust description of "type". Remove + specbits, explicit_int_p and explicit_char_p. Rename + typedef_signed_p to explicit_signed_p. Add default_int_p, long_p, + short_p, signed_p, unsigned_p and complex_p. + (finish_declspecs): New. + * c-parse.in (datadef, datadecl, setspecs, decl, component_decl, + typename): Call finish_declspecs. + * c-decl.c (finish_declspecs): New. + (declspecs_add_type): Check for combinations which cannot occur in + valid specifier lists. Update comments. + (shadow_tag_warned): Remove checks done in finish_declspecs. + Don't report useless type name if type defaulted to int. + (grokdeclarator): Remove checks and actions done in + finish_declspecs. Don't allow for type being NULL. Update for + datastructures changes. Initialize decl_attr. + (build_null_declspecs, quals_from_declspecs): Update for + datastructures changes. + 2004-09-17 Sylvain Pion * doc/extend.texi: Fix duplicated word. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index b29a152dacc..e1e8d4d8f0d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2681,7 +2681,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) pending_invalid_xref = 0; - if (declspecs->type && !declspecs->typedef_p) + if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p) { tree value = declspecs->type; enum tree_code code = TREE_CODE (value); @@ -2730,17 +2730,6 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) 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 (declspecs->inline_p) { error ("% in empty declaration"); @@ -2779,12 +2768,6 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 2; } - if (!warned && !in_system_header && declspecs->specbits) - { - warning ("useless keyword or type name in empty declaration"); - warned = 2; - } - if (warned != 1) { if (!found_tag) @@ -2805,14 +2788,17 @@ quals_from_declspecs (const struct c_declspecs *specs) | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)); gcc_assert (!specs->type && !specs->decl_attr - && !specs->specbits + && specs->typespec_word == cts_none && specs->storage_class == csc_none && !specs->typedef_p - && !specs->typedef_signed_p + && !specs->explicit_signed_p && !specs->deprecated_p - && !specs->explicit_int_p - && !specs->explicit_char_p + && !specs->long_p && !specs->long_long_p + && !specs->short_p + && !specs->signed_p + && !specs->unsigned_p + && !specs->complex_p && !specs->inline_p && !specs->thread_p); return quals; @@ -3673,7 +3659,6 @@ grokdeclarator (const struct c_declarator *declarator, struct c_declspecs *declspecs, enum decl_context decl_context, bool initialized, tree *width) { - int specbits = declspecs->specbits; tree type = declspecs->type; bool threadp = declspecs->thread_p; enum c_storage_class storage_class = declspecs->storage_class; @@ -3681,13 +3666,12 @@ grokdeclarator (const struct c_declarator *declarator, int restrictp; int volatilep; int type_quals = TYPE_UNQUALIFIED; - int defaulted_int = 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 decl_attr = declspecs->decl_attr; int array_ptr_quals = TYPE_UNQUALIFIED; tree array_ptr_attrs = NULL_TREE; int array_parm_static = 0; @@ -3749,182 +3733,28 @@ grokdeclarator (const struct c_declarator *declarator, warn_deprecated_use (declspecs->type); typedef_type = type; - if (type) - size_varies = C_TYPE_VARIABLE_SIZE (type); - - /* No type at all: default to `int', and set DEFAULTED_INT - because it was not a user-defined typedef. */ + size_varies = C_TYPE_VARIABLE_SIZE (type); - if (type == 0) - { - if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_SIGNED) - | (1 << (int) RID_UNSIGNED) - | (1 << (int) RID_COMPLEX)))) - /* Don't warn about typedef foo = bar. */ - && ! (storage_class == csc_typedef && initialized) - && ! in_system_header) - { - /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type - and this is a function, or if -Wimplicit; prefer the former - warning since it is more explicit. */ - if ((warn_implicit_int || warn_return_type || flag_isoc99) - && funcdef_flag) - warn_about_return_type = 1; - else if (warn_implicit_int || flag_isoc99) - pedwarn_c99 ("type defaults to % in declaration of %qs", - name); - } + /* Diagnose defaulting to "int". */ - defaulted_int = 1; - type = integer_type_node; - } - - /* Now process the modifiers that were specified - and check for invalid combinations. */ - - /* Long double is a special combination. */ - - if ((specbits & 1 << (int) RID_LONG) && ! declspecs->long_long_p - && TYPE_MAIN_VARIANT (type) == double_type_node) + if (declspecs->default_int_p && !in_system_header) { - specbits &= ~(1 << (int) RID_LONG); - type = long_double_type_node; + /* Issue a warning if this is an ISO C 99 program or if + -Wreturn-type and this is a function, or if -Wimplicit; + prefer the former warning since it is more explicit. */ + if ((warn_implicit_int || warn_return_type || flag_isoc99) + && funcdef_flag) + warn_about_return_type = 1; + else if (warn_implicit_int || flag_isoc99) + pedwarn_c99 ("type defaults to % in declaration of %qs", name); } - /* Check all other uses of type modifiers. */ - - if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED))) - { - int ok = 0; - - if ((specbits & 1 << (int) RID_LONG) - && (specbits & 1 << (int) RID_SHORT)) - error ("both long and short specified for %qs", name); - else if (((specbits & 1 << (int) RID_LONG) - || (specbits & 1 << (int) RID_SHORT)) - && declspecs->explicit_char_p) - error ("long or short specified with char for %qs", name); - else if (((specbits & 1 << (int) RID_LONG) - || (specbits & 1 << (int) RID_SHORT)) - && TREE_CODE (type) == REAL_TYPE) - { - static int already = 0; - - error ("long or short specified with floating type for %qs", name); - if (! already && ! pedantic) - { - error ("the only valid combination is %"); - already = 1; - } - } - else if ((specbits & 1 << (int) RID_SIGNED) - && (specbits & 1 << (int) RID_UNSIGNED)) - error ("both signed and unsigned specified for %qs", name); - else if (TREE_CODE (type) != INTEGER_TYPE) - error ("long, short, signed or unsigned invalid for %qs", name); - else - { - ok = 1; - if (!declspecs->explicit_int_p && !defaulted_int - && !declspecs->explicit_char_p) - { - error ("long, short, signed or unsigned used invalidly for %qs", - name); - ok = 0; - } - } - - /* Discard the type modifiers if they are invalid. */ - if (! ok) - { - specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)); - declspecs->long_long_p = 0; - } - } - - if ((specbits & (1 << (int) RID_COMPLEX)) - && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) - { - error ("complex invalid for %qs", name); - specbits &= ~(1 << (int) RID_COMPLEX); - } - - /* Decide whether an integer type is signed or not. - Optionally treat bit-fields as signed by default. */ - if (specbits & 1 << (int) RID_UNSIGNED - || (bitfield && ! flag_signed_bitfields - && (declspecs->explicit_int_p || defaulted_int - || declspecs->explicit_char_p - /* A typedef for plain `int' without `signed' - can be controlled just like plain `int'. */ - || !declspecs->typedef_signed_p) - && TREE_CODE (type) != ENUMERAL_TYPE - && !(specbits & 1 << (int) RID_SIGNED))) - { - if (declspecs->long_long_p) - type = long_long_unsigned_type_node; - else if (specbits & 1 << (int) RID_LONG) - type = long_unsigned_type_node; - else if (specbits & 1 << (int) RID_SHORT) - type = short_unsigned_type_node; - else if (type == char_type_node) - type = unsigned_char_type_node; - else if (declspecs->typedef_p) - type = c_common_unsigned_type (type); - else - type = unsigned_type_node; - } - else if ((specbits & 1 << (int) RID_SIGNED) - && type == char_type_node) - type = signed_char_type_node; - else if (declspecs->long_long_p) - type = long_long_integer_type_node; - else if (specbits & 1 << (int) RID_LONG) - type = long_integer_type_node; - else if (specbits & 1 << (int) RID_SHORT) - type = short_integer_type_node; - - if (specbits & 1 << (int) RID_COMPLEX) - { - if (pedantic && !flag_isoc99) - pedwarn ("ISO C90 does not support complex types"); - /* If we just have "complex", it is equivalent to - "complex double", but if any modifiers at all are specified it is - the complex form of TYPE. E.g, "complex short" is - "complex short int". */ - - if (defaulted_int && ! declspecs->long_long_p - && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_SIGNED) - | (1 << (int) RID_UNSIGNED)))) - { - if (pedantic) - pedwarn ("ISO C does not support plain % meaning " - "%"); - type = complex_double_type_node; - } - else if (type == integer_type_node) - { - if (pedantic) - pedwarn ("ISO C does not support complex integer types"); - type = complex_integer_type_node; - } - else if (type == float_type_node) - type = complex_float_type_node; - else if (type == double_type_node) - type = complex_double_type_node; - else if (type == long_double_type_node) - type = complex_long_double_type_node; - else - { - if (pedantic) - pedwarn ("ISO C does not support complex integer types"); - type = build_complex_type (type); - } - } + /* Adjust the type if a bit-field is being declared, + -funsigned-bitfields applied and the type is not explicitly + "signed". */ + if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p + && TREE_CODE (type) == INTEGER_TYPE) + type = c_common_unsigned_type (type); /* Check the type and width of a bit-field. */ if (bitfield) @@ -4397,8 +4227,7 @@ grokdeclarator (const struct c_declarator *declarator, if (type_quals) type = c_build_qualified_type (type, type_quals); decl = build_decl (TYPE_DECL, declarator->u.id, type); - if ((specbits & (1 << (int) RID_SIGNED)) - || declspecs->typedef_signed_p) + if (declspecs->explicit_signed_p) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; decl_attributes (&decl, returned_attrs, 0); if (declspecs->inline_p) @@ -4602,7 +4431,7 @@ grokdeclarator (const struct c_declarator *declarator, if (funcdef_flag) current_function_arg_info = arg_info; - if (defaulted_int) + if (declspecs->default_int_p) C_FUNCTION_IMPLICIT_INT (decl) = 1; /* Record presence of `inline', if it is reasonable. */ @@ -6765,15 +6594,19 @@ build_null_declspecs (void) ret->type = 0; ret->decl_attr = 0; ret->attrs = 0; - ret->specbits = 0; + ret->typespec_word = cts_none; ret->storage_class = csc_none; ret->non_sc_seen_p = false; ret->typedef_p = false; - ret->typedef_signed_p = false; + ret->explicit_signed_p = false; ret->deprecated_p = false; - ret->explicit_int_p = false; - ret->explicit_char_p = false; + ret->default_int_p = false; + ret->long_p = false; ret->long_long_p = false; + ret->short_p = false; + ret->signed_p = false; + ret->unsigned_p = false; + ret->complex_p = false; ret->inline_p = false; ret->thread_p = false; ret->const_p = false; @@ -6825,38 +6658,254 @@ 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; + /* Handle type specifier keywords. */ if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type)) { enum rid i = C_RID_CODE (type); + if (specs->type) + { + error ("two or more data types in declaration specifiers"); + return specs; + } if ((int) i <= (int) RID_LAST_MODIFIER) { - if (i == RID_LONG && (specs->specbits & (1 << (int) RID_LONG))) + /* "long", "short", "signed", "unsigned" or "_Complex". */ + bool dupe = false; + switch (i) { + case RID_LONG: if (specs->long_long_p) - error ("% is too long for GCC"); - else { + error ("% is too long for GCC"); + break; + } + if (specs->long_p) + { + if (specs->typespec_word == cts_double) + { + error ("both % and % in " + "declaration specifiers"); + break; + } if (pedantic && !flag_isoc99 && !in_system_header && warn_long_long) pedwarn ("ISO C90 does not support %"); specs->long_long_p = 1; + break; } + if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_char) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else + specs->long_p = true; + break; + case RID_SHORT: + dupe = specs->short_p; + if (specs->long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_char) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_double) + error ("both % and % in " + "declaration specifiers"); + else + specs->short_p = true; + break; + case RID_SIGNED: + dupe = specs->signed_p; + if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_double) + error ("both % and % in " + "declaration specifiers"); + else + specs->signed_p = true; + break; + case RID_UNSIGNED: + dupe = specs->unsigned_p; + if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_float) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_double) + error ("both % and % in " + "declaration specifiers"); + else + specs->unsigned_p = true; + break; + case RID_COMPLEX: + dupe = specs->complex_p; + if (pedantic && !flag_isoc99) + pedwarn ("ISO C90 does not support complex types"); + if (specs->typespec_word == cts_void) + error ("both % and % in " + "declaration specifiers"); + else if (specs->typespec_word == cts_bool) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else + specs->complex_p = true; + break; + default: + gcc_unreachable (); } - else if (specs->specbits & (1 << (int) i)) + + if (dupe) error ("duplicate %qs", IDENTIFIER_POINTER (type)); - specs->specbits |= 1 << (int) i; return specs; } + else + { + /* "void", "_Bool", "char", "int", "float" or "double". */ + if (specs->typespec_word != cts_none) + { + error ("two or more data types in declaration specifiers"); + return specs; + } + switch (i) + { + case RID_VOID: + if (specs->long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->complex_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_void; + return specs; + case RID_BOOL: + if (specs->long_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else if (specs->complex_p) + error ("both % and %<_Bool%> in " + "declaration specifiers"); + else + specs->typespec_word = cts_bool; + return specs; + case RID_CHAR: + if (specs->long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_char; + return specs; + case RID_INT: + specs->typespec_word = cts_int; + return specs; + case RID_FLOAT: + if (specs->long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_float; + return specs; + case RID_DOUBLE: + if (specs->long_long_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->short_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->signed_p) + error ("both % and % in " + "declaration specifiers"); + else if (specs->unsigned_p) + error ("both % and % in " + "declaration specifiers"); + else + specs->typespec_word = cts_double; + return specs; + default: + /* ObjC reserved word "id", handled below. */ + break; + } + } } - if (specs->type) + + /* Now we have a typedef (a TYPE_DECL node), an identifier (some + form of ObjC type, cases such as "int" and "long" being handled + above), a TYPE (struct, union, enum and typeof specifiers) or an + ERROR_MARK. In none of these cases may there have previously + been any type specifiers. */ + if (specs->type || specs->typespec_word != cts_none + || specs->long_p || specs->short_p || specs->signed_p + || specs->unsigned_p || specs->complex_p) 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) @@ -6866,10 +6915,9 @@ declspecs_add_type (struct c_declspecs *specs, tree type) specs->type = TREE_TYPE (type); specs->decl_attr = DECL_ATTRIBUTES (type); specs->typedef_p = true; - specs->typedef_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type); + specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type); } } - /* Built-in types come as identifiers. */ else if (TREE_CODE (type) == IDENTIFIER_NODE) { tree t = lookup_name (type); @@ -6981,6 +7029,146 @@ declspecs_add_attrs (struct c_declspecs *specs, tree attrs) return specs; } +/* Combine "long", "short", "signed", "unsigned" and "_Complex" type + specifiers with any other type specifier to determine the resulting + type. This is where ISO C checks on complex types are made, since + "_Complex long" is a prefix of the valid ISO C type "_Complex long + double". */ + +struct c_declspecs * +finish_declspecs (struct c_declspecs *specs) +{ + /* If a type was specified as a whole, we have no modifiers and are + done. */ + if (specs->type != NULL_TREE) + { + gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p + && !specs->complex_p); + return specs; + } + + /* If none of "void", "_Bool", "char", "int", "float" or "double" + has been specified, treat it as "int" unless "_Complex" is + present and there are no other specifiers. If we just have + "_Complex", it is equivalent to "_Complex double", but e.g. + "_Complex short" is equivalent to "_Complex short int". */ + if (specs->typespec_word == cts_none) + { + if (specs->long_p || specs->short_p + || specs->signed_p || specs->unsigned_p) + { + specs->typespec_word = cts_int; + } + else if (specs->complex_p) + { + specs->typespec_word = cts_double; + if (pedantic) + pedwarn ("ISO C does not support plain % meaning " + "%"); + } + else + { + specs->typespec_word = cts_int; + specs->default_int_p = true; + /* We don't diagnose this here because grokdeclarator will + give more specific diagnostics according to whether it is + a function definition. */ + } + } + + /* If "signed" was specified, record this to distinguish "int" and + "signed int" in the case of a bit-field with + -funsigned-bitfields. */ + specs->explicit_signed_p = specs->signed_p; + + /* Now compute the actual type. */ + switch (specs->typespec_word) + { + case cts_void: + gcc_assert (!specs->long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p + && !specs->complex_p); + specs->type = void_type_node; + break; + case cts_bool: + gcc_assert (!specs->long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p + && !specs->complex_p); + specs->type = boolean_type_node; + break; + case cts_char: + gcc_assert (!specs->long_p && !specs->short_p); + gcc_assert (!(specs->signed_p && specs->unsigned_p)); + if (specs->signed_p) + specs->type = signed_char_type_node; + else if (specs->unsigned_p) + specs->type = unsigned_char_type_node; + else + specs->type = char_type_node; + if (specs->complex_p) + { + if (pedantic) + pedwarn ("ISO C does not support complex integer types"); + specs->type = build_complex_type (specs->type); + } + break; + case cts_int: + gcc_assert (!(specs->long_p && specs->short_p)); + gcc_assert (!(specs->signed_p && specs->unsigned_p)); + if (specs->long_long_p) + specs->type = (specs->unsigned_p + ? long_long_unsigned_type_node + : long_long_integer_type_node); + else if (specs->long_p) + specs->type = (specs->unsigned_p + ? long_unsigned_type_node + : long_integer_type_node); + else if (specs->short_p) + specs->type = (specs->unsigned_p + ? short_unsigned_type_node + : short_integer_type_node); + else + specs->type = (specs->unsigned_p + ? unsigned_type_node + : integer_type_node); + if (specs->complex_p) + { + if (pedantic) + pedwarn ("ISO C does not support complex integer types"); + specs->type = build_complex_type (specs->type); + } + break; + case cts_float: + gcc_assert (!specs->long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p); + specs->type = (specs->complex_p + ? complex_float_type_node + : float_type_node); + break; + case cts_double: + gcc_assert (!specs->long_long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p); + if (specs->long_p) + { + specs->type = (specs->complex_p + ? complex_long_double_type_node + : long_double_type_node); + } + else + { + specs->type = (specs->complex_p + ? complex_double_type_node + : double_type_node); + } + break; + default: + gcc_unreachable (); + } + + 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. */ diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 20ed784f6f3..6fcf66739f5 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -420,7 +420,7 @@ datadef: | declspecs_ts setspecs initdecls ';' { POP_DECLSPEC_STACK; } | declspecs ';' - { shadow_tag ($1); } + { shadow_tag (finish_declspecs ($1)); } | error ';' | error '}' | ';' @@ -835,7 +835,7 @@ datadecl: | declspecs_nots_nosa setspecs notype_initdecls ';' { POP_DECLSPEC_STACK; } | declspecs_ts_nosa ';' - { shadow_tag_warned ($1, 1); + { shadow_tag_warned (finish_declspecs ($1), 1); pedwarn ("empty declaration"); } | declspecs_nots_nosa ';' { pedwarn ("empty declaration"); } @@ -868,6 +868,7 @@ setspecs: /* empty */ prefix_attributes = NULL_TREE; current_declspecs = build_null_declspecs (); } + current_declspecs = finish_declspecs (current_declspecs); all_prefix_attributes = prefix_attributes; } ; @@ -888,7 +889,7 @@ decl: | declspecs_nots setspecs notype_nested_function { POP_DECLSPEC_STACK; } | declspecs ';' - { shadow_tag ($1); } + { shadow_tag (finish_declspecs ($1)); } | extension decl { RESTORE_EXT_FLAGS ($1); } ; @@ -1745,7 +1746,7 @@ component_decl: | declspecs_nosc_nots { if (pedantic) pedwarn ("ISO C forbids member declarations with no members"); - shadow_tag_warned ($1, pedantic); + shadow_tag_warned (finish_declspecs ($1), pedantic); $$ = NULL_TREE; } | error { $$ = NULL_TREE; } @@ -1823,7 +1824,7 @@ enumerator: typename: declspecs_nosc { pending_xref_error (); - $$ = $1; } + $$ = finish_declspecs ($1); } absdcl { $$ = XOBNEW (&parser_obstack, struct c_type_name); $$->specs = $2; diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 5d1ec30425c..76981a7ea7c 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -141,10 +141,24 @@ enum c_storage_class { csc_typedef }; +/* A type specifier keyword "void", "_Bool", "char", "int", "float", + "double", or none of these. */ +enum c_typespec_keyword { + cts_none, + cts_void, + cts_bool, + cts_char, + cts_int, + cts_float, + cts_double +}; + /* A sequence of declaration specifiers in C. */ struct c_declspecs { - /* The type specified, not reflecting modifiers such as "short" and - "unsigned", or NULL_TREE if none. */ + /* The type specified, if a single type specifier such as a struct, + union or enum specifier, typedef name or typeof specifies the + whole type, or NULL_TREE if none or a keyword such as "void" or + "char" is used. Does not include qualifiers. */ tree type; /* The attributes from a typedef decl. */ tree decl_attr; @@ -152,8 +166,9 @@ struct c_declspecs { NULL; attributes (possibly from multiple lists) will be passed separately. */ tree attrs; - /* The modifier bits present. */ - int specbits; + /* Any type specifier keyword used such as "int", not reflecting + modifiers such as "short", or cts_none if none. */ + enum c_typespec_keyword typespec_word; /* The storage class specifier, or csc_none if none. */ enum c_storage_class storage_class; /* Whether something other than a storage class specifier or @@ -165,17 +180,26 @@ struct c_declspecs { BOOL_BITFIELD non_sc_seen_p : 1; /* Whether the type is specified by a typedef. */ BOOL_BITFIELD typedef_p : 1; - /* Whether the type is specified by a typedef whose type is - explicitly "signed". */ - BOOL_BITFIELD typedef_signed_p : 1; + /* Whether the type is explicitly "signed" or specified by a typedef + whose type is explicitly "signed". */ + BOOL_BITFIELD explicit_signed_p : 1; /* Whether the specifiers include a deprecated typedef. */ BOOL_BITFIELD deprecated_p : 1; - /* Whether "int" was explicitly specified. */ - BOOL_BITFIELD explicit_int_p : 1; - /* Whether "char" was explicitly specified. */ - BOOL_BITFIELD explicit_char_p : 1; + /* Whether the type defaulted to "int" because there were no type + specifiers. */ + BOOL_BITFIELD default_int_p; + /* Whether "long" was specified. */ + BOOL_BITFIELD long_p : 1; /* Whether "long" was specified more than once. */ BOOL_BITFIELD long_long_p : 1; + /* Whether "short" was specified. */ + BOOL_BITFIELD short_p : 1; + /* Whether "signed" was specified. */ + BOOL_BITFIELD signed_p : 1; + /* Whether "unsigned" was specified. */ + BOOL_BITFIELD unsigned_p : 1; + /* Whether "complex" was specified. */ + BOOL_BITFIELD complex_p : 1; /* Whether "inline" was specified. */ BOOL_BITFIELD inline_p : 1; /* Whether "__thread" was specified. */ @@ -362,6 +386,7 @@ extern struct c_declspecs *declspecs_add_qual (struct c_declspecs *, tree); extern struct c_declspecs *declspecs_add_type (struct c_declspecs *, tree); extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree); extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree); +extern struct c_declspecs *finish_declspecs (struct c_declspecs *); /* in c-objc-common.c */ extern int c_disregard_inline_limits (tree); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f8fe5af7083..0a27ca6c57e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-09-17 Joseph S. Myers + + * gcc.dg/declspec-4.c, gcc.dg/declspec-5.c, gcc.dg/declspec-6.c: + Update expected messages. + * gcc.dg/declspec-13.c: New test. + 2004-09-17 David Edelsohn * gcc.dg/darwin-longlong.c: XFAIL on AIX and SPE. diff --git a/gcc/testsuite/gcc.dg/declspec-13.c b/gcc/testsuite/gcc.dg/declspec-13.c new file mode 100644 index 00000000000..317252064e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/declspec-13.c @@ -0,0 +1,86 @@ +/* Test declaration specifiers. Test messages for bad type + specifiers. */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu89 -pedantic" } */ + +/* typeof should act much like typedef, so the following are + invalid. */ +typeof(double) long x0; /* { dg-error "error: two or more data types in declaration specifiers" } */ +typeof(double) _Complex x1; /* { dg-error "error: two or more data types in declaration specifiers" } */ + +/* The following is erroneous, and used to get a bogus message about + complex integer types. */ +typedef double D; +D _Complex x2; /* { dg-error "error: two or more data types in declaration specifiers" } */ + +/* The following empty declarations should have problems in their type + specifiers diagnosed, not just the general problem that they are + empty declarations. */ +long short; /* { dg-error "error: both 'long' and 'short' in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 20 } */ +_Complex double; /* { dg-warning "warning: ISO C90 does not support complex types" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 22 } */ +_Complex; /* { dg-warning "warning: ISO C90 does not support complex types" } */ +/* { dg-warning "warning: ISO C does not support plain 'complex' meaning 'double complex'" "ISO C" { target *-*-* } 24 } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 24 } */ +_Complex int; /* { dg-warning "warning: ISO C90 does not support complex types" } */ +/* { dg-warning "warning: ISO C does not support complex integer types" "ISO C" { target *-*-* } 27 } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 27 } */ + +/* Specific messages for each invalid combination. (That some message + is given when appropriate for a larger collection of combinations + of type specifiers is tested in *typespec*.c.) */ + +long double long x3; /* { dg-error "both 'long long' and 'double' in declaration specifiers" } */ +short long x4; /* { dg-error "both 'long' and 'short' in declaration specifiers" } */ +void long x5; /* { dg-error "both 'long' and 'void' in declaration specifiers" } */ +_Bool long x6; /* { dg-error "both 'long' and '_Bool' in declaration specifiers" } */ +char long x7; /* { dg-error "both 'long' and 'char' in declaration specifiers" } */ +float long x8; /* { dg-error "both 'long' and 'float' in declaration specifiers" } */ +long short x9; /* { dg-error "both 'long' and 'short' in declaration specifiers" } */ +void short x10; /* { dg-error "both 'short' and 'void' in declaration specifiers" } */ +_Bool short x11; /* { dg-error "both 'short' and '_Bool' in declaration specifiers" } */ +char short x12; /* { dg-error "both 'short' and 'char' in declaration specifiers" } */ +float short x13; /* { dg-error "both 'short' and 'float' in declaration specifiers" } */ +double short x14; /* { dg-error "both 'short' and 'double' in declaration specifiers" } */ +unsigned signed x15; /* { dg-error "both 'signed' and 'unsigned' in declaration specifiers" } */ +void signed x16; /* { dg-error "both 'signed' and 'void' in declaration specifiers" } */ +_Bool signed x17; /* { dg-error "both 'signed' and '_Bool' in declaration specifiers" } */ +float signed x18; /* { dg-error "both 'signed' and 'float' in declaration specifiers" } */ +double signed x19; /* { dg-error "both 'signed' and 'double' in declaration specifiers" } */ +signed unsigned x20; /* { dg-error "both 'signed' and 'unsigned' in declaration specifiers" } */ +void unsigned x21; /* { dg-error "both 'unsigned' and 'void' in declaration specifiers" } */ +_Bool unsigned x22; /* { dg-error "both 'unsigned' and '_Bool' in declaration specifiers" } */ +float unsigned x23; /* { dg-error "both 'unsigned' and 'float' in declaration specifiers" } */ +double unsigned x24; /* { dg-error "both 'unsigned' and 'double' in declaration specifiers" } */ +void _Complex x25; /* { dg-error "both 'complex' and 'void' in declaration specifiers" } */ +/* { dg-warning "warning: ISO C90 does not support complex types" "C90" { target *-*-* } 57 } */ +_Bool _Complex x26; /* { dg-error "both 'complex' and '_Bool' in declaration specifiers" } */ +/* { dg-warning "warning: ISO C90 does not support complex types" "C90" { target *-*-* } 59 } */ + +long void x27; /* { dg-error "both 'long' and 'void' in declaration specifiers" } */ +short void x28; /* { dg-error "both 'short' and 'void' in declaration specifiers" } */ +signed void x29; /* { dg-error "both 'signed' and 'void' in declaration specifiers" } */ +unsigned void x30; /* { dg-error "both 'unsigned' and 'void' in declaration specifiers" } */ +_Complex void x31; /* { dg-error "both 'complex' and 'void' in declaration specifiers" } */ +/* { dg-warning "warning: ISO C90 does not support complex types" "C90" { target *-*-* } 66 } */ +/* { dg-warning "warning: ISO C does not support plain 'complex' meaning 'double complex'" "complex" { target *-*-* } 66 } */ +long _Bool x32; /* { dg-error "both 'long' and '_Bool' in declaration specifiers" } */ +short _Bool x33; /* { dg-error "both 'short' and '_Bool' in declaration specifiers" } */ +signed _Bool x34; /* { dg-error "both 'signed' and '_Bool' in declaration specifiers" } */ +unsigned _Bool x35; /* { dg-error "both 'unsigned' and '_Bool' in declaration specifiers" } */ +_Complex _Bool x36; /* { dg-error "both 'complex' and '_Bool' in declaration specifiers" } */ +/* { dg-warning "warning: ISO C90 does not support complex types" "C90" { target *-*-* } 73 } */ +/* { dg-warning "warning: ISO C does not support plain 'complex' meaning 'double complex'" "complex" { target *-*-* } 73 } */ +long char x37; /* { dg-error "both 'long' and 'char' in declaration specifiers" } */ +short char x38; /* { dg-error "both 'short' and 'char' in declaration specifiers" } */ +long float x39; /* { dg-error "both 'long' and 'float' in declaration specifiers" } */ +short float x40; /* { dg-error "both 'short' and 'float' in declaration specifiers" } */ +signed float x41; /* { dg-error "both 'signed' and 'float' in declaration specifiers" } */ +unsigned float x42; /* { dg-error "both 'unsigned' and 'float' in declaration specifiers" } */ +long long double x43; /* { dg-error "both 'long long' and 'double' in declaration specifiers" } */ +/* { dg-warning "warning: ISO C90 does not support 'long long'" "C90" { target *-*-* } 82 } */ +short double x44; /* { dg-error "both 'short' and 'double' in declaration specifiers" } */ +signed double x45; /* { dg-error "both 'signed' and 'double' in declaration specifiers" } */ +unsigned double x46; /* { dg-error "both 'unsigned' and 'double' in declaration specifiers" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-4.c b/gcc/testsuite/gcc.dg/declspec-4.c index fbc6c3667ca..b8eb9d0f99c 100644 --- a/gcc/testsuite/gcc.dg/declspec-4.c +++ b/gcc/testsuite/gcc.dg/declspec-4.c @@ -19,23 +19,25 @@ enum e1 { E1 }; /* Not declaring anything (pedwarns). */ struct { int a; }; /* { dg-warning "warning: unnamed struct/union that defines no instances" } */ int; /* { dg-warning "warning: useless type name in empty declaration" } */ -long; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ -/* { dg-warning "warning: empty declaration" "long" { target *-*-* } 22 } */ +long; /* { dg-warning "warning: useless type name in empty declaration" } */ T; /* { dg-warning "warning: useless type name in empty declaration" } */ static const; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ -/* { dg-warning "warning: empty declaration" "long" { target *-*-* } 25 } */ +/* { dg-warning "warning: empty declaration" "static const" { target *-*-* } 24 } */ union { long b; }; /* { dg-warning "warning: unnamed struct/union that defines no instances" } */ /* Multiple type names (errors). */ struct s1 int; /* { dg-error "error: two or more data types in declaration specifiers" } */ char union u1; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-warning "warning: useless type name in empty declaration" "char union" { target *-*-* } 31 } */ +/* { dg-warning "warning: useless type name in empty declaration" "char union" { target *-*-* } 30 } */ double enum { E2 }; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-warning "warning: useless type name in empty declaration" "double enum" { target *-*-* } 33 } */ +/* { dg-warning "warning: useless type name in empty declaration" "double enum" { target *-*-* } 32 } */ T struct s2; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-warning "warning: useless type name in empty declaration" "T struct" { target *-*-* } 35 } */ -long union u2; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -struct s3 short; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -union u3 signed; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -unsigned struct s4; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -_Complex enum { E3 }; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ +/* { dg-warning "warning: useless type name in empty declaration" "T struct" { target *-*-* } 34 } */ +long union u2; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 36 } */ +struct s3 short; /* { dg-error "error: two or more data types in declaration specifiers" } */ +union u3 signed; /* { dg-error "error: two or more data types in declaration specifiers" } */ +unsigned struct s4; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 40 } */ +_Complex enum { E3 }; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 42 } */ diff --git a/gcc/testsuite/gcc.dg/declspec-5.c b/gcc/testsuite/gcc.dg/declspec-5.c index febbfb32edc..f24d9b468b9 100644 --- a/gcc/testsuite/gcc.dg/declspec-5.c +++ b/gcc/testsuite/gcc.dg/declspec-5.c @@ -19,23 +19,27 @@ enum e1 { E1 }; /* Not declaring anything (pedwarns). */ struct { int a; }; /* { dg-warning "warning: unnamed struct/union that defines no instances" } */ int; /* { dg-warning "warning: useless type name in empty declaration" } */ -long; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ -/* { dg-warning "warning: empty declaration" "long" { target *-*-* } 22 } */ +long; /* { dg-warning "warning: useless type name in empty declaration" } */ T; /* { dg-warning "warning: useless type name in empty declaration" } */ static const; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ -/* { dg-warning "warning: empty declaration" "long" { target *-*-* } 25 } */ +/* { dg-warning "warning: empty declaration" "static const" { target *-*-* } 24 } */ union { long b; }; /* { dg-warning "warning: unnamed struct/union that defines no instances" } */ /* Multiple type names (errors). */ struct s1 int; /* { dg-error "error: two or more data types in declaration specifiers" } */ char union u1; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-warning "warning: useless type name in empty declaration" "char union" { target *-*-* } 31 } */ +/* { dg-warning "warning: useless type name in empty declaration" "char union" { target *-*-* } 30 } */ double enum { E2 }; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-warning "warning: useless type name in empty declaration" "double enum" { target *-*-* } 33 } */ +/* { dg-warning "warning: useless type name in empty declaration" "double enum" { target *-*-* } 32 } */ T struct s2; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-warning "warning: useless type name in empty declaration" "T struct" { target *-*-* } 35 } */ -long union u2; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -struct s3 short; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -union u3 signed; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -unsigned struct s4; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -_Complex enum { E3 }; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ +/* { dg-warning "warning: useless type name in empty declaration" "T struct" { target *-*-* } 34 } */ +long union u2; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 36 } */ +struct s3 short; /* { dg-error "error: two or more data types in declaration specifiers" } */ +union u3 signed; /* { dg-error "error: two or more data types in declaration specifiers" } */ +unsigned struct s4; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 40 } */ +_Complex enum { E3 }; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-warning "warning: useless type name in empty declaration" "empty" { target *-*-* } 42 } */ +/* { dg-warning "warning: ISO C90 does not support complex types" "C90" { target *-*-* } 42 } */ +/* { dg-warning "warning: ISO C does not support plain 'complex' meaning 'double complex'" "ISO C" { target *-*-* } 42 } */ diff --git a/gcc/testsuite/gcc.dg/declspec-6.c b/gcc/testsuite/gcc.dg/declspec-6.c index 305eed78bd9..29ef24843bf 100644 --- a/gcc/testsuite/gcc.dg/declspec-6.c +++ b/gcc/testsuite/gcc.dg/declspec-6.c @@ -19,23 +19,27 @@ enum e1 { E1 }; /* Not declaring anything (pedwarns). */ struct { int a; }; /* { dg-error "error: unnamed struct/union that defines no instances" } */ int; /* { dg-error "error: useless type name in empty declaration" } */ -long; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ -/* { dg-error "error: empty declaration" "long" { target *-*-* } 22 } */ +long; /* { dg-error "error: useless type name in empty declaration" } */ T; /* { dg-error "error: useless type name in empty declaration" } */ static const; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ -/* { dg-error "error: empty declaration" "long" { target *-*-* } 25 } */ +/* { dg-error "error: empty declaration" "static const" { target *-*-* } 24 } */ union { long b; }; /* { dg-error "error: unnamed struct/union that defines no instances" } */ /* Multiple type names (errors). */ struct s1 int; /* { dg-error "error: two or more data types in declaration specifiers" } */ char union u1; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-error "error: useless type name in empty declaration" "char union" { target *-*-* } 31 } */ +/* { dg-error "error: useless type name in empty declaration" "char union" { target *-*-* } 30 } */ double enum { E2 }; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-error "error: useless type name in empty declaration" "double enum" { target *-*-* } 33 } */ +/* { dg-error "error: useless type name in empty declaration" "double enum" { target *-*-* } 32 } */ T struct s2; /* { dg-error "error: two or more data types in declaration specifiers" } */ -/* { dg-error "error: useless type name in empty declaration" "T struct" { target *-*-* } 35 } */ -long union u2; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -struct s3 short; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -union u3 signed; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -unsigned struct s4; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ -_Complex enum { E3 }; /* { dg-error "error: long, short, signed, unsigned or complex used invalidly in empty declaration" } */ +/* { dg-error "error: useless type name in empty declaration" "T struct" { target *-*-* } 34 } */ +long union u2; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-error "error: useless type name in empty declaration" "empty" { target *-*-* } 36 } */ +struct s3 short; /* { dg-error "error: two or more data types in declaration specifiers" } */ +union u3 signed; /* { dg-error "error: two or more data types in declaration specifiers" } */ +unsigned struct s4; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-error "error: useless type name in empty declaration" "empty" { target *-*-* } 40 } */ +_Complex enum { E3 }; /* { dg-error "error: two or more data types in declaration specifiers" } */ +/* { dg-error "error: useless type name in empty declaration" "empty" { target *-*-* } 42 } */ +/* { dg-error "error: ISO C90 does not support complex types" "C90" { target *-*-* } 42 } */ +/* { dg-error "error: ISO C does not support plain 'complex' meaning 'double complex'" "ISO C" { target *-*-* } 42 } */