class.c (finish_struct_1): Set things up for 0-width bitfields like we do for others.
authorJason Merrill <jason@yorick.cygnus.com>
Mon, 23 Nov 1998 01:14:55 +0000 (01:14 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 23 Nov 1998 01:14:55 +0000 (20:14 -0500)
* class.c (finish_struct_1): Set things up for 0-width bitfields
like we do for others.
* decl.c (check_tag_decl): New fn.
(shadow_tag): Split out from here.
* decl2.c (grok_x_components): Call it.

From-SVN: r23762

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c

index bc99a43..9616c2c 100644 (file)
@@ -1,3 +1,12 @@
+1998-11-23  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * class.c (finish_struct_1): Set things up for 0-width bitfields
+       like we do for others.
+
+       * decl.c (check_tag_decl): New fn.
+       (shadow_tag): Split out from here.
+       * decl2.c (grok_x_components): Call it.
+
 1998-11-22  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl.c: Lose warn_about_return_type.
index 9ade201..17f728f 100644 (file)
@@ -3669,23 +3669,24 @@ finish_struct_1 (t, warn_anon)
                                 x, TREE_TYPE (x));
                }
 
-             if (DECL_INITIAL (x) == NULL_TREE)
-               ;
-             else if (width == 0)
+             if (DECL_INITIAL (x))
                {
+                 DECL_INITIAL (x) = NULL_TREE;
+                 DECL_FIELD_SIZE (x) = width;
+                 DECL_BIT_FIELD (x) = 1;
+
+                 if (width == 0)
+                   {
 #ifdef EMPTY_FIELD_BOUNDARY
-                 DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
+                     DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+                                           EMPTY_FIELD_BOUNDARY);
 #endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-                 DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
-                                       TYPE_ALIGN (TREE_TYPE (x)));
+                     if (PCC_BITFIELD_TYPE_MATTERS)
+                       DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+                                             TYPE_ALIGN (TREE_TYPE (x)));
 #endif
-               }
-             else
-               {
-                 DECL_INITIAL (x) = NULL_TREE;
-                 DECL_FIELD_SIZE (x) = width;
-                 DECL_BIT_FIELD (x) = 1;
+                   }
                }
            }
          else
index 340d992..4f2fccb 100644 (file)
@@ -2706,6 +2706,7 @@ extern int init_type_desc                 PROTO((void));
 extern tree define_function
        PROTO((char *, tree, enum built_in_function,
               void (*) (tree), char *));
+extern tree check_tag_decl                     PROTO((tree));
 extern void shadow_tag                         PROTO((tree));
 extern tree groktypename                       PROTO((tree));
 extern tree start_decl                         PROTO((tree, tree, int, tree, tree));
index 9611b0d..cacdf05 100644 (file)
@@ -6452,41 +6452,33 @@ fixup_anonymous_union (t)
     error ("an anonymous union cannot have function members");
 }
 
-/* Called when a declaration is seen that contains no names to declare.
-   If its type is a reference to a structure, union or enum inherited
-   from a containing scope, shadow that tag name for the current scope
-   with a forward reference.
-   If its type defines a new named structure or union
-   or defines an enum, it is valid but we need not do anything here.
-   Otherwise, it is an error.
+/* Make sure that a declaration with no declarator is well-formed, i.e.
+   just defines a tagged type or anonymous union.
 
-   C++: may have to grok the declspecs to learn about static,
-   complain for anonymous unions.  */
+   Returns the type defined, if any.  */
 
