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]

Re: Patch: Feature: MSVC-style bit field packing -- take 2


An update based on more (odd) cases suppiled by several folks.
(Special thanks to them for finding some of the more egregious
weirdnesses: Mumit, Alastair Houghton, and Mikey.)

Donn
===================================================
Donn Terry                  mailto:donn@interix.com
Softway Systems, Inc.        http://www.interix.com
2850 McClelland Dr, Ste. 1800   Ft.Collins CO 80525
Tel: +1-970-204-9900           Fax: +1-970-204-9951
===================================================
Feature: MSVC-style bit field packing, take 2.

This revision covers more cases than before.  More accurately,
it covers more odd corner cases.   The testcase has been extended 
to cover the corner cases.  (The only files changed from the last
patch are those to stor-layout.c and the test cases.)

Don't blame me for the truly odd rules, it matches MSVC output.

Thanks to Mumit Khan, Alastair Houghton, and "Mikey" (don't know which)
for their contributions to the tests and identifying some of the
less intuitive special cases so they could be fixed.

I realize that Jeff has said that the default should be "native"
(match the ABI), but these structure packing rules are so different
from the current default that some transition time is needed if they
ever become the default.  Thus, the option is retained.

(Yes, I know, it's a feature and we're past the deadline, so Jeff, just
ignore it for now.  However, for others who could use it (Cygwin, e.g.), 
at least it's available.)

The patch also provides compile line and attribute options to set the option.

Details:
	MSVC (and maybe other) compilers don't align bitfields to match
	any of the "normal" gcc modes.  In addition, there are good arguments
	on both sides of whether "gnu" or "native" packing should be provided
	(and what the default should be).  Rather than making a commitment...

	I chose the names "native" and "gnu" rather than "native" and
	"no-native" or some other variation both because it seemed more
	extensible and because it asserted what was being done directly.

	As a note: both the alpha and the i386 seem to already use
	PCC_BITFIELD_TYPE_MATTERS as 1, so I did not change that.  However,
	this is set up so that it would be a one line change in the
	the configuration files to make it track the setting of the
	"native" flag I introduce below.  (I don't see a reason to
	provide a bunch of options along these lines: the native mode
	and the gcc default seem to be the only two interesting ones.
	However, if there's more than one native mode, then there may
	be a need.) (No recommendation, just an observation.)

	1)  Add command line --native-struct and --gnu-struct, and
	    corresponding __attribute__ native_struct and gnu_struct.
	    Let the end-user choose which format he wants.  These are
	    exactly parallel to --packed/packed, except that they apply
	    ONLY to whole structs (__attribute__((packed)) can be applied
	    to a single field).
	    tree.h: add new bit native_flag to struct tree_type, 
	      TYPE_NATIVE macro to maintain it.
	    flags.h: add new flag_native_struct for global setting of
	      the mode.
	    c-common.c: add A_NATIVE and A_GCC_PACK to the __attribute__
	      enum, add the keywords in init_attributes, and the cases 
	      to decl_attributes.  These set/clear TYPE_NATIVE
	    c-decl.c: set TYPE_NATIVE from flag_native_struct
	    toplev.c: parse the new keywords (add to table) and initialize
	      flag_native_struct to DEFAULT_NATIVE_STRUCT (0 if not defined)
	      so that the compiler's default can be controlled from the
	      configuration.

	2)  Add a new packing mode, enabled by GROUP_BITFIELDS_BY_ALIGN
	    which aligns bitfields so that fields with underlying type
	    of the same alignment are packed together (but a new alignment
	    starts a new group of bitfields).  (This is an abstraction
	    of the MSVC semantics.)  There are also a large number of
	    special cases having to do with adjacent (or not) and zero
	    size bitfields.

	3)  C++ was not honoring the command line --packed-struct option
	    (just ignoring it).  It also needed to propigate native type.

	    * cp/decl.c:xref_tag(): set the NATIVE and PACKED bits for the
	      type in the analogous place that in c-decl.c.  (I don't
	      see a reason not to honor the command line option if the
	      attribute works, but if there is one....)
	    * cp/pt.c: instantiate_class_template().  Propigate the 
	      native property the same way packed is.

	4)  (The flags to turn this on for Interix were already present,
	    but needed a tweak.)

	I have a testcase, which I have informally attached.

	Part of the testcase should be compiled with the native
	compiler, part with gcc, and the two linked together and
	run to check the results.  I'll provide a testsuite patch
	if someone will recommend a way to set up that mixed
	compilation in the testsuite environment (or is that asking
	too much?)  The test case is set up to use both the attribute
	and command line forms easily.  As it appears below, it's
	set up for command line.

	Note: gcc would have to treat "long double" as a 64-bit type
	to get structures containing "long double" to match MSVC.
	It was (currently) felt that having long double be an 80 bit type
	was preferable, since double does the job nicely.

	Note: the change to the existing code is stor-layout.c just 
	indentation and one clarification to a comment (add "e.g.").

