aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <jsm@polyomino.org.uk>2004-09-17 19:18:05 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2004-09-17 19:18:05 +0100
commit98c3a782774396163f6bcacf91515131e3abe375 (patch)
tree065e742552e8a8e99595de375f55074a900b5eb3 /gcc
parent254ea84c129481587eae80d78783b08d8d6cd507 (diff)
downloadgcc-98c3a782774396163f6bcacf91515131e3abe375.zip
gcc-98c3a782774396163f6bcacf91515131e3abe375.tar.gz
gcc-98c3a782774396163f6bcacf91515131e3abe375.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/c-decl.c620
-rw-r--r--gcc/c-parse.in11
-rw-r--r--gcc/c-tree.h47
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/declspec-13.c86
-rw-r--r--gcc/testsuite/gcc.dg/declspec-4.c24
-rw-r--r--gcc/testsuite/gcc.dg/declspec-5.c26
-rw-r--r--gcc/testsuite/gcc.dg/declspec-6.c26
9 files changed, 602 insertions, 265 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e4fea29..04eec4c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2004-09-17 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * 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 <Sylvain.Pion@sophia.inria.fr>
* doc/extend.texi: Fix duplicated word.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index b29a152..e1e8d4d 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 ("%<inline%> 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 %<int%> 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 %<int%> 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 %<long double%>");
- 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 %<complex%> meaning "
- "%<double complex%>");
- 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 ("%<long long long%> is too long for GCC");
- else
{
+ error ("%<long long long%> is too long for GCC");
+ break;
+ }
+ if (specs->long_p)
+ {
+ if (specs->typespec_word == cts_double)
+ {
+ error ("both %<long long%> and %<double%> in "
+ "declaration specifiers");
+ break;
+ }
if (pedantic && !flag_isoc99 && !in_system_header
&& warn_long_long)
pedwarn ("ISO C90 does not support %<long long%>");
specs->long_long_p = 1;
+ break;
}
+ if (specs->short_p)
+ error ("both %<long%> and %<short%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<long%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<long%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<long%> and %<float%> in "
+ "declaration specifiers");
+ else
+ specs->long_p = true;
+ break;
+ case RID_SHORT:
+ dupe = specs->short_p;
+ if (specs->long_p)
+ error ("both %<long%> and %<short%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<short%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<short%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<short%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<short%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->short_p = true;
+ break;
+ case RID_SIGNED:
+ dupe = specs->signed_p;
+ if (specs->unsigned_p)
+ error ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<signed%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<signed%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<signed%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->signed_p = true;
+ break;
+ case RID_UNSIGNED:
+ dupe = specs->unsigned_p;
+ if (specs->signed_p)
+ error ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<unsigned%> and %<double%> 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 %<complex%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<complex%> 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 %<long%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<void%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_void;
+ return specs;
+ case RID_BOOL:
+ if (specs->long_p)
+ error ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_bool;
+ return specs;
+ case RID_CHAR:
+ if (specs->long_p)
+ error ("both %<long%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<char%> 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 %<long%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_float;
+ return specs;
+ case RID_DOUBLE:
+ if (specs->long_long_p)
+ error ("both %<long long%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<double%> 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 %<complex%> meaning "
+ "%<double complex%>");
+ }
+ 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 20ed784..6fcf667 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 ();
- $<dsptype>$ = $1; }
+ $<dsptype>$ = finish_declspecs ($1); }
absdcl
{ $$ = XOBNEW (&parser_obstack, struct c_type_name);
$$->specs = $<dsptype>2;
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 5d1ec30..76981a7 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 f8fe5af..0a27ca6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2004-09-17 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * 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 <edelsohn@gnu.org>
* 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 0000000..3172520
--- /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 <jsm@polyomino.org.uk> */
+/* { 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 fbc6c36..b8eb9d0 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 febbfb3..f24d9b4 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 305eed7..29ef248 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 } */