-void
-shadow_tag (declspecs)
+tree
+check_tag_decl (declspecs)
      tree declspecs;
 {
-  int found_tag = 0;
+  int found_type = 0;
   tree ob_modifier = NULL_TREE;
   register tree link;
-  register enum tree_code code, ok_code = ERROR_MARK;
   register tree t = NULL_TREE;
 
   for (link = declspecs; link; link = TREE_CHAIN (link))
     {
       register tree value = TREE_VALUE (link);
 
-      code = TREE_CODE (value);
-      if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
+      if (TYPE_P (value))
        {
-         my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
-
-         maybe_process_partial_specialization (value);
+         ++found_type;
 
-         t = value;
-         ok_code = code;
-         found_tag++;
+         if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
+           {
+             my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+             t = value;
+           }
        }
       else if (value == ridpointers[(int) RID_STATIC]
               || value == ridpointers[(int) RID_EXTERN]
@@ -6494,31 +6486,22 @@ shadow_tag (declspecs)
               || value == ridpointers[(int) RID_REGISTER]
               || value == ridpointers[(int) RID_INLINE]
               || value == ridpointers[(int) RID_VIRTUAL]
+              || (value == ridpointers[(int) RID_FRIEND]
+                  && (current_class_type == NULL_TREE
+                      || current_scope () != current_class_type))
+              || value == ridpointers[(int) RID_CONST]
+              || value == ridpointers[(int) RID_VOLATILE]
               || value == ridpointers[(int) RID_EXPLICIT])
        ob_modifier = value;
     }
 
-  /* This is where the variables in an anonymous union are
-     declared.  An anonymous union declaration looks like:
-     union { ... } ;
-     because there is no declarator after the union, the parser
-     sends that declaration here.  */
-  if (ok_code == UNION_TYPE
-      && t != NULL_TREE
-      && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
-          && ANON_AGGRNAME_P (TYPE_NAME (t)))
-         || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
-             && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
-    {
-      fixup_anonymous_union (t);
-
-      if (TYPE_FIELDS (t))
-       {
-         tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
-                                     NULL_TREE);
-         finish_anon_union (decl);
-       }
-    }
+  if (found_type > 1)
+    error ("multiple types in one declaration");
+    
+  if (t == NULL_TREE)
+    pedwarn ("declaration does not declare anything");
+  else if (ANON_UNION_TYPE_P (t))
+    return t;
   else
     {
       /* Anonymous unions are objects, that's why we only check for
@@ -6529,6 +6512,8 @@ shadow_tag (declspecs)
          if (ob_modifier == ridpointers[(int) RID_INLINE]
              || ob_modifier == ridpointers[(int) RID_VIRTUAL])
            cp_error ("`%D' can only be specified for functions", ob_modifier);
+         else if (ob_modifier == ridpointers[(int) RID_FRIEND])
+           cp_error ("`%D' can only be specified inside a class", ob_modifier);
          else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
            cp_error ("`%D' can only be specified for constructors",
                      ob_modifier);
@@ -6536,11 +6521,46 @@ shadow_tag (declspecs)
            cp_error ("`%D' can only be specified for objects and functions",
                      ob_modifier);
        }
+    }
 
-      if (found_tag == 0)
-       cp_error ("abstract declarator used as declaration");
-      else if (found_tag > 1)
-       pedwarn ("multiple types in one declaration");
+  return t;
+}
+
+/* Called when a declaration is seen that contains no names to declare.
+   If its type is a reference to a structure, union or enum inherited
+   from a containing scope, shadow that tag name for the current scope
+   with a forward reference.
+   If its type defines a new named structure or union
+   or defines an enum, it is valid but we need not do anything here.
+   Otherwise, it is an error.
+
+   C++: may have to grok the declspecs to learn about static,
+   complain for anonymous unions.  */
+
+void
+shadow_tag (declspecs)
+     tree declspecs;
+{
+  tree t = check_tag_decl (declspecs);
+
+  if (t)
+    maybe_process_partial_specialization (t);
+
+  /* This is where the variables in an anonymous union are
+     declared.  An anonymous union declaration looks like:
+     union { ... } ;
+     because there is no declarator after the union, the parser
+     sends that declaration here.  */
+  if (t && ANON_UNION_TYPE_P (t))
+    {
+      fixup_anonymous_union (t);
+
+      if (TYPE_FIELDS (t))
+       {
+         tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
+                                     NULL_TREE);
+         finish_anon_union (decl);
+       }
     }
 }
 \f
@@ -10761,9 +10781,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                                                           type))
                  /* If we just return the declaration, crashes
                     will sometimes occur.  We therefore return
-                        void_type_node, as if this was a friend
-                        declaration, to cause callers to completely
-                        ignore this declaration.  */
+                    void_type_node, as if this was a friend
+                    declaration, to cause callers to completely
+                    ignore this declaration.  */
                  return void_type_node;
              }
 
index 79025a5..bd09eba 100644 (file)
@@ -858,17 +858,14 @@ grok_x_components (specs)
   struct pending_inline **p;
   tree t;
 
-  t = groktypename (build_decl_list (strip_attrs (specs), NULL_TREE)); 
-  
-  if (t == NULL_TREE)
-    {
-      cp_error ("invalid member declaration");
-      return;
-    }
+  specs = strip_attrs (specs);
+
+  check_tag_decl (specs);
+  t = groktypename (build_decl_list (specs, NULL_TREE)); 
 
   /* The only case where we need to do anything additional here is an
      anonymous union field, e.g.: `struct S { union { int i; }; };'.  */
-  if (!ANON_UNION_TYPE_P (t))
+  if (t == NULL_TREE || !ANON_UNION_TYPE_P (t))
     return;
 
   fixup_anonymous_union (t);