ChangeLog gcc

Mon Apr 26 12:25:41 1999 Donn Terry (donn@interix.com)

	* flags.h (flag_native_struct): New boolean.
	* tree.h (TYPE_NATIVE): New macro.
	(tree_type): Add native_flag.
	* c-common.c (attrs): Add A_NATIVE, A_GCC_PACK to enum.
	(init_attributes): Set them up.
	(decl_attributes): Parse them, setting flag_native_struct.
	* c-decl.c (start_struct): Propigate TYPE_NATIVE.
	* stor-layout.c (layout_record): Honor GROUP_BITFIELDS_BY_ALIGN.
	(layout_union): Likewise.
	* toplev.c (lang_independent_options): Add native-struct and
	gcc-struct flags.
	(flag_native_struct): Initialize.
	* config/i386/i386-interix.h (PCC_BITFIELD_TYPE_TEST): remove.
	* config/alpha/alpha-interix.h (PCC_BITFIELD_TYPE_TEST): remove.

ChangeLog gcc/cp

Mon Apr 26 12:25:41 1999 Donn Terry (donn@interix.com)

	* decl.c (xref_tag): Init TYPE_PACKED and TYPE_NATIVE from globals.
	* pt.c (instantiate_class_template): Propigate TYPE_NATIVE.


diff -drupP egcs.source.pack.reference/gcc/c-common.c egcs.source/gcc/c-common.c
--- egcs.source.pack.reference/gcc/c-common.c	Mon Apr 26 12:25:41 1999
+++ egcs.source/gcc/c-common.c	Mon Apr 26 20:58:50 1999
@@ -54,7 +54,9 @@ int skip_evaluation;
 enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
 	    A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
 	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
-	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};
+	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS,
+	    A_NATIVE, A_GCC_PACK,
+	    };
 
 enum format_type { printf_format_type, scanf_format_type,
 		   strftime_format_type };
