This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Anonymous struct/union in C


I've been sitting on Alastair Houghton's patch to support anonymous
aggregates for a long time, and it's probably a good time to send
if off now that Jason has added anon struct to C++.

It adds the support for the following:

  #include <stdio.h>

  struct {
    struct {
      int b1;
      int b2;
    };
    union {
      float f1;
      int i1;
    };
    int b3;
  } foo = {{31, 17}, {3.2}, 13};

  int
  main ()
  {
    int b1 = foo.b1;
    int b3 = foo.b3;
    return 0;
  }

as well as the following:

  #include <stdio.h>

  struct phone 
  {
    int areacode;
    int number;
  };

  struct person
  {
    char name[30];
    struct phone;
  } Jim = {"Jim bob", {53706, 123456}};

  int
  main ()
  {
    printf ("Jim's name = %s\n", Jim.name);
    printf ("Jim's areacode = %d\n", Jim.areacode);
    printf ("Jim's number = %d\n", Jim.number);
    return 0;
  }
  

Note that I have NOT added the changes to regenerated files since
I'm basically looking for comments/critiques (ok, and flame) at this 
stage.

The change to c-parse.in (component_decl) is pretty self-explanatory.
I've had to remove the field-sorting from c-decl.c (finish_struct)
to avoid lossage when a structure contains anon struct/union AND
has more than 16, the magic number, fields.

No testsuite regressions. I've tested it reasonably well, some on
real code that makes extensive use of anonymous struct/union 
struct members. It's been in use by a few windows32 folks as well.

==== patch

Modified version of Alastair Houghton' original patch to
support unnamed/anonymous structs and unions in C.

Sat Jun 12 15:56:40 1999  Alastair J. Houghton <ajh8@doc.ic.ac.uk>
			  Mumit Khan  <khan@xraylith.wisc.edu>

	* c-parse.in (component_decl): Support anonymous struct/union.
	(%expect): Update.
	* c-parse.y: Regenerate.
	* c-parse.c: Likewise.
	* objc/objc-parse.y: Likewise.
	* objc/objc-parse.c: Likewise.
	* c-decl.c (finish_struct): Don't sort the fields.

Index: gcc-2.95/gcc/c-parse.in
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-2.95/gcc/c-parse.in,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 c-parse.in
--- gcc-2.95/gcc/c-parse.in	1999/06/10 02:09:53	1.1.1.1
+++ gcc-2.95/gcc/c-parse.in	1999/06/12 04:40:07
@@ -28,10 +28,10 @@ Boston, MA 02111-1307, USA.  */
    written by AT&T, but I have never seen it.  */
 
 ifobjc
-%expect 66
+%expect 73
 end ifobjc
 ifc
-%expect 51
+%expect 52
 
 /* These are the 23 conflicts you should get in parse.output;
    the state numbers may vary if minor changes in the grammar are made.
@@ -1594,12 +1594,21 @@ component_decl:
 		  prefix_attributes = TREE_PURPOSE (declspec_stack);
 		  declspec_stack = TREE_CHAIN (declspec_stack);
 		  resume_momentary ($2); }
-	| typed_typespecs
-		{ if (pedantic)
-		    pedwarn ("ANSI C forbids member declarations with no members");
-		  shadow_tag($1);
-		  $$ = NULL_TREE; }
-	| nonempty_type_quals setspecs components
+	| typed_typespecs setspecs save_filename save_lineno maybe_attribute
+		{
+		  /* Support for unnamed structs or unions as members of 
+		     structs or unions (which is [a] useful and [b] supports 
+		     MS P-SDK).  */
+		  if (pedantic)
+		    pedwarn ("ANSI C doesn't support unnamed structs/unions");
+
+		  $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
+		  current_declspecs = TREE_VALUE (declspec_stack);
+		  prefix_attributes = TREE_PURPOSE (declspec_stack);
+		  declspec_stack = TREE_CHAIN (declspec_stack);
+		  resume_momentary ($2);
+		}
+    | nonempty_type_quals setspecs components
 		{ $$ = $3;
 		  current_declspecs = TREE_VALUE (declspec_stack);
 		  prefix_attributes = TREE_PURPOSE (declspec_stack);
Index: gcc-2.95/gcc/c-decl.c
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-2.95/gcc/c-decl.c,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 c-decl.c
--- gcc-2.95/gcc/c-decl.c	1999/06/10 02:09:53	1.1.1.1
+++ gcc-2.95/gcc/c-decl.c	1999/06/12 20:38:08
@@ -6043,43 +6045,6 @@ finish_struct (t, fieldlist, attributes)
       Store it in this type and in the variants.  */
 
   TYPE_FIELDS (t) = fieldlist;
-
-  /* If there are lots of fields, sort so we can look through them fast.
-     We arbitrarily consider 16 or more elts to be "a lot".  */
-  {
-    int len = 0;
-
-    for (x = fieldlist; x; x = TREE_CHAIN (x))
-      {
-	if (len > 15)
-	  break;
-	len += 1;
-      }
-    if (len > 15)
-      {
-	tree *field_array;
-	char *space;
-
-	len += list_length (x);
-	/* Use the same allocation policy here that make_node uses, to
-	   ensure that this lives as long as the rest of the struct decl.
-	   All decls in an inline function need to be saved.  */
-	if (allocation_temporary_p ())
-	  space = savealloc (sizeof (struct lang_type) + len * sizeof (tree));
-	else
-	  space = oballoc (sizeof (struct lang_type) + len * sizeof (tree));
-
-	TYPE_LANG_SPECIFIC (t) = (struct lang_type *) space;
-	TYPE_LANG_SPECIFIC (t)->len = len;
-
-	field_array = &TYPE_LANG_SPECIFIC (t)->elts[0];
-	len = 0;
-	for (x = fieldlist; x; x = TREE_CHAIN (x))
-	  field_array[len++] = x;
-
-	qsort (field_array, len, sizeof (tree), field_decl_cmp);
-      }
-  }
 
   for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
     {

Regards,
Mumit


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]