* c-tree.h (enum c_typespec_keyword): New.
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Sep 2004 18:18:05 +0000 (18:18 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Sep 2004 18:18:05 +0000 (18:18 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@87660 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/c-parse.in
gcc/c-tree.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/declspec-13.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/declspec-4.c
gcc/testsuite/gcc.dg/declspec-5.c
gcc/testsuite/gcc.dg/declspec-6.c

index e4fea29..04eec4c 100644 (file)
@@ -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.
index b29a152..e1e8d4d 100644 (file)
@@ -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.  */
index 20ed784..6fcf667 100644 (file)
@@ -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;
index 5d1ec30..76981a7 100644 (file)
@@ -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);
index f8fe5af..0a27ca6 100644 (file)
@@ -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 (file)
index 0000000..3172520
--- /dev/null
@@ -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" } */
index fbc6c36..b8eb9d0 100644 (file)
@@ -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 } */
index febbfb3..f24d9b4 100644 (file)
@@ -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 } */
index 305eed7..29ef248 100644 (file)
@@ -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 } */