@@ -376,6 +378,8 @@ static void
 init_attributes ()
 {
   add_attribute (A_PACKED, "packed", 0, 0, 0);
+  add_attribute (A_NATIVE, "native_struct", 0, 0, 0);
+  add_attribute (A_GCC_PACK, "gcc_struct", 0, 0, 0);
   add_attribute (A_NOCOMMON, "nocommon", 0, 0, 1);
   add_attribute (A_COMMON, "common", 0, 0, 1);
   add_attribute (A_NORETURN, "noreturn", 0, 0, 1);
@@ -499,6 +503,24 @@ decl_attributes (node, attributes, prefi
 	    DECL_PACKED (decl) = 1;
 	  /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
 	     used for DECL_REGISTER.  It wouldn't mean anything anyway.  */
+	  else
+	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+	  break;
+
+	case A_NATIVE:
+	  /* It only applies to the whole struct */
+	  if (is_type)
+	    TYPE_NATIVE (type) = 1;
+	  /* it doesn't mean anything to variables */
+	  else
+	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+	  break;
+
+	case A_GCC_PACK:
+	  /* It only applies to the whole struct */
+	  if (is_type)
+	    TYPE_NATIVE (type) = 0;
+	  /* it doesn't mean anything to variables */
 	  else
 	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
 	  break;
diff -drupP egcs.source.pack.reference/gcc/c-decl.c egcs.source/gcc/c-decl.c
--- egcs.source.pack.reference/gcc/c-decl.c	Mon Apr 26 12:25:42 1999
+++ egcs.source/gcc/c-decl.c	Tue Apr 27 12:10:43 1999
@@ -5743,6 +5743,7 @@ start_struct (code, name)
     {
       C_TYPE_BEING_DEFINED (ref) = 1;
       TYPE_PACKED (ref) = flag_pack_struct;
+      TYPE_NATIVE (ref) = flag_native_struct;
       if (TYPE_FIELDS (ref))
 	error ((code == UNION_TYPE ? "redefinition of `union %s'"
 		: "redefinition of `struct %s'"),
@@ -5757,6 +5758,7 @@ start_struct (code, name)
   pushtag (name, ref);
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
+  TYPE_NATIVE (ref) = flag_native_struct;
   return ref;
 }
 
diff -drupP egcs.source.pack.reference/gcc/config/alpha/alpha-interix.h egcs.source/gcc/config/alpha/alpha-interix.h
--- egcs.source.pack.reference/gcc/config/alpha/alpha-interix.h	Mon Apr 26 12:23:27 1999
+++ egcs.source/gcc/config/alpha/alpha-interix.h	Tue Apr 27 14:20:48 1999
@@ -206,7 +206,6 @@ while (0)
 #define HOST_PTR_AS_INT unsigned long
 
 #define PCC_BITFIELD_TYPE_MATTERS 1
-#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec)
 #define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
 
 /* DWARF2 Unwinding doesn't work with exception handling yet. */
diff -drupP egcs.source.pack.reference/gcc/config/i386/i386-interix.h egcs.source/gcc/config/i386/i386-interix.h
--- egcs.source.pack.reference/gcc/config/i386/i386-interix.h	Mon Apr 26 12:23:37 1999
+++ egcs.source/gcc/config/i386/i386-interix.h	Tue Apr 27 13:24:53 1999
@@ -412,7 +412,6 @@ while (0)
 #define HOST_PTR_AS_INT unsigned long
 
 #define PCC_BITFIELD_TYPE_MATTERS 1
-#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec)
 #define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
 
 /* The following two flags are usually "off" for i386, because some non-gnu
diff -drupP egcs.source.pack.reference/gcc/flags.h egcs.source/gcc/flags.h
--- egcs.source.pack.reference/gcc/flags.h	Mon Apr 26 12:25:54 1999
+++ egcs.source/gcc/flags.h	Mon Apr 26 20:58:51 1999
@@ -436,6 +436,9 @@ extern int flag_gnu_linker;
 /* Tag all structures with __attribute__(packed) */
 extern int flag_pack_struct;
 
+/* Tag all structures with __attribute__(native_struct) */
+extern int flag_native_struct;
+
 /* This flag is only tested if alias checking is enabled.
    0 if pointer arguments may alias each other.  True in C.
    1 if pointer arguments may not alias each other but may alias
diff -drupP egcs.source.pack.reference/gcc/stor-layout.c egcs.source/gcc/stor-layout.c
--- egcs.source.pack.reference/gcc/stor-layout.c	Mon Apr 26 12:26:06 1999
+++ egcs.source/gcc/stor-layout.c	Tue Apr 27 13:27:55 1999
@@ -333,6 +333,26 @@ layout_decl (decl, known_align)
    The return value is a list of static members of the record.
    They still need to be laid out.  */
 
+/* To repreise: PCC_BITFIELD_TYPE_MATTERS is a flag (which must be a valid
+   expression) to force alignment to follow a different set of alignment
+   rules (more like "other compilers", whatever that means).
+
+   In some systems, it can be a dynamic test for the "native" flag applied
+   to a structure.  In others it may not be.
+
+   It may also be just part of the solution.  The flag GROUP_BITFIELDS_BY_ALIGN
+   causes structures to be aligned according to additional rules (beyond
+   those of PCC...) (that coincide with Windows alignment). */
+
+/* G_B_B_A means that a change in the required alignment of a sequence
+   of bitfields causes the next one to be aligned to whatever alignment
+   it needs.  Otherwise with P_B_T_M, bitfields are forced to align only
+   by zero-sized fields.  With neither, gcc default alignment (fairly
+   tightly packed), prevails.  So noone goes astray, sanity check. */
+#if defined(GROUP_BITFIELDS_BY_ALIGN) && !defined(PCC_BITFIELD_TYPE_MATTERS)
+You must define PCC_BITFIELD_TYPE_MATTERS to use GROUP_BITFIELDS_BY_ALIGN
+#endif
+
 static tree
 layout_record (rec)
      tree rec;
@@ -351,6 +371,7 @@ layout_record (rec)
   /* Once we start using VAR_SIZE, this is the maximum alignment
      that we know VAR_SIZE has.  */
   register int var_align = BITS_PER_UNIT;
+  int last_align = -1;
 
 #ifdef STRUCTURE_SIZE_BOUNDARY
   /* Packed structures don't need to have minimum size.  */
@@ -402,35 +423,111 @@ layout_record (rec)
 
 #ifndef PCC_BITFIELD_TYPE_MATTERS
       record_align = MAX (record_align, desired_align);
-#else
+#else /* [ */
       if (PCC_BITFIELD_TYPE_MATTERS && TREE_TYPE (field) != error_mark_node
 	  && DECL_BIT_FIELD_TYPE (field)
 	  && ! integer_zerop (TYPE_SIZE (TREE_TYPE (field))))
 	{
-	  /* For these machines, a zero-length field does not
-	     affect the alignment of the structure as a whole.
-	     It does, however, affect the alignment of the next field
-	     within the structure.  */
-	  if (! integer_zerop (DECL_SIZE (field)))
-	    record_align = MAX ((int)record_align, desired_align);
-	  else if (! DECL_PACKED (field))
-	    desired_align = TYPE_ALIGN (TREE_TYPE (field));
-	  /* A named bit field of declared type `int'
-	     forces the entire structure to have `int' alignment.  */
-	  if (DECL_NAME (field) != 0)
+#ifdef GROUP_BITFIELDS_BY_ALIGN
+	  if (!GROUP_BITFIELDS_BY_ALIGN)
+#endif
 	    {
-	      int type_align = TYPE_ALIGN (TREE_TYPE (field));
-	      if (maximum_field_alignment != 0)
-		type_align = MIN (type_align, maximum_field_alignment);
-	      else if (DECL_PACKED (field))
-		type_align = MIN (type_align, BITS_PER_UNIT);
+	      /* For these machines, a zero-length field does not
+		 affect the alignment of the structure as a whole.
+		 It does, however, affect the alignment of the next field
+		 within the structure.  */
+	      if (! integer_zerop (DECL_SIZE (field)))
+		record_align = MAX ((int)record_align, desired_align);
+	      else if (! DECL_PACKED (field))
+		desired_align = TYPE_ALIGN (TREE_TYPE (field));
+	      /* A named bit field of declared type e.g. `int'
+		 forces the entire structure to have `int' alignment.  */
+	      if (DECL_NAME (field) != 0)
+		{
+		  int type_align = TYPE_ALIGN (TREE_TYPE (field));
+		  if (maximum_field_alignment != 0)
+		    type_align = MIN (type_align, maximum_field_alignment);
+		  else if (DECL_PACKED (field))
+		    type_align = MIN (type_align, BITS_PER_UNIT);
 
-	      record_align = MAX ((int)record_align, type_align);
+		  record_align = MAX ((int)record_align, type_align);
+		}
+	    }
+#ifdef GROUP_BITFIELDS_BY_ALIGN /* [ */
+	  else 
+	    {
+	      /* For these, a zero size bitfield is only meaningful when
+		 immediately following another bitfield.  If if follows
+		 a non-bitfield, it's COMPLETELY ignored.  Just to add
+		 to the confusion, a zero size bitfield is NOT considered
+		 a prior bitfield for this rule, so two zero-size bitfields
+		 in a row cause the second to be ignored.
+
+		 Hey... don't blame me: I'm just trying to do what they
+		 did.  */
+
+	      if (DECL_PACKED (field)) {
+		  /* Already done */
+	      }
+	      else if (integer_zerop (DECL_SIZE (field)) && last_align == -1) 
+		{
+		  /* Completely ignore it */
+		  desired_align = 1;
+	        }
+	      else 
+		{
+		  int type_align;
+		  int proposed_record_align;
+
+		  proposed_record_align 
+		      = type_align 
+		      = TYPE_ALIGN (TREE_TYPE (field));
+
+		  /* A zero size forces both field and record alignment,
+		     *if* it wasn't ignored above.  Non-zero size forces
+		     record alignment, too. */
+	          if (integer_zerop (DECL_SIZE (field)))
+		      desired_align = type_align;
+
+		  /* Apply ceilings on record alignment */
+		  if (maximum_field_alignment != 0)
+		    proposed_record_align = 
+			MIN (proposed_record_align, maximum_field_alignment);
+		  else if (DECL_PACKED (field))
+		    proposed_record_align = 
+			MIN (proposed_record_align, BITS_PER_UNIT);
+
+		  record_align = MAX ((int)record_align, proposed_record_align);
+
+		  /* We only change alignment if it changes; else leave things
+		     alone. */
+		  if (last_align != type_align)
+		      desired_align = MAX(last_align,type_align);
+
+		  /* Zero size resets the "saw bitfield" state. */
+		  if (integer_zerop (DECL_SIZE (field)))
+		      last_align = -1;
+		  else
+		      last_align = type_align;
+		}
 	    }
+#endif /* ] */
 	}
       else
-	record_align = MAX ((int)record_align, desired_align);
+	{
+#ifdef GROUP_BITFIELDS_BY_ALIGN
+	  /* Note: last_align can never be different from -1 unless
+	     the GROUP_BITFIELDS_BY_ALIGN stuff is enabled.
+
+	     If the prior field caused an alignment, NOW is when
+	     we honor it. */
+	  if (last_align != -1) 
+	     desired_align = MAX(desired_align, last_align);
+	  last_align = -1;
 #endif
+	  record_align = MAX ((int)record_align, desired_align);
+	}
+#endif  /* ] */
 
       /* Does this field automatically have alignment it needs
 	 by virtue of the fields that precede it and the record's
@@ -636,12 +733,23 @@ layout_union (rec)
 
       /* Union must be at least as aligned as any field requires.  */
 
-      union_align = MAX (union_align, DECL_ALIGN (field));
+#ifdef GROUP_BITFIELDS_BY_ALIGN
+      /* However, bitfields don't count in this case */
+      if (!GROUP_BITFIELDS_BY_ALIGN
+	  || !DECL_BIT_FIELD_TYPE (field))
+#endif
+          union_align = MAX (union_align, DECL_ALIGN (field));
 
 #ifdef PCC_BITFIELD_TYPE_MATTERS
       /* On the m88000, a bit field of declare type `int'
-	 forces the entire union to have `int' alignment.  */
-      if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
+	 forces the entire union to have `int' alignment.
+	 However, if GROUP_BITFIELDS_BY_ALIGN is true, we don't
+	 do this. */
+      if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field)
+#ifdef GROUP_BITFIELDS_BY_ALIGN
+         && !GROUP_BITFIELDS_BY_ALIGN
+#endif
+      )
 	union_align = MAX (union_align, TYPE_ALIGN (TREE_TYPE (field)));
 #endif
 
diff -drupP egcs.source.pack.reference/gcc/toplev.c egcs.source/gcc/toplev.c
--- egcs.source.pack.reference/gcc/toplev.c	Mon Apr 26 12:26:07 1999
+++ egcs.source/gcc/toplev.c	Tue Apr 27 13:21:41 1999
@@ -718,9 +718,15 @@ int flag_gnu_linker = 0;
 int flag_gnu_linker = 1;
 #endif
 
-/* Tag all structures with __attribute__(packed) */
+/* Tag all structures with __attribute__(packed) off */
 int flag_pack_struct = 0;
 
+/* Tag all structures with __attribute__(native_struct) off */
+#ifndef DEFAULT_NATIVE_STRUCT
+#define DEFAULT_NATIVE_STRUCT 0
+#endif
+int flag_native_struct = DEFAULT_NATIVE_STRUCT;
+
 /* Emit code to check for stack overflow; also may cause large objects
    to be allocated dynamically.  */
 int flag_stack_check;
@@ -944,6 +950,10 @@ lang_independent_options f_options[] =
    "Do the full regmove optimization pass"},
   {"pack-struct", &flag_pack_struct, 1,
    "Pack structure members together without holes" },
+  {"native-struct", &flag_native_struct, 1,
+   "Pack structure members consistent with some other (native) compiler" },
+  {"gcc-struct", &flag_native_struct, 0,
+   "Pack structure members using gcc default rules" },
   {"stack-check", &flag_stack_check, 1,
    "Insert stack checking code into the program" },
   {"argument-alias", &flag_argument_noalias, 0,
diff -drupP egcs.source.pack.reference/gcc/tree.h egcs.source/gcc/tree.h
--- egcs.source.pack.reference/gcc/tree.h	Mon Apr 26 12:26:07 1999
+++ egcs.source/gcc/tree.h	Mon Apr 26 20:58:51 1999
@@ -875,10 +875,15 @@ struct tree_block
    the same way that the first union alternative would be passed.  */
 #define TYPE_TRANSPARENT_UNION(NODE) (TYPE_CHECK (NODE)->type.transparent_union_flag)
 
-/* Indicated that objects of this type should be laid out in as
+/* Indicates that objects of this type should be laid out in as
    compact a way as possible.  */
 #define TYPE_PACKED(NODE) (TYPE_CHECK (NODE)->type.packed_flag)
 
+/* Indicates that objects of this type should be layed out as the
+   native compiler does; if a compile line option (or default state)
+   turns this on, then turning it OFF should result in gnu alignment. */
+#define TYPE_NATIVE(NODE) ((NODE)->type.native_flag)
+
 struct tree_type
 {
   char common[sizeof (struct tree_common)];
@@ -900,6 +905,7 @@ struct tree_type
   unsigned needs_constructing_flag : 1;
   unsigned transparent_union_flag : 1;
   unsigned packed_flag : 1;
+  unsigned native_flag : 1;
   unsigned restrict_flag : 1;
 
   unsigned lang_flag_0 : 1;
@@ -909,7 +915,7 @@ struct tree_type
   unsigned lang_flag_4 : 1;
   unsigned lang_flag_5 : 1;
   unsigned lang_flag_6 : 1;
-  /* room for 3 more bits */
+  /* room for 2 more bits */
 
   unsigned int align;
   union tree_node *pointer_to;
diff -drupP egcs.source.pack.reference/gcc/cp/decl.c egcs.source/gcc/cp/decl.c
--- egcs.source.pack.reference/gcc/cp/decl.c	Mon Apr 26 12:24:09 1999
+++ egcs.source/gcc/cp/decl.c	Mon Apr 26 20:58:51 1999
@@ -12657,6 +12657,9 @@ xref_tag (code_type_node, name, globaliz
 	  /* Class types don't nest the way enums do.  */
 	  class_binding_level = (struct binding_level *)0;
 #endif
+	  TYPE_PACKED (ref) = flag_pack_struct;
+	  TYPE_NATIVE (ref) = flag_native_struct;
+
 	  pushtag (name, ref, globalize);
 	  class_binding_level = old_b;
 	}
diff -drupP egcs.source.pack.reference/gcc/cp/pt.c egcs.source/gcc/cp/pt.c
--- egcs.source.pack.reference/gcc/cp/pt.c	Mon Apr 26 12:24:12 1999
+++ egcs.source/gcc/cp/pt.c	Mon Apr 26 20:58:51 1999
@@ -4882,6 +4882,7 @@ instantiate_class_template (type)
   TYPE_USES_VIRTUAL_BASECLASSES (type)
     = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
   TYPE_PACKED (type) = TYPE_PACKED (pattern);
+  TYPE_NATIVE (type) = TYPE_NATIVE (pattern);
   TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
   TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
   if (ANON_UNION_TYPE_P (pattern))

-----------------TEST CASE bittest.h --------------------------------------
struct a_type {
   int a;
   unsigned char b;
   unsigned c:7;
   int d;
   unsigned e:3;
   unsigned f:9;
   unsigned char g:7;
   int h;
   unsigned int i:6;
   unsigned int :0;
   unsigned int j:6;
} NATIVE ;

struct b_type {
   int a;
   unsigned char b;
   unsigned int c:7;
   int d;
   unsigned int e:3;
   unsigned int f:9;
   unsigned char g:7;
   int h;
   unsigned char i:6;
   unsigned char :0;
   unsigned char j:6;

} NATIVE ;

struct c_type {
   int a;
   unsigned char b;
   unsigned short c:7;
   int d;
   unsigned short e:3;
   unsigned short f:9;
   unsigned char g:7;
   short h;
   unsigned short i:6;
   unsigned short :0;
   unsigned short j:6;
} NATIVE ;

struct d_type {
   int a:3;
   int b:4;
   int c:4;
   int d:6;
   int e:5;
   int f:5;
   int g:5;
} NATIVE ;

/* Bitfields of size 0 have some truly odd behaviors. */

struct e_type {   /* should be size 2! */
   char a;
   int :0;        /* ignored; prior field is not a bitfield. */
   char b;
};

struct f_type {   /* should be size 8! */
   char a:8;
   int :0;	  /* not ignored; prior field IS a bitfield, causes struct
		     alignment as well. */
   char b;
};

struct g_type {   /* should be size 2! */
   char a:8;
   char :0;
   int  :0;	  /* Ignored; prior field is zero size bitfield. */
   char b;
};

struct h_type {   /* should be size 3! */
   short a:3;
   char  b;
};

#ifdef _MSC_VER
#define LONGLONG __int64
#else
#define LONGLONG long long
#endif

union i_type {   /* should be size 2! */
   LONGLONG a:3;
   char  b;
};
-----------------TEST CASE bittest_nat.c --------------------------------------
#define NATIVE   /* as nothing */
#include "bittest.h"
#include <stddef.h>
#define poffset(a,b) printf("   %s: %d\n", #b, offsetof(struct a,b));

struct a_type a;
struct b_type b;
struct c_type c;
struct d_type d;
struct e_type e;
struct f_type f;
struct g_type g;
struct h_type h;
union i_type i;

int a_offsets[]={offsetof(struct a_type,b),
             offsetof(struct a_type,d),
             offsetof(struct a_type,h),
	     sizeof(struct a_type)};

int b_offsets[]={offsetof(struct b_type,b),
             offsetof(struct b_type,d),
             offsetof(struct b_type,h),
	     sizeof(struct b_type)};

int c_offsets[]={offsetof(struct c_type,b),
             offsetof(struct c_type,d),
             offsetof(struct c_type,h),
	     sizeof(struct c_type)};

int d_size = sizeof(struct d_type);
int e_size = sizeof(struct e_type);
int f_size = sizeof(struct f_type);
int g_size = sizeof(struct g_type);
int h_size = sizeof(struct h_type);
int i_size = sizeof(union i_type);

main()
{

    a.a=1;
    a.b=2;
    a.c=3;
    a.d=4;
    a.e=5;
    a.f=6;
    a.g=7;
    a.h=8;
    a.i=9;
    a.j=10;

    b.a=1;
    b.b=2;
    b.c=3;
    b.d=4;
    b.e=5;
    b.f=6;
    b.g=7;
    b.h=8;
    b.i=9;
    b.j=10;

    c.a=1;
    c.b=2;
    c.c=3;
    c.d=4;
    c.e=5;
    c.f=6;
    c.g=7;
    c.h=8;
    c.i=9;
    c.j=10;

    d.a=1;
    d.b=2;
    d.c=3;
    d.d=4;
    d.e=5;
    d.f=6;
    d.g=7;

    e.a=1;
    e.b=2;

    f.a=1;
    f.b=2;

    g.a=1;
    g.b=2;

    h.a=1;
    h.b=2;

    i.a=1;
    i.b=2;

    check_results();
}
-----------------TEST CASE bittest_gcc.c --------------------------------------
#define NATIVE 
//#define NATIVE __attribute__((__native_struct__))
#include "bittest.h"
#include <stddef.h>

#define check(s,f,v) if (s.f != v) { \
        printf(#s"."#f " was %d not " #v "\n", s.f); exit_code = 1;}

#define ckoff(a) for (ii=0; ii<3; ii++) { \
		if (a##_offsets[ii] != my_##a##_offsets[ii]) {\
		    printf(#a" offset field %d did not match: nat: %d v gcc: %d\n", \
			ii, a##_offsets[ii], my_##a##_offsets[ii]); \
			exit_code = 1; } }

#define cksize(a) if (a##_size != my_##a##_size) { \
		    printf(#a" size did not match: nat %d v gcc %d\n", \
		       a##_size, my_##a##_size); \
		       exit_code = 1; } 

extern int a_offsets[];
extern int b_offsets[];
extern int c_offsets[];

int my_a_offsets[]={offsetof(struct a_type,b),
             offsetof(struct a_type,d),
             offsetof(struct a_type,h),
	     sizeof(struct a_type)};

int my_b_offsets[]={offsetof(struct b_type,b),
             offsetof(struct b_type,d),
             offsetof(struct b_type,h),
	     sizeof(struct b_type)};

int my_c_offsets[]={offsetof(struct c_type,b),
             offsetof(struct c_type,d),
             offsetof(struct c_type,h),
	     sizeof(struct c_type)};

int my_d_size = sizeof(struct d_type);
int my_e_size = sizeof(struct e_type);
int my_f_size = sizeof(struct f_type);
int my_g_size = sizeof(struct g_type);
int my_h_size = sizeof(struct h_type);
int my_i_size = sizeof(union i_type);

extern int d_size;
extern int e_size;
extern int f_size;
extern int g_size;
extern int h_size;
extern int i_size;

extern struct a_type a;
extern struct b_type b;
extern struct c_type c;
extern struct d_type d;
extern struct e_type e;
extern struct f_type f;
extern struct g_type g;
extern struct h_type h;
extern union i_type i;

check_results()
{
    int ii;
    int exit_code = 0;

    ckoff(a);
    ckoff(b);
    ckoff(c);

    cksize(d);
    cksize(e);
    cksize(f);
    cksize(g);
    cksize(h);
    cksize(i);

    check(a,a,1);
    check(a,b,2);
    check(a,c,3);
    check(a,d,4);
    check(a,e,5);
    check(a,f,6);
    check(a,g,7);
    check(a,h,8);
    check(a,i,9);
    check(a,j,10);

    check(b,a,1);
    check(b,b,2);
    check(b,c,3);
    check(b,d,4);
    check(b,e,5);
    check(b,f,6);
    check(b,g,7);
    check(b,h,8);
    check(b,i,9);
    check(b,j,10);

    check(c,a,1);
    check(c,b,2);
    check(c,c,3);
    check(c,d,4);
    check(c,e,5);
    check(c,f,6);
    check(c,g,7);
    check(c,h,8);
    check(c,i,9);
    check(c,j,10);

    check(d,a,1);
    check(d,b,2);
    check(d,c,3);
    check(d,d,4);
    check(d,e,5);
    check(d,f,6);
    check(d,g,7);

    check(e,a,1);
    check(e,b,2);

    check(f,a,1);
    check(f,b,2);

    check(g,a,1);
    check(g,b,2);

    check(h,a,1);
    check(h,b,2);

    check(i,b,2);

    exit(exit_code);
}
-----------------TEST CASE driver script --------------------------------------
cc -c bittest_nat.c
# be sure to point gcc at the right gcc.

#This should pass and say nothing.
gcc -c -fnative-struct bittest_gcc.c 
echo NATIVE:
gcc bittest_nat.o bittest_gcc.o
a.out

#...This should fail and list errors.
gcc -c -fgcc-struct bittest_gcc.c 
echo GNU:
gcc bittest_nat.o bittest_gcc.o
a.out

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