Declspecs patch 5

Joseph S. Myers jsm@polyomino.org.uk
Fri Sep 17 18:55:00 GMT 2004


This fifth declspecs patch completes the initial overhaul of C
declaration specifiers structures.  Some bug fixes are still to come
in the sixth and last patch of this series.

Handling of type specifier keywords and detection of invalid
combinations is moved from grokdeclarator to parse time.  Many
messages are more specific (I don't like messages referring e.g. to
"long, short, signed or unsigned"; the compiler knows which was
involved so should say so in the message).  There is now a common path
in finish_declspecs checking declaration specifiers and computing the
type before the code paths split into grokdeclarator and shadow_tag.
Some erroneous cases involving typeof that used to be accepted, such
as "typeof(double) long", are now diagnosed properly, and "typedef
double D; D _Complex x;" no longer receives a bogus message about
complex integer types.

The change to set decl_attr in grokdeclarator restored something lost
in a previous patch in this series (without showing any testsuite
regressions).  I didn't manage to work out a testcase for this, but
further investigation would be needed of whether there may be relevant
cases, where an attribute applied to a TYPE_DECL rather than its type
should be used again when that typedef is used.

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
  http://www.srcf.ucam.org/~jsm28/gcc/#c90status - status of C90 for GCC 4.0
    jsm@polyomino.org.uk (personal mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

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.

testsuite:
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.

diff -rupN GCC.orig/gcc/c-decl.c GCC/gcc/c-decl.c
--- GCC.orig/gcc/c-decl.c	2004-09-14 18:57:06.000000000 +0000
+++ GCC/gcc/c-decl.c	2004-09-17 13:20:36.000000000 +0000
@@ -2681,7 +2681,7 @@ shadow_tag_warned (const struct c_declsp
 
   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_declsp
       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_declsp
       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_dec
 	       | (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_declarato
 		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_declarato
   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_declarato
     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.  */
-
-  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);
-	}
-
-      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.  */
+  size_varies = C_TYPE_VARIABLE_SIZE (type);
 
-  if ((specbits & 1 << (int) RID_LONG) && ! declspecs->long_long_p
-      && TYPE_MAIN_VARIANT (type) == double_type_node)
-    {
-      specbits &= ~(1 << (int) RID_LONG);
-      type = long_double_type_node;
-    }
-
-  /* Check all other uses of type modifiers.  */
+  /* Diagnose defaulting to "int".  */
 
-  if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-		  | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)))
+  if (declspecs->default_int_p && !in_system_header)
     {
-      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);
-	}
-    }
+      /* 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);
+    }
+
+  /* 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_declarato
       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_declarato
 	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->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->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 
   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 -rupN GCC.orig/gcc/c-parse.in GCC/gcc/c-parse.in
--- GCC.orig/gcc/c-parse.in	2004-09-12 23:48:33.000000000 +0000
+++ GCC/gcc/c-parse.in	2004-09-15 23:28:20.000000000 +0000
@@ -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 -rupN GCC.orig/gcc/c-tree.h GCC/gcc/c-tree.h
--- GCC.orig/gcc/c-tree.h	2004-09-14 18:57:06.000000000 +0000
+++ GCC/gcc/c-tree.h	2004-09-16 15:31:58.000000000 +0000
@@ -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
 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 -rupN GCC.orig/gcc/testsuite/gcc.dg/declspec-13.c GCC/gcc/testsuite/gcc.dg/declspec-13.c
--- GCC.orig/gcc/testsuite/gcc.dg/declspec-13.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/declspec-13.c	2004-09-17 18:02:30.000000000 +0000
@@ -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 -rupN GCC.orig/gcc/testsuite/gcc.dg/declspec-4.c GCC/gcc/testsuite/gcc.dg/declspec-4.c
--- GCC.orig/gcc/testsuite/gcc.dg/declspec-4.c	2004-09-11 21:23:10.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/declspec-4.c	2004-09-16 16:22:48.000000000 +0000
@@ -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 -rupN GCC.orig/gcc/testsuite/gcc.dg/declspec-5.c GCC/gcc/testsuite/gcc.dg/declspec-5.c
--- GCC.orig/gcc/testsuite/gcc.dg/declspec-5.c	2004-09-11 21:23:10.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/declspec-5.c	2004-09-16 16:23:14.000000000 +0000
@@ -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 -rupN GCC.orig/gcc/testsuite/gcc.dg/declspec-6.c GCC/gcc/testsuite/gcc.dg/declspec-6.c
--- GCC.orig/gcc/testsuite/gcc.dg/declspec-6.c	2004-09-11 21:23:10.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/declspec-6.c	2004-09-16 16:24:16.000000000 +0000
@@ -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 } */



More information about the Gcc-patches mailing list