[PCH] discriminators for C++ language structures

Geoffrey Keating geoffk@romulus.sfbay.redhat.com
Sat Apr 27 12:38:00 GMT 2002


This patch became much more complicated than I'd hoped, because the
mark_pending_inlines routine had to go.

Bootstrapped & tested on i686-pc-linux-gnu with GC checking.

-- 
Geoff Keating <geoffk@redhat.com>

===File ~/patches/pchbranch-cpdesc.patch====================
Index: ChangeLog
2002-04-26  Geoffrey Keating  <geoffk@redhat.com>

	* gengtype.h (note_yacc_type): Add prototype.
	* gengtype.c (note_yacc_type): New function.
	* gengtype-lex.l: Add lexer support for yacc files.
	* gengtype-yacc.y (start): Extract union from yacc files.
	(yacc_union): New rule.
	(yacc_typematch): New rule.
	(yacc_ids): New rule.
	(enum_items): Tweak for efficiency.
	(optionseq): Likewise.

Index: cp/ChangeLog
2002-04-26  Geoffrey Keating  <geoffk@redhat.com>

	* class.c (duplicate_tag_error): Reset discriminator.
	(check_bases_and_members): Update for data structure changes.
	* cp-tree.h (struct lang_id2): Use gengtype.
	(flagged_type_tree): Likewise.
	(SET_LANG_ID): Use GGC on struct lang_id2.
	(struct cp_language_function): Use gengtype.  Remove field
	'x_vcalls_possible_p'.
	(current_vcalls_possible_p): Delete.
	(struct lang_type_header): New.
	(struct lang_type_class): Rename from struct lang_type.  Include
	struct lang_type_header.
	(struct lang_type_ptrmem): New.
	(struct lang_type): New.
	(LANG_TYPE_CLASS_CHECK): New.  Use it in all the appropriate macros.
	(LANG_TYPE_PTRMEM_CHECK): New.  Use it in all the appropriate macros.
	(TYPE_SET_PTRMEMFUNC_TYPE): Set discriminator, update for changes.
	(struct lang_decl_flags): Use gengtype.  Add discriminators.
	(struct lang_decl): Use gengtype.  Add and use discriminators.
	Update the macros that reference moved fields.
	(LANG_DECL_U2_CHECK): New function.  Use it when appropriate.
	(SET_DECL_THUNK_P): Set discriminator too.
	(clear_inline_text_obstack): Delete prototype.
	(finish_inline_definitions): Delete prototype.
	(mark_pending_inlines): Delete prototype.
	(lang_check_failed): New prototype.
	* decl.c (struct named_label_use_list): Use gengtype.
	(struct named_label_list): Likewise.
	(mark_binding_level): Delete.
	(mark_named_label_lists): Delete.
	(push_local_name): Set discriminator on DECL_LANG_SPECIFIC.
	(cxx_init_decl_processing): Use generated marker routine.
	(begin_destructor_body): Delete dead set to
	current_vcalls_possible_p.
	(mark_lang_function): Delete.
	(mark_cp_function_context): Delete.
	(lang_mark_tree): Use generated marker routines.
	* decl2.c (start_objects): Set discriminator when setting
	GLOBAL_INIT_PRIORITY.
	* lex.c (retrofit_lang_decl): Set discriminators.
	(copy_lang_type): Update for changes to lang_type structure.
	(cp_make_lang_type): Set discriminator.
	* parse.y: Use gengtype on YYLVAL.  Don't use dots in identifiers.
	* search.c: Include ggc.h.
	* semantics.c (anon_aggr_type_p): Use the macro, don't hand-code it.
	(finish_inline_definitions): Delete.
	* spew.c (struct token): Use gengtype.
	(struct token_chunk): New.
	(struct unparsed_text): Use gengtype.  Store tokens in chunks.
	(struct feed): Use gengtype.
	(feed_obstack): Delete.
	(feed): Mark as GC root.
	(pending_inlines): Mark as GC root.
	(pending_inlines_tail): Likewise.
	(processing_these_inlines): Likewise.
	(token_obstack): Make static.
	(first_token): Likewise.
	(init_spew): Don't initialise deleted things; use gengtype for roots.
	(clear_inline_text_obstack): Delete.
	(feed_input): Use GC for struct feed.  Update for changes to
	struct unparsed_text.
	(mark_pending_inlines): Delete.
	(next_token): Rename from add_token.  Change all callers.  Update
	for changes to struct unparsed_text.
	(space_for_token): New.
	(remove_last_token): New.
	(alloc_unparsed_text): New.
	(snarf_block): Take an unparsed_text.  Update for changes to struct
	unparsed_text.
	(snarf_method): Update for changes to struct unparsed_text.
	(snarf_defarg): Update for changes to struct unparsed_text.
	* tree.c (lang_check_failed): New.

Index: gengtype-lex.l
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gengtype-lex.l,v
retrieving revision 1.1.2.4
diff -p -u -p -r1.1.2.4 gengtype-lex.l
--- gengtype-lex.l	15 Apr 2002 21:16:09 -0000	1.1.2.4
+++ gengtype-lex.l	27 Apr 2002 19:22:13 -0000
@@ -52,7 +52,7 @@ WS	[[:space:]]+
 IWORD	short|long|(un)?signed|char|int|HOST_WIDE_INT
 ITYPE	{IWORD}({WS}{IWORD})*
 
-%x in_struct in_struct_comment in_comment
+%x in_struct in_struct_comment in_comment in_yacc_escape
 %option warn noyywrap nounput nodefault perf-report
 %option 8bit never-interactive
 %%
@@ -91,6 +91,7 @@ ITYPE	{IWORD}({WS}{IWORD})*
 }
 
 [^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
+
   char *namestart;
   size_t namelen;
   struct type *t;
@@ -163,13 +164,22 @@ ITYPE	{IWORD}({WS}{IWORD})*
 
 [^[:alnum:]_](extern|static){WS}/"GTY" {
   BEGIN(in_struct);
+  update_lineno (yytext, yyleng);
   return ENT_EXTERNSTATIC;
 }
 
+^"%union"{WS}"{"{WS}/"GTY" {
+  BEGIN(in_struct);
+  update_lineno (yytext, yyleng);
+  return ENT_YACCUNION;
+}
+
 <in_struct>{
 
 "/*"				{ BEGIN(in_struct_comment); }
 
+^"%{"				{ BEGIN(in_yacc_escape); }
+
 {WS}				{ update_lineno (yytext, yyleng); }
 
 "const"/[^[:alnum:]_]		/* don't care */
@@ -206,8 +216,16 @@ ITYPE	{IWORD}({WS}{IWORD})*
   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
   return ARRAY;
 }
+^"%"{ID}			{
+  yylval.s = xmemdup (yytext+1, yyleng-1, yyleng);
+  return PERCENT_ID;
+}
+"'"("\\".|[^\\])"'"		{
+  yylval.s = xmemdup (yytext+1, yyleng-2, yyleng);
+  return CHAR;
+}
 
-[(){},*:]			{ return yytext[0]; }
+[(){},*:<>]			{ return yytext[0]; }
 
 [;=]				{
   if (lexer_toplevel_done)
@@ -218,6 +236,11 @@ ITYPE	{IWORD}({WS}{IWORD})*
   return yytext[0];
 }
 
+^"%%"				{
+  BEGIN(INITIAL);
+  return PERCENTPERCENT;
+}
+
 .				{
   error_at_line (&lexer_line, "unexpected character `%s'", yytext);
 }
@@ -238,6 +261,19 @@ ITYPE	{IWORD}({WS}{IWORD})*
 }
 <in_comment>"*/"	{ BEGIN(INITIAL); } 
 <in_struct_comment>"*/"	{ BEGIN(in_struct); }
+
+<in_yacc_escape>{
+\n		{ lexer_line.line++; }
+[^%]{16}	|
+[^%]		/* do nothing */
+"%"/[^}]	/* do nothing */
+"%}"		{ BEGIN(in_struct); }
+"%"		{
+  error_at_line (&lexer_line, 
+		 "unterminated %{; unexpected EOF");
+}
+}
+
 
 ["/]    		|
 <in_struct_comment,in_comment>"*"	{
Index: gengtype-yacc.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gengtype-yacc.y,v
retrieving revision 1.1.2.5
diff -p -u -p -r1.1.2.5 gengtype-yacc.y
--- gengtype-yacc.y	15 Apr 2002 21:16:10 -0000	1.1.2.5
+++ gengtype-yacc.y	27 Apr 2002 19:22:13 -0000
@@ -36,18 +36,22 @@ Software Foundation, 59 Temple Place - S
 %token <t>ENT_TYPEDEF_STRUCT
 %token <t>ENT_STRUCT
 %token ENT_EXTERNSTATIC
+%token ENT_YACCUNION
 %token GTY_TOKEN "GTY"
 %token UNION "union"
 %token STRUCT "struct"
 %token ENUM "enum"
 %token VARRAY_TYPE "varray_type"
 %token NUM
+%token PERCENTPERCENT "%%"
 %token <t>SCALAR
 %token <s>ID
 %token <s>STRING
 %token <s>ARRAY
+%token <s>PERCENT_ID
+%token <s>CHAR
 
-%type <p> struct_fields
+%type <p> struct_fields yacc_ids yacc_typematch
 %type <t> type lasttype
 %type <o> optionsopt options option optionseq optionseqopt
 
@@ -56,6 +60,7 @@ Software Foundation, 59 Temple Place - S
 start: /* empty */
        | typedef_struct start
        | externstatic start
+       | yacc_union start
 
 typedef_struct: ENT_TYPEDEF_STRUCT options 
 		   { 
@@ -105,6 +110,71 @@ lasttype: type
 
 semiequal: ';'
 	   | '='
+	   ;
+
+yacc_union: ENT_YACCUNION options struct_fields '}' yacc_typematch PERCENTPERCENT
+	      {
+	        note_yacc_type ($2, $3, $5, &lexer_line);
+	      }
+
+yacc_typematch: /* empty */
+		   { $$ = NULL; }
+		| yacc_typematch PERCENT_ID yacc_ids
+		   { 
+		     pair_p p;
+		     for (p = $3; p->next != NULL; p = p->next)
+		       {
+		         p->name = NULL;
+			 p->type = NULL;
+		       }
+		     p->name = NULL;
+		     p->type = NULL;
+		     p->next = $1;
+		     $$ = $3;
+		   }
+		| yacc_typematch PERCENT_ID '<' ID '>' yacc_ids
+		   {
+		     pair_p p;
+		     type_p newtype = NULL;
+		     if (strcmp ($2, "type") == 0)
+		       newtype = (type_p) 1;
+		     for (p = $6; p->next != NULL; p = p->next)
+		       {
+		         p->name = $4;
+		         p->type = newtype;
+		       }
+		     p->name = $4;
+		     p->next = $1;
+		     p->type = newtype;
+		     $$ = $6;
+		   }
+		;
+
+yacc_ids: /* empty */
+	{ $$ = NULL; }
+     | yacc_ids ID
+        { 
+	  pair_p p = xcalloc (1, sizeof (*p));
+	  p->next = $1;
+	  p->line = lexer_line;
+	  p->opt = xmalloc (sizeof (*(p->opt)));
+	  p->opt->name = "tag";
+	  p->opt->next = NULL;
+	  p->opt->info = $2;
+	  $$ = p;
+	}
+     | yacc_ids CHAR
+        {
+	  pair_p p = xcalloc (1, sizeof (*p));
+	  p->next = $1;
+	  p->line = lexer_line;
+	  p->opt = xmalloc (sizeof (*(p->opt)));
+	  p->opt->name = "tag";
+	  p->opt->next = NULL;
+	  p->opt->info = xmalloc (3 + strlen ($2));
+	  sprintf (p->opt->info, "'%s'", $2);
+	  $$ = p;
+	}
 
 struct_fields: { $$ = NULL; }
 	       | type optionsopt ID bitfieldopt ';' struct_fields
@@ -193,9 +263,13 @@ type: SCALAR
          { $$ = create_scalar_type ($2, strlen ($2)); }
 
 enum_items: /* empty */
-	    | ID '=' NUM ',' enum_items {}
-	    | ID ',' enum_items {}
-	    | ID enum_items {}
+	    | ID '=' NUM ',' enum_items
+	      { }
+	    | ID ',' enum_items
+	      { }
+	    | ID enum_items
+	      { }
+	    ;
 
 optionsopt: { $$ = NULL; }
 	    | options { $$ = $1; }
@@ -222,10 +296,10 @@ optionseq: option
 	        $1->next = NULL;
 		$$ = $1;
 	      }
-	    | option ',' optionseq
+	    | optionseq ',' option
 	      {
-	        $1->next = $3;
-		$$ = $1;
+	        $3->next = $1;
+		$$ = $3;
 	      }
 
 optionseqopt: { $$ = NULL }
Index: gengtype.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gengtype.c,v
retrieving revision 1.1.2.9
diff -p -u -p -r1.1.2.9 gengtype.c
--- gengtype.c	15 Apr 2002 21:16:10 -0000	1.1.2.9
+++ gengtype.c	27 Apr 2002 19:22:13 -0000
@@ -210,6 +210,75 @@ note_variable (s, t, o, pos)
   n->next = variables;
   variables = n;
 }
+
+void
+note_yacc_type (o, fields, typeinfo, pos)
+     options_p o;
+     pair_p fields;
+     pair_p typeinfo;
+     struct fileloc *pos;
+{
+  type_p t = find_structure ("yy_union", 1, pos);
+  pair_p p;
+  pair_p *p_p;
+  
+  for (p = typeinfo; p; p = p->next)
+    {
+      pair_p m;
+      
+      if (p->name == NULL)
+	continue;
+
+      if (p->type == (type_p) 1)
+	{
+	  pair_p pp;
+	  int ok = 0;
+	  
+	  for (pp = typeinfo; pp; pp = pp->next)
+	    if (pp->type != (type_p) 1
+		&& strcmp (pp->opt->info, p->opt->info) == 0)
+	      {
+		ok = 1;
+		break;
+	      }
+	  if (! ok)
+	    continue;
+	}
+
+      for (m = fields; m; m = m->next)
+	if (strcmp (m->name, p->name) == 0)
+	  p->type = m->type;
+      if (p->type == NULL)
+	{
+	  error_at_line (&p->line, 
+			 "couldn't match fieldname `%s'", p->name);
+	  p->name = NULL;
+	}
+    }
+  
+  p_p = &typeinfo;
+  while (*p_p)
+    {
+      pair_p p = *p_p;
+
+      if (p->name == NULL
+	  || p->type == (type_p) 1)
+	*p_p = p->next;
+      else
+	p_p = &p->next;
+    }
+
+  t->u.s.fields = typeinfo;
+  t->u.s.opt = o;
+  if (t->u.s.line.file)
+    {
+      error_at_line (pos, 
+		     "duplicate structure definition");
+      error_at_line (&t->u.s.line, "previous definition here");
+    }
+  t->u.s.line = lexer_line;
+  do_typedef ("YYSTYPE", t, pos);
+}
 
 /* File mapping routines.  For each input file, there is one output .c file
    (but some output files have many input files), and there is one .h file
Index: gengtype.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gengtype.h,v
retrieving revision 1.1.2.4
diff -p -u -p -r1.1.2.4 gengtype.h
--- gengtype.h	15 Apr 2002 21:16:10 -0000	1.1.2.4
+++ gengtype.h	27 Apr 2002 19:22:13 -0000
@@ -100,6 +100,8 @@ extern type_p create_array PARAMS ((type
 extern type_p adjust_field_type PARAMS ((type_p, options_p));
 extern void note_variable PARAMS ((const char *s, type_p t, options_p o,
 				   struct fileloc *pos));
+extern void note_yacc_type PARAMS ((options_p o, pair_p fields,
+				    pair_p typeinfo, struct fileloc *pos));
 
 /* Lexer and parser routines, most automatically generated.  */
 extern int yylex PARAMS((void));
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.430.2.2
diff -p -u -p -r1.430.2.2 class.c
--- cp/class.c	14 Mar 2002 21:37:08 -0000	1.430.2.2
+++ cp/class.c	27 Apr 2002 19:22:18 -0000
@@ -2165,6 +2165,7 @@ duplicate_tag_error (t)
       memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
       BINFO_BASETYPES(binfo) = NULL_TREE;
 
+      TYPE_LANG_SPECIFIC (t)->u.h.is_lang_type_class = 1;
       TYPE_BINFO (t) = binfo;
       CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
@@ -4380,7 +4381,7 @@ check_bases_and_members (t, empty_p)
 
   /* Figure out whether or not we will need a cookie when dynamically
      allocating an array of this type.  */
-  TYPE_LANG_SPECIFIC (t)->vec_new_uses_cookie
+  TYPE_LANG_SPECIFIC (t)->u.c.vec_new_uses_cookie
     = type_requires_array_cookie (t);
 }
 
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.671.2.4
diff -p -u -p -r1.671.2.4 cp-tree.h
--- cp/cp-tree.h	9 Apr 2002 21:57:09 -0000	1.671.2.4
+++ cp/cp-tree.h	27 Apr 2002 19:22:18 -0000
@@ -254,13 +254,14 @@ extern const short rid_to_yy[RID_MAX];
 #define LANG_IDENTIFIER_CAST(NODE) \
 	((struct lang_identifier*)IDENTIFIER_NODE_CHECK (NODE))
 
-struct lang_id2
+struct lang_id2 GTY(())
 {
-  tree label_value, implicit_decl;
+  tree label_value;
+  tree implicit_decl;
   tree error_locus;
 };
 
-typedef struct
+typedef struct flagged_type_tree_s GTY(())
 {
   tree t;
   int new_type_flag;
@@ -451,10 +452,10 @@ struct tree_srcloc
   (LANG_IDENTIFIER_CAST (NODE)->x			\
    ? LANG_IDENTIFIER_CAST (NODE)->x->NAME : 0)
 
-#define SET_LANG_ID(NODE, VALUE, NAME)					  \
-  (LANG_IDENTIFIER_CAST (NODE)->x == 0				  	  \
-   ? LANG_IDENTIFIER_CAST (NODE)->x					  \
-      = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
+#define SET_LANG_ID(NODE, VALUE, NAME)					     \
+  (LANG_IDENTIFIER_CAST (NODE)->x == 0					     \
+   ? LANG_IDENTIFIER_CAST (NODE)->x					     \
+      = (struct lang_id2 *)ggc_alloc_cleared (sizeof (struct lang_id2)) : 0, \
    LANG_IDENTIFIER_CAST (NODE)->x->NAME = (VALUE))
 
 #define IDENTIFIER_LABEL_VALUE(NODE) \
@@ -809,7 +810,7 @@ struct unparsed_text;
 
 /* Global state pertinent to the current function.  */
 
-struct cp_language_function
+struct cp_language_function GTY(())
 {
   struct language_function base;
 
@@ -821,8 +822,6 @@ struct cp_language_function
   tree x_vtt_parm;
   tree x_return_value;
 
-  tree *x_vcalls_possible_p;
-
   int returns_value;
   int returns_null;
   int returns_abnormally;
@@ -832,7 +831,7 @@ struct cp_language_function
   struct named_label_use_list *x_named_label_uses;
   struct named_label_list *x_named_labels;
   struct cp_binding_level *bindings;
-  varray_type x_local_names;
+  varray_type GTY ((varray_type (tree))) x_local_names;
 
   const char *cannot_inline;
   struct unparsed_text *unparsed_inlines;
@@ -872,12 +871,6 @@ struct cp_language_function
 
 #define current_vtt_parm cp_function_chain->x_vtt_parm
 
-/* In destructors, this is a pointer to a condition in an
-   if-statement.  If the pointed-to value is boolean_true_node, then
-   there may be virtual function calls in this destructor.  */
-
-#define current_vcalls_possible_p cp_function_chain->x_vcalls_possible_p
-
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
@@ -1187,6 +1180,22 @@ enum languages { lang_c, lang_cplusplus,
 #define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
   lookup_base ((TYPE), (PARENT),  ba_not_special | ba_quiet, NULL)
 
+/* This is a few header flags for 'struct lang_type'.  Actually,
+   all but the first are used only for lang_type_class; they
+   are put in this structure to save space.  */
+struct lang_type_header GTY(())
+{
+  unsigned is_lang_type_class : 1;
+
+  unsigned has_type_conversion : 1;
+  unsigned has_init_ref : 1;
+  unsigned has_default_ctor : 1;
+  unsigned uses_multiple_inheritance : 1;
+  unsigned const_needs_init : 1;
+  unsigned ref_needs_init : 1;
+  unsigned has_const_assign_ref : 1;
+};
+
 /* This structure provides additional information above and beyond
    what is provide in the ordinary tree_type.  In the past, we used it
    for the types of class types, template parameters types, typename
@@ -1200,19 +1209,12 @@ enum languages { lang_c, lang_cplusplus,
    many (i.e., thousands) of classes can easily be generated.
    Therefore, we should endeavor to keep the size of this structure to
    a minimum.  */
-struct lang_type
+struct lang_type_class GTY(())
 {
+  struct lang_type_header h;
+  
   unsigned char align;
 
-  unsigned has_type_conversion : 1;
-  unsigned has_init_ref : 1;
-  unsigned has_default_ctor : 1;
-  unsigned uses_multiple_inheritance : 1;
-  unsigned const_needs_init : 1;
-  unsigned ref_needs_init : 1;
-  unsigned has_const_assign_ref : 1;
-  unsigned anon_aggr : 1;
-
   unsigned has_mutable : 1;
   unsigned com_interface : 1;
   unsigned non_pod_class : 1;
@@ -1251,6 +1253,7 @@ struct lang_type
   unsigned is_partial_instantiation : 1;
   unsigned java_interface : 1;
 
+  unsigned anon_aggr : 1;
   /* When adding a flag here, consider whether or not it ought to
      apply to a template instance if it applies to the template.  If
      so, make sure to copy it in instantiate_class_template!  */
@@ -1258,7 +1261,7 @@ struct lang_type
   /* There are some bits left to fill out a 32-bit word.  Keep track
      of this by updating the size of this bitfield whenever you add or
      remove a flag.  */
-  unsigned dummy : 8;
+  unsigned dummy : 7;
 
   int vsize;
 
@@ -1276,12 +1279,50 @@ struct lang_type
   tree befriending_classes;
 };
 
+struct lang_type_ptrmem GTY(())
+{
+  struct lang_type_header h;
+  tree record;
+};
+
+struct lang_type GTY(())
+{
+  union lang_type_u 
+  {
+    struct lang_type_header GTY((tag ("2"))) h;
+    struct lang_type_class  GTY((tag ("1"))) c;
+    struct lang_type_ptrmem GTY((tag ("0"))) ptrmem;
+  } GTY((desc ("%h.h.is_lang_type_class"))) u;
+};
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+#define LANG_TYPE_CLASS_CHECK(NODE)				\
+({  struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE);		\
+    if (! lt->u.h.is_lang_type_class)				\
+      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
+    &lt->u.c; })
+
+#define LANG_TYPE_PTRMEM_CHECK(NODE)				\
+({  struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE);		\
+    if (lt->u.h.is_lang_type_class)				\
+      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
+    &lt->u.ptrmem; })
+
+#else
+
+#define LANG_TYPE_CLASS_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.c)
+#define LANG_TYPE_PTRMEM_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.p)
+
+#endif /* ENABLE_TREE_CHECKING */
+
 /* Indicates whether or not (and how) a template was expanded for this class.
      0=no information yet/non-template class
      1=implicit template instantiation
      2=explicit template specialization
      3=explicit template instantiation  */
-#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC (NODE)->use_template)
+#define CLASSTYPE_USE_TEMPLATE(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
 
 /* Fields used for storing information before the class is defined.
    After the class is defined, these fields hold other information.  */
@@ -1290,66 +1331,66 @@ struct lang_type
 #define CLASSTYPE_INLINE_FRIENDS(NODE) CLASSTYPE_PURE_VIRTUALS (NODE)
 
 /* Nonzero for _CLASSTYPE means that operator delete is defined.  */
-#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC (NODE)->gets_delete)
+#define TYPE_GETS_DELETE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->gets_delete)
 #define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
 
 /* Nonzero if `new NODE[x]' should cause the allocation of extra
    storage to indicate how many array elements are in use.  */
 #define TYPE_VEC_NEW_USES_COOKIE(NODE)			\
   (CLASS_TYPE_P (NODE)					\
-   && TYPE_LANG_SPECIFIC (NODE)->vec_new_uses_cookie)
+   && LANG_TYPE_CLASS_CHECK (NODE)->vec_new_uses_cookie)
 
 /* Nonzero means that this _CLASSTYPE node defines ways of converting
    itself to other types.  */
 #define TYPE_HAS_CONVERSION(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_type_conversion)
+  (LANG_TYPE_CLASS_CHECK (NODE)->h.has_type_conversion)
 
 /* Nonzero means that this _CLASSTYPE node overloads operator=(X&).  */
-#define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_assign_ref)
+#define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref)
 #define TYPE_HAS_CONST_ASSIGN_REF(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_const_assign_ref)
+  (LANG_TYPE_CLASS_CHECK (NODE)->h.has_const_assign_ref)
 
 /* Nonzero means that this _CLASSTYPE node has an X(X&) constructor.  */
-#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_init_ref)
+#define TYPE_HAS_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->h.has_init_ref)
 #define TYPE_HAS_CONST_INIT_REF(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_const_init_ref)
+  (LANG_TYPE_CLASS_CHECK (NODE)->has_const_init_ref)
 
 /* Nonzero if this class defines an overloaded operator new.  (An
    operator new [] doesn't count.)  */
 #define TYPE_HAS_NEW_OPERATOR(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_new)
+  (LANG_TYPE_CLASS_CHECK (NODE)->has_new)
 
 /* Nonzero if this class defines an overloaded operator new[].  */
 #define TYPE_HAS_ARRAY_NEW_OPERATOR(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_array_new)
+  (LANG_TYPE_CLASS_CHECK (NODE)->has_array_new)
 
 /* Nonzero means that this type is being defined.  I.e., the left brace
    starting the definition of this type has been seen.  */
-#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC (NODE)->being_defined)
+#define TYPE_BEING_DEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->being_defined)
 /* Nonzero means that this type has been redefined.  In this case, if
    convenient, don't reprocess any methods that appear in its redefinition.  */
-#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC (NODE)->redefined)
+#define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
 
 /* The is the basetype that contains NODE's rtti.  */
-#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC (NODE)->rtti)
+#define CLASSTYPE_RTTI(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->rtti)
 
 /* Nonzero means that this _CLASSTYPE node overloads operator().  */
 #define TYPE_OVERLOADS_CALL_EXPR(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_call_overloaded)
+  (LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded)
 
 /* Nonzero means that this _CLASSTYPE node overloads operator[].  */
 #define TYPE_OVERLOADS_ARRAY_REF(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_array_ref_overloaded)
+  (LANG_TYPE_CLASS_CHECK (NODE)->has_array_ref_overloaded)
 
 /* Nonzero means that this _CLASSTYPE node overloads operator->.  */
 #define TYPE_OVERLOADS_ARROW(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_arrow_overloaded)
+  (LANG_TYPE_CLASS_CHECK (NODE)->has_arrow_overloaded)
 
 /* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
    multiple inheritance.  If this is 0 for the root of a type
    hierarchy, then we can use more efficient search techniques.  */
 #define TYPE_USES_MULTIPLE_INHERITANCE(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->uses_multiple_inheritance)
+  (LANG_TYPE_CLASS_CHECK (NODE)->h.uses_multiple_inheritance)
 
 /* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
    virtual base classes.  If this is 0 for the root of a type
@@ -1362,7 +1403,7 @@ struct lang_type
    two elements are for constructors, and destructors, respectively.
    Any conversion operators are next, followed by ordinary member
    functions.  There may be empty entries at the end of the vector.  */
-#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC (NODE)->methods)
+#define CLASSTYPE_METHOD_VEC(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->methods)
 
 /* The slot in the CLASSTYPE_METHOD_VEC where constructors go.  */
 #define CLASSTYPE_CONSTRUCTOR_SLOT 0
@@ -1388,19 +1429,19 @@ struct lang_type
 
 /* Get the value of the Nth mark bit.  */
 #define CLASSTYPE_MARKED_N(NODE, N)				\
-  (((CLASS_TYPE_P (NODE) ? TYPE_LANG_SPECIFIC (NODE)->marks	\
+  (((CLASS_TYPE_P (NODE) ? LANG_TYPE_CLASS_CHECK (NODE)->marks	\
      : ((unsigned) TYPE_ALIAS_SET (NODE))) & (1 << (N))) != 0)
 
 /* Set the Nth mark bit.  */
 #define SET_CLASSTYPE_MARKED_N(NODE, N)				\
   (CLASS_TYPE_P (NODE)						\
-   ? (void) (TYPE_LANG_SPECIFIC (NODE)->marks |= (1 << (N)))	\
+   ? (void) (LANG_TYPE_CLASS_CHECK (NODE)->marks |= (1 << (N)))	\
    : (void) (TYPE_ALIAS_SET (NODE) |= (1 << (N))))
 
 /* Clear the Nth mark bit.  */
 #define CLEAR_CLASSTYPE_MARKED_N(NODE, N)			\
   (CLASS_TYPE_P (NODE)						\
-   ? (void) (TYPE_LANG_SPECIFIC (NODE)->marks &= ~(1 << (N)))	\
+   ? (void) (LANG_TYPE_CLASS_CHECK (NODE)->marks &= ~(1 << (N)))	\
    : (void) (TYPE_ALIAS_SET (NODE) &= ~(1 << (N))))
 
 /* Get the value of the mark bits.  */
@@ -1429,7 +1470,7 @@ struct lang_type
    found within this class.  The TREE_PURPOSE of each node is the name
    of the type; the TREE_VALUE is the type itself.  This list includes
    nested member class templates.  */
-#define CLASSTYPE_TAGS(NODE)		(TYPE_LANG_SPECIFIC (NODE)->tags)
+#define CLASSTYPE_TAGS(NODE)		(LANG_TYPE_CLASS_CHECK (NODE)->tags)
 
 /* Nonzero if NODE has a primary base class, i.e., a base class with
    which it shares the virtual function table pointer.  */
@@ -1440,11 +1481,11 @@ struct lang_type
    the base class which contains the virtual function table pointer
    for this class.  */
 #define CLASSTYPE_PRIMARY_BINFO(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->primary_base)
+  (LANG_TYPE_CLASS_CHECK (NODE)->primary_base)
 
 /* The number of virtual functions present in this class' virtual
    function table.  */
-#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC (NODE)->vsize)
+#define CLASSTYPE_VSIZE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vsize)
 
 /* A chain of BINFOs for the direct and indirect virtual base classes
    that this type uses in a post-order depth-first left-to-right
@@ -1454,7 +1495,7 @@ struct lang_type
    list are all "real"; they are the same BINFOs that will be
    encountered when using dfs_unmarked_real_bases_queue_p and related
    functions.  */
-#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC (NODE)->vbases)
+#define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases)
 
 /* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
    binfo_for_vbase.  C is the most derived class for the hierarchy
@@ -1470,10 +1511,10 @@ struct lang_type
 
 /* These are the size and alignment of the type without its virtual
    base classes, for when we use this type as a base itself.  */
-#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC (NODE)->size)
-#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC (NODE)->size_unit)
-#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC (NODE)->align)
-#define CLASSTYPE_USER_ALIGN(NODE) (TYPE_LANG_SPECIFIC (NODE)->user_align)
+#define CLASSTYPE_SIZE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size)
+#define CLASSTYPE_SIZE_UNIT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size_unit)
+#define CLASSTYPE_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->align)
+#define CLASSTYPE_USER_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->user_align)
 
 /* The alignment of NODE, without its virtual bases, in bytes.  */
 #define CLASSTYPE_ALIGN_UNIT(NODE) \
@@ -1481,65 +1522,65 @@ struct lang_type
 
 /* True if this a Java interface type, declared with 
    '__attribute__ ((java_interface))'. */
-#define TYPE_JAVA_INTERFACE(NODE) (TYPE_LANG_SPECIFIC (NODE)->java_interface)
+#define TYPE_JAVA_INTERFACE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->java_interface)
 
 /* A cons list of virtual functions which cannot be inherited by
    derived classes.  When deriving from this type, the derived
    class must provide its own definition for each of these functions.  */
-#define CLASSTYPE_PURE_VIRTUALS(NODE) (TYPE_LANG_SPECIFIC (NODE)->pure_virtuals)
+#define CLASSTYPE_PURE_VIRTUALS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals)
 
 /* Nonzero means that this aggr type has been `closed' by a semicolon.  */
-#define CLASSTYPE_GOT_SEMICOLON(NODE) (TYPE_LANG_SPECIFIC (NODE)->got_semicolon)
+#define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon)
 
 /* Nonzero means that the main virtual function table pointer needs to be
    set because base constructors have placed the wrong value there.
    If this is zero, it means that they placed the right value there,
    and there is no need to change it.  */
 #define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->needs_virtual_reinit)
+  (LANG_TYPE_CLASS_CHECK (NODE)->needs_virtual_reinit)
 
 /* Nonzero means that this type has an X() constructor.  */
 #define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->has_default_ctor)
+  (LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
 
 /* Nonzero means that this type contains a mutable member */
-#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_mutable)
+#define CLASSTYPE_HAS_MUTABLE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_mutable)
 #define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
 
 /*  Nonzero means that this class type is a non-POD class.  */
-#define CLASSTYPE_NON_POD_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_pod_class)
+#define CLASSTYPE_NON_POD_P(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
 
 /* Nonzero if this class is "nearly empty", i.e., contains only a
    virtual function table pointer.  */
 #define CLASSTYPE_NEARLY_EMPTY_P(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->nearly_empty_p)
+  (LANG_TYPE_CLASS_CHECK (NODE)->nearly_empty_p)
 
 /* A list of class types of which this type is a friend.  The
    TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
    case of a template friend.  */
 #define CLASSTYPE_FRIEND_CLASSES(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->friend_classes)
+  (LANG_TYPE_CLASS_CHECK (NODE)->friend_classes)
 
 /* A list of the classes which grant friendship to this class.  */
 #define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->befriending_classes)
+  (LANG_TYPE_CLASS_CHECK (NODE)->befriending_classes)
 
 /* Say whether this node was declared as a "class" or a "struct".  */
 #define CLASSTYPE_DECLARED_CLASS(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->declared_class)
+  (LANG_TYPE_CLASS_CHECK (NODE)->declared_class)
 
 /* Nonzero if this class has const members which have no specified initialization.  */
 #define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->const_needs_init)
+  (LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init)
 
 /* Nonzero if this class has ref members which have no specified initialization.  */
 #define CLASSTYPE_REF_FIELDS_NEED_INIT(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->ref_needs_init)
+  (LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init)
 
 /* Nonzero if this class is included from a header file which employs
    `#pragma interface', and it is not included in its implementation file.  */
 #define CLASSTYPE_INTERFACE_ONLY(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->interface_only)
+  (LANG_TYPE_CLASS_CHECK (NODE)->interface_only)
 
 /* True if we have already determined whether or not vtables, VTTs,
    typeinfo, and other similar per-class data should be emitted in
@@ -1547,21 +1588,21 @@ struct lang_type
    these items should be emitted; it only indicates that we know one
    way or the other.  */
 #define CLASSTYPE_INTERFACE_KNOWN(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->interface_unknown == 0)
+  (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown == 0)
 /* The opposite of CLASSTYPE_INTERFANCE_KNOWN.  */
 #define CLASSTYPE_INTERFACE_UNKNOWN(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->interface_unknown)
+  (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown)
 
 #define SET_CLASSTYPE_INTERFACE_UNKNOWN_X(NODE,X) \
-  (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = !!(X))
+  (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = !!(X))
 #define SET_CLASSTYPE_INTERFACE_UNKNOWN(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = 1)
+  (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = 1)
 #define SET_CLASSTYPE_INTERFACE_KNOWN(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = 0)
+  (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = 0)
 
 /* Nonzero if a _DECL node requires us to output debug info for this class.  */
 #define CLASSTYPE_DEBUG_REQUESTED(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->debug_requested)
+  (LANG_TYPE_CLASS_CHECK (NODE)->debug_requested)
 
 /* Additional macros for inheritance information.  */
 
@@ -1676,7 +1717,7 @@ struct lang_type
    TREE_PURPOSE is NULL.  Otherwise, the TREE_PURPOSE is the BINFO for
    the class containing the vfield.  The TREE_VALUE is the class where
    the vfield was first defined.  */
-#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC (NODE)->vfields)
+#define CLASSTYPE_VFIELDS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vfields)
 
 /* Get the assoc info that caused this vfield to exist.  */
 #define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE)
@@ -1736,7 +1777,7 @@ struct lang_type
      || TREE_CODE (NODE) == FIELD_DECL		\
      || TREE_CODE (NODE) == USING_DECL))
 
-struct lang_decl_flags
+struct lang_decl_flags GTY(())
 {
   struct c_lang_decl base;
 
@@ -1757,26 +1798,28 @@ struct lang_decl_flags
   unsigned not_really_extern : 1;
   unsigned needs_final_overrider : 1;
   unsigned initialized_in_class : 1;
-  unsigned pending_inline_p : 1;
+  unsigned assignment_operator_p : 1;
 
   unsigned global_ctor_p : 1;
   unsigned global_dtor_p : 1;
-  unsigned assignment_operator_p : 1;
   unsigned anticipated_p : 1;
-  /* Four unused bits.  */
+  unsigned u1sel : 1;
+  unsigned u2sel : 1;
+  unsigned can_be_full : 1;
+  /* 2 unused bits.  */
 
-  union {
+  union lang_decl_u {
     /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
        is DECL_TEMPLATE_INFO.  */
-    tree template_info;
+    tree GTY ((tag ("0"))) template_info;
 
     /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL.  */
-    struct cp_binding_level *level;
-  } u;
+    struct cp_binding_level * GTY ((tag ("1"))) level;
+  } GTY ((desc ("%1.u1sel"))) u;
 
-  union {
+  union lang_decl_u2 {
     /* This is DECL_ACCESS.  */
-    tree access;
+    tree GTY ((tag ("0"))) access;
 
     /* For VAR_DECL in function, this is DECL_DISCRIMINATOR.  */
     int discriminator;
@@ -1787,36 +1830,59 @@ struct lang_decl_flags
 
     /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
        THUNK_VCALL_OFFSET.  */
-    tree vcall_offset;
-  } u2;
+    tree GTY((tag ("2"))) vcall_offset;
+  } GTY ((desc ("%1.u2sel"))) u2;
 };
 
-struct lang_decl
+struct lang_decl GTY(())
 {
   struct lang_decl_flags decl_flags;
 
-  tree befriending_classes;
+  union lang_decl_u4
+    {
+      struct full_lang_decl 
+      {
+	tree befriending_classes;
+	
+	/* For a virtual FUNCTION_DECL, this is DECL_VIRTUAL_CONTEXT.  For a
+	   non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT.  */
+	tree context;
+	
+	/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
+	tree cloned_function;
+	
+	/* In an overloaded operator, this is the value of
+	   DECL_OVERLOADED_OPERATOR_P.  */
+	enum tree_code operator_code;
+
+	unsigned u3sel : 1;
+	unsigned pending_inline_p : 1;
+	
+	union lang_decl_u3
+	{
+	  tree GTY ((tag ("0"))) sorted_fields;
+	  struct unparsed_text * GTY ((tag ("2"))) pending_inline_info;
+	  struct cp_language_function * GTY ((tag ("1"))) 
+	       saved_language_function;
+	} GTY ((desc ("%1.u3sel + %1.pending_inline_p"))) u;
+      } GTY ((tag ("1"))) f;
+  } GTY ((desc ("%1.decl_flags.can_be_full"))) u;
+};
 
-  /* For a virtual FUNCTION_DECL, this is DECL_VIRTUAL_CONTEXT.  For a
-     non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT.  */
-  tree context;
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 
-  /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
-  tree cloned_function;
+#define LANG_DECL_U2_CHECK(NODE, TF)				\
+({  struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE);		\
+    if (lt->decl_flags.u2sel != TF)				\
+      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
+    &lt->decl_flags.u2; })
 
-  union
-  {
-    tree sorted_fields;
-    struct unparsed_text *pending_inline_info;
-    struct cp_language_function *saved_language_function;
-  } u;
+#else
 
-  union {
-    /* In an overloaded operator, this is the value of
-       DECL_OVERLOADED_OPERATOR_P.  */
-    enum tree_code operator_code;
-  } u2;
-};
+#define LANG_DECL_U2_CHECK(NODE, TF) \
+  (&DECL_LANG_SPECIFIC (NODE)->decl_flags.u2)
+
+#endif /* ENABLE_TREE_CHECKING */
 
 #define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK (NODE)->identifier.id.str)
 
@@ -1925,7 +1991,7 @@ struct lang_decl
 /* If DECL_CLONED_FUNCTION_P holds, this is the function that was
    cloned.  */
 #define DECL_CLONED_FUNCTION(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->cloned_function)
+  (DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function)
 
 /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS.  */
 #define DECL_DISCRIMINATOR_P(NODE)	\
@@ -1933,8 +1999,7 @@ struct lang_decl
    && DECL_FUNCTION_SCOPE_P (NODE))
 
 /* Discriminator for name mangling.  */
-#define DECL_DISCRIMINATOR(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.discriminator)
+#define DECL_DISCRIMINATOR(NODE) (LANG_DECL_U2_CHECK (NODE, 1)->discriminator)
 
 /* Non-zero if the VTT parm has been added to NODE.  */
 #define DECL_HAS_VTT_PARM_P(NODE) \
@@ -1953,7 +2018,7 @@ struct lang_decl
 
 /* Set the overloaded operator code for NODE to CODE.  */
 #define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
-  (DECL_LANG_SPECIFIC (NODE)->u2.operator_code = (CODE))
+  (DECL_LANG_SPECIFIC (NODE)->u.f.operator_code = (CODE))
 
 /* If NODE is an overloaded operator, then this returns the TREE_CODE
    associcated with the overloaded operator.
@@ -1964,7 +2029,7 @@ struct lang_decl
    to test whether or not NODE is an overloaded operator.  */
 #define DECL_OVERLOADED_OPERATOR_P(NODE)		\
   (IDENTIFIER_OPNAME_P (DECL_NAME (NODE))		\
-   ? DECL_LANG_SPECIFIC (NODE)->u2.operator_code : ERROR_MARK)
+   ? DECL_LANG_SPECIFIC (NODE)->u.f.operator_code : ERROR_MARK)
 
 /* Non-zero if NODE is an assignment operator.  */
 #define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
@@ -1999,7 +2064,7 @@ struct lang_decl
 
 /* A TREE_LIST of the types which have befriended this FUNCTION_DECL.  */
 #define DECL_BEFRIENDING_CLASSES(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->befriending_classes)
+  (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
 
 /* Nonzero for FUNCTION_DECL means that this decl is a static
    member function.  */
@@ -2073,8 +2138,9 @@ struct lang_decl
   (DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE))
 
 /* Set DECL_THUNK_P for node.  */
-#define SET_DECL_THUNK_P(NODE) \
-  (DECL_LANG_FLAG_7 (NODE) = 1)
+#define SET_DECL_THUNK_P(NODE)					\
+  (DECL_LANG_FLAG_7 (NODE) = 1, 				\
+   DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1)
 
 /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
    template function.  */
@@ -2094,12 +2160,12 @@ struct lang_decl
    the DECL_FRIEND_CONTEXT for `f' will be `S'.  */
 #define DECL_FRIEND_CONTEXT(NODE)				\
   ((DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE))	\
-   ? DECL_LANG_SPECIFIC (NODE)->context                         \
+   ? DECL_LANG_SPECIFIC (NODE)->u.f.context			\
    : NULL_TREE)
 
 /* Set the DECL_FRIEND_CONTEXT for NODE to CONTEXT.  */
 #define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
-  (DECL_LANG_SPECIFIC (NODE)->context = (CONTEXT))
+  (DECL_LANG_SPECIFIC (NODE)->u.f.context = (CONTEXT))
 
 /* NULL_TREE in DECL_CONTEXT represents the global namespace. */
 #define CP_DECL_CONTEXT(NODE) \
@@ -2109,7 +2175,7 @@ struct lang_decl
 /* For a virtual function, the base where we find its vtable entry.
    For a non-virtual function, the base where it is defined.  */
 #define DECL_VIRTUAL_CONTEXT(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->context)
+  (DECL_LANG_SPECIFIC (NODE)->u.f.context)
 
 /* 1 iff NODE has namespace scope, including the global namespace.  */
 #define DECL_NAMESPACE_SCOPE_P(NODE)				\
@@ -2168,17 +2234,17 @@ struct lang_decl
    the class definition.  We have saved away the text of the function,
    but have not yet processed it.  */
 #define DECL_PENDING_INLINE_P(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->decl_flags.pending_inline_p)
+  (DECL_LANG_SPECIFIC (NODE)->u.f.pending_inline_p)
 
 /* If DECL_PENDING_INLINE_P holds, this is the saved text of the
    function.  */
 #define DECL_PENDING_INLINE_INFO(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->u.pending_inline_info)
+  (DECL_LANG_SPECIFIC (NODE)->u.f.u.pending_inline_info)
 
 /* For a TYPE_DECL: if this function has many fields, we'll sort them
    and put them into a TREE_VEC. */
 #define DECL_SORTED_FIELDS(NODE) \
-  (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.sorted_fields)
+  (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.f.u.sorted_fields)
 
 /* True if on the deferred_fns (see decl2.c) list.  */
 #define DECL_DEFERRED_FN(DECL) \
@@ -2192,7 +2258,7 @@ struct lang_decl
 
 /* Template information for a RECORD_TYPE or UNION_TYPE.  */
 #define CLASSTYPE_TEMPLATE_INFO(NODE) \
-  (TYPE_LANG_SPECIFIC (RECORD_OR_UNION_TYPE_CHECK (NODE))->template_info)
+  (LANG_TYPE_CLASS_CHECK (RECORD_OR_UNION_TYPE_CHECK (NODE))->template_info)
 
 /* Template information for an ENUMERAL_TYPE.  Although an enumeration may
    not be a primary template, it may be declared within the scope of a
@@ -2202,7 +2268,7 @@ struct lang_decl
 
 /* Template information for a template template parameter.  */
 #define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \
-  (TYPE_LANG_SPECIFIC (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
+  (LANG_TYPE_CLASS_CHECK (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
    ->template_info)
 
 /* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE.  */
@@ -2340,8 +2406,9 @@ struct lang_decl
 #define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
 
 /* In a FUNCTION_DECL, the saved language-specific per-function data.  */
-#define DECL_SAVED_FUNCTION_DATA(NODE) \
-  (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->u.saved_language_function)
+#define DECL_SAVED_FUNCTION_DATA(NODE)			\
+  (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))	\
+   ->u.f.u.saved_language_function)
 
 #define NEW_EXPR_USE_GLOBAL(NODE)	TREE_LANG_FLAG_0 (NODE)
 #define DELETE_EXPR_USE_GLOBAL(NODE)	TREE_LANG_FLAG_0 (NODE)
@@ -2480,15 +2547,15 @@ extern int flag_new_for_scope;
 /* Nonzero means that an object of this type can not be initialized using
    an initializer list.  */
 #define CLASSTYPE_NON_AGGREGATE(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->non_aggregate)
+  (LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate)
 #define TYPE_NON_AGGREGATE_CLASS(NODE) \
   (IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
 
 /* Nonzero if there is a user-defined X::op=(x&) for this class.  */
-#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_real_assign_ref)
-#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_complex_assign_ref)
-#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_abstract_assign_ref)
-#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_complex_init_ref)
+#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_real_assign_ref)
+#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
+#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_abstract_assign_ref)
+#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref)
 
 /* Nonzero if TYPE has a trivial destructor.  From [class.dtor]:
 
@@ -2547,7 +2614,7 @@ extern int flag_new_for_scope;
    && TYPE_PTRMEMFUNC_FLAG (NODE))
 
 #define TYPE_PTRMEMFUNC_FLAG(NODE) \
-  (TYPE_LANG_SPECIFIC (NODE)->ptrmemfunc_flag)
+  (LANG_TYPE_CLASS_CHECK (NODE)->ptrmemfunc_flag)
 
 /* Indicates when overload resolution may resolve to a pointer to
    member function. [expr.unary.op]/3 */
@@ -2592,9 +2659,17 @@ enum ptrmemfunc_vbit_where_t
 /* These are use to manipulate the canonical RECORD_TYPE from the
    hashed POINTER_TYPE, and can only be used on the POINTER_TYPE.  */
 #define TYPE_GET_PTRMEMFUNC_TYPE(NODE) \
-  ((tree)TYPE_LANG_SPECIFIC (NODE))
-#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) \
-  (TYPE_LANG_SPECIFIC (NODE) = ((struct lang_type *)(void*)(VALUE)))
+  (TYPE_LANG_SPECIFIC (NODE) ? LANG_TYPE_PTRMEM_CHECK (NODE)->record : NULL)
+#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE)				\
+  do {									\
+    if (TYPE_LANG_SPECIFIC (NODE) == NULL)				\
+      {									\
+	TYPE_LANG_SPECIFIC (NODE) = 					\
+	  ggc_alloc_cleared (sizeof (struct lang_type_ptrmem));		\
+	TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0;	\
+      }									\
+    TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.record = (VALUE);		\
+  } while (0)
 /* Returns the pfn field from a TYPE_PTRMEMFUNC_P.  */
 #define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE))
 
@@ -2639,9 +2714,9 @@ enum ptrmemfunc_vbit_where_t
    flag for this because "A union for which objects or pointers are
    declared is not an anonymous union" [class.union].  */
 #define ANON_AGGR_TYPE_P(NODE)				\
-  (CLASS_TYPE_P (NODE) && TYPE_LANG_SPECIFIC (NODE)->anon_aggr)
+  (CLASS_TYPE_P (NODE) && LANG_TYPE_CLASS_CHECK (NODE)->anon_aggr)
 #define SET_ANON_AGGR_TYPE_P(NODE)			\
-  (TYPE_LANG_SPECIFIC (NODE)->anon_aggr = 1)
+  (LANG_TYPE_CLASS_CHECK (NODE)->anon_aggr = 1)
 
 /* Nonzero if TYPE is an anonymous union type.  */
 #define ANON_UNION_TYPE_P(NODE) \
@@ -2651,7 +2726,7 @@ enum ptrmemfunc_vbit_where_t
 
 /* Define fields and accessors for nodes representing declared names.  */
 
-#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->was_anonymous)
+#define TYPE_WAS_ANONYMOUS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->was_anonymous)
 
 /* C++: all of these are overloaded!  These apply only to TYPE_DECLs.  */
 
@@ -2676,7 +2751,7 @@ enum ptrmemfunc_vbit_where_t
    For example, if a member that would normally be public in a
    derived class is made protected, then the derived class and the
    protected_access_node will appear in the DECL_ACCESS for the node.  */
-#define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.access)
+#define DECL_ACCESS(NODE) (LANG_DECL_U2_CHECK (NODE, 0)->access)
 
 /* Nonzero if the FUNCTION_DECL is a global constructor.  */
 #define DECL_GLOBAL_CTOR_P(NODE) \
@@ -2691,7 +2766,7 @@ enum ptrmemfunc_vbit_where_t
    with lower numbers should be run first.  Destructors should be run
    in the reverse order of constructors.  */
 #define GLOBAL_INIT_PRIORITY(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.init_priority)
+  (LANG_DECL_U2_CHECK (NODE, 1)->init_priority)
 
 /* Accessor macros for C++ template decl nodes.  */
 
@@ -2874,7 +2949,7 @@ enum ptrmemfunc_vbit_where_t
    i.e., an instantiation whose instantiation arguments involve
    template types.  */
 #define PARTIAL_INSTANTIATION_P(TYPE) \
-  (TYPE_LANG_SPECIFIC (TYPE)->is_partial_instantiation)
+  (LANG_TYPE_CLASS_CHECK (TYPE)->is_partial_instantiation)
 
 /* Non-zero iff we are currently processing a declaration for an
    entity with its own template parameter list, and which is not a
@@ -2939,7 +3014,7 @@ enum ptrmemfunc_vbit_where_t
    is always located at offset zero from the f `this' pointer.)  If
    NULL, then there is no vcall offset.  */
 #define THUNK_VCALL_OFFSET(DECL) \
-  (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
+  (LANG_DECL_U2_CHECK (DECL, 0)->vcall_offset)
 
 /* These macros provide convenient access to the various _STMT nodes
    created when parsing template declarations.  */
@@ -3953,7 +4028,6 @@ extern tree make_aggr_type			PARAMS ((en
 extern void compiler_error			PARAMS ((const char *, ...))
   ATTRIBUTE_PRINTF_1;
 extern void yyerror				PARAMS ((const char *));
-extern void clear_inline_text_obstack		PARAMS ((void));
 extern void yyhook				PARAMS ((int));
 extern int cp_type_qual_from_rid                PARAMS ((tree));
 extern const char *cxx_init			PARAMS ((const char *));
@@ -4178,7 +4252,6 @@ extern tree begin_class_definition      
 extern tree finish_class_definition             PARAMS ((tree, tree, int, int));
 extern void finish_default_args                 PARAMS ((void));
 extern void begin_inline_definitions            PARAMS ((void));
-extern void finish_inline_definitions           PARAMS ((void));
 extern tree finish_member_class_template        PARAMS ((tree));
 extern void finish_template_decl                PARAMS ((tree));
 extern tree finish_template_type                PARAMS ((tree, tree, int));
@@ -4204,7 +4277,6 @@ extern tree finish_global_stmt_expr     
 
 /* in spew.c */
 extern void init_spew				PARAMS ((void));
-extern void mark_pending_inlines		PARAMS ((PTR));
 extern int peekyylex				PARAMS ((void));
 extern tree arbitrate_lookup			PARAMS ((tree, tree, tree));
 extern tree frob_opname                         PARAMS ((tree));
@@ -4217,15 +4289,18 @@ extern void replace_defarg			PARAMS ((tr
 extern void end_input				PARAMS ((void));
 
 /* in tree.c */
-extern tree stabilize_expr		PARAMS ((tree, tree *));
-extern tree cxx_unsave_expr_now		PARAMS ((tree));
+extern void lang_check_failed			PARAMS ((const char *, int,
+							 const char *));
+extern tree stabilize_expr			PARAMS ((tree, tree *));
+extern tree cxx_unsave_expr_now			PARAMS ((tree));
 extern void init_tree			        PARAMS ((void));
 extern int pod_type_p				PARAMS ((tree));
 extern tree canonical_type_variant              PARAMS ((tree));
 extern void unshare_base_binfos			PARAMS ((tree));
 extern int member_p				PARAMS ((tree));
 extern cp_lvalue_kind real_lvalue_p		PARAMS ((tree));
-extern tree build_min				PARAMS ((enum tree_code, tree, ...));
+extern tree build_min				PARAMS ((enum tree_code, tree,
+							 ...));
 extern tree build_min_nt			PARAMS ((enum tree_code, ...));
 extern tree build_cplus_new			PARAMS ((tree, tree));
 extern tree get_target_expr			PARAMS ((tree));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.847.2.7
diff -p -u -p -r1.847.2.7 decl.c
--- cp/decl.c	9 Apr 2002 21:57:12 -0000	1.847.2.7
+++ cp/decl.c	27 Apr 2002 19:22:20 -0000
@@ -126,10 +126,6 @@ static tree check_initializer PARAMS ((t
 static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
 static void push_cp_function_context PARAMS ((struct function *));
 static void pop_cp_function_context PARAMS ((struct function *));
-static void mark_binding_level PARAMS ((void *));
-static void mark_named_label_lists PARAMS ((void *, void *));
-static void mark_cp_function_context PARAMS ((void *));
-static void mark_lang_function PARAMS ((struct cp_language_function *));
 static void save_function_data PARAMS ((tree));
 static void check_function_type PARAMS ((tree, tree));
 static void destroy_local_var PARAMS ((tree));
@@ -216,7 +212,7 @@ static int only_namespace_names;
 /* Used only for jumps to as-yet undefined labels, since jumps to
    defined labels can have their validity checked immediately.  */
 
-struct named_label_use_list
+struct named_label_use_list GTY(())
 {
   struct cp_binding_level *binding_level;
   tree names_in_scope;
@@ -249,7 +245,7 @@ tree last_function_parms;
    we can clear out their names' definitions at the end of the
    function, and so we can check the validity of jumps to these labels.  */
 
-struct named_label_list
+struct named_label_list GTY(())
 {
   struct cp_binding_level *binding_level;
   tree names_in_scope;
@@ -1928,36 +1924,6 @@ wrapup_globals_for_namespace (namespace,
 }
 
 
-/* Mark ARG (which is really a struct cp_binding_level **) for GC.  */
-
-static void
-mark_binding_level (arg)
-     void *arg;
-{
-  gt_ggc_m_cp_binding_level (*(struct cp_binding_level **)arg);
-}
-
-static void
-mark_named_label_lists (labs, uses)
-     void *labs;
-     void *uses;
-{
-  struct named_label_list *l = *(struct named_label_list **)labs;
-  struct named_label_use_list *u = *(struct named_label_use_list **)uses;
-
-  for (; l; l = l->next)
-    {
-      ggc_mark (l);
-      mark_binding_level (l->binding_level);
-      ggc_mark_tree (l->old_value);
-      ggc_mark_tree (l->label_decl);
-      ggc_mark_tree (l->bad_decls);
-    }
-
-  for (; u; u = u->next)
-    ggc_mark (u);
-}
-
 /* For debugging.  */
 static int no_print_functions = 0;
 static int no_print_builtins = 0;
@@ -2688,6 +2654,7 @@ push_local_name (decl)
 	{
 	  if (!DECL_LANG_SPECIFIC (decl))
 	    retrofit_lang_decl (decl);
+	  DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
 	  if (DECL_LANG_SPECIFIC (t))
 	    DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
 	  else
@@ -3575,7 +3542,8 @@ duplicate_decls (newdecl, olddecl)
       /* Don't really know how much of the language-specific
 	 values we should copy from old to new.  */
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
-      DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
+      DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 = 
+	DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       DECL_INITIALIZED_IN_CLASS_P (newdecl)
@@ -6345,7 +6313,7 @@ cxx_init_decl_processing ()
   /* Fill in back-end hooks.  */
   init_lang_status = &push_cp_function_context;
   free_lang_status = &pop_cp_function_context;
-  mark_lang_status = &mark_cp_function_context;
+  mark_lang_status = &gt_ggc_m_cp_language_function;
   lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
 
   init_decl2 ();
@@ -13856,7 +13824,6 @@ begin_destructor_body ()
      appropriately, so we just assume that we always need to
      initialize the vtables.)  */
   finish_if_stmt_cond (boolean_true_node, if_stmt);
-  current_vcalls_possible_p = &IF_COND (if_stmt);
 
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
 
@@ -14484,37 +14451,6 @@ pop_cp_function_context (f)
   f->language = 0;
 }
 
-/* Mark P for GC.  */
-
-static void
-mark_lang_function (p)
-     struct cp_language_function *p;
-{
-  if (!p)
-    return;
-
-  mark_c_language_function (&p->base);
-
-  ggc_mark_tree (p->x_dtor_label);
-  ggc_mark_tree (p->x_current_class_ptr);
-  ggc_mark_tree (p->x_current_class_ref);
-  ggc_mark_tree (p->x_eh_spec_block);
-  ggc_mark_tree_varray (p->x_local_names);
-
-  mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
-  mark_binding_level (&p->bindings);
-  mark_pending_inlines (&p->unparsed_inlines);
-}
-
-/* Mark the language-specific data in F for GC.  */
-
-static void
-mark_cp_function_context (language)
-     void *language;
-{
-  mark_lang_function ((struct cp_language_function *) language);
-}
-
 void
 lang_mark_tree (t)
      tree t;
@@ -14523,23 +14459,16 @@ lang_mark_tree (t)
   if (code == IDENTIFIER_NODE)
     {
       struct lang_identifier *li = (struct lang_identifier *) t;
-      struct lang_id2 *li2 = li->x;
       ggc_mark_tree (li->namespace_bindings);
       ggc_mark_tree (li->bindings);
       ggc_mark_tree (li->class_value);
       ggc_mark_tree (li->class_template_info);
-
-      if (li2)
-	{
-	  ggc_mark_tree (li2->label_value);
-	  ggc_mark_tree (li2->implicit_decl);
-	  ggc_mark_tree (li2->error_locus);
-	}
+      gt_ggc_m_lang_id2 (li->x);
     }
   else if (code == CPLUS_BINDING)
     {
       if (BINDING_HAS_LEVEL_P (t))
-	mark_binding_level (&BINDING_LEVEL (t));
+	gt_ggc_m_cp_binding_level (&BINDING_LEVEL (t));
       else
 	ggc_mark_tree (BINDING_SCOPE (t));
       ggc_mark_tree (BINDING_VALUE (t));
@@ -14548,63 +14477,10 @@ lang_mark_tree (t)
     ggc_mark_tree (OVL_FUNCTION (t));
   else if (code == TEMPLATE_PARM_INDEX)
     ggc_mark_tree (TEMPLATE_PARM_DECL (t));
-  else if (TREE_CODE_CLASS (code) == 'd')
-    {
-      struct lang_decl *ld = DECL_LANG_SPECIFIC (t);
-
-      if (ld)
-	{
-	  ggc_mark (ld);
-	  c_mark_lang_decl (&ld->decl_flags.base);
-	  if (!DECL_GLOBAL_CTOR_P (t)
-	      && !DECL_GLOBAL_DTOR_P (t)
-	      && !DECL_THUNK_P (t)
-	      && !DECL_DISCRIMINATOR_P (t))
-	    ggc_mark_tree (ld->decl_flags.u2.access);
-	  else if (DECL_THUNK_P (t))
-	    ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
-	  if (TREE_CODE (t) != NAMESPACE_DECL)
-	    ggc_mark_tree (ld->decl_flags.u.template_info);
-	  else
-	    mark_binding_level (&NAMESPACE_LEVEL (t));
-	  if (CAN_HAVE_FULL_LANG_DECL_P (t))
-	    {
-	      ggc_mark_tree (ld->befriending_classes);
-	      ggc_mark_tree (ld->context);
-	      ggc_mark_tree (ld->cloned_function);
-	      if (TREE_CODE (t) == TYPE_DECL)
-		ggc_mark_tree (ld->u.sorted_fields);
-	      else if (TREE_CODE (t) == FUNCTION_DECL
-		       && !DECL_PENDING_INLINE_P (t))
-		mark_lang_function (DECL_SAVED_FUNCTION_DATA (t));
-	    }
-	}
-    }
-  else if (TREE_CODE_CLASS (code) == 't')
-    {
-      struct lang_type *lt = TYPE_LANG_SPECIFIC (t);
-
-      if (lt && !(TREE_CODE (t) == POINTER_TYPE
-		  && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
-	{
-	  ggc_mark (lt);
-	  ggc_mark_tree (lt->primary_base);
-	  ggc_mark_tree (lt->vfields);
-	  ggc_mark_tree (lt->vbases);
-	  ggc_mark_tree (lt->tags);
-	  ggc_mark_tree (lt->size);
-	  ggc_mark_tree (lt->pure_virtuals);
-	  ggc_mark_tree (lt->friend_classes);
-	  ggc_mark_tree (lt->rtti);
-	  ggc_mark_tree (lt->methods);
-	  ggc_mark_tree (lt->template_info);
-	  ggc_mark_tree (lt->befriending_classes);
-	}
-      else if (lt)
-	/* In the case of pointer-to-member function types, the
-	   TYPE_LANG_SPECIFIC is really just a tree.  */
-	ggc_mark_tree ((tree) lt);
-    }
+   else if (TYPE_P (t))
+    gt_ggc_m_lang_type (TYPE_LANG_SPECIFIC (t));
+  else if (DECL_P (t))
+    gt_ggc_m_lang_decl (DECL_LANG_SPECIFIC (t));
 }
 
 /* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.512.2.3
diff -p -u -p -r1.512.2.3 decl2.c
--- cp/decl2.c	9 Apr 2002 21:57:15 -0000	1.512.2.3
+++ cp/decl2.c	27 Apr 2002 19:22:20 -0000
@@ -2721,6 +2721,7 @@ start_objects (method_type, initp)
     DECL_GLOBAL_CTOR_P (current_function_decl) = 1;
   else
     DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
+  DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
   GLOBAL_INIT_PRIORITY (current_function_decl) = initp;
 
   body = begin_compound_stmt (/*has_no_scope=*/0);
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.262.2.2
diff -p -u -p -r1.262.2.2 lex.c
--- cp/lex.c	14 Mar 2002 21:37:12 -0000	1.262.2.2
+++ cp/lex.c	27 Apr 2002 19:22:21 -0000
@@ -1458,6 +1458,12 @@ retrofit_lang_decl (t)
 
   ld = (struct lang_decl *) ggc_alloc_cleared (size);
 
+  ld->decl_flags.can_be_full = CAN_HAVE_FULL_LANG_DECL_P (t) ? 1 : 0;
+  ld->decl_flags.u1sel = TREE_CODE (t) == NAMESPACE_DECL ? 1 : 0;
+  ld->decl_flags.u2sel = 0;
+  if (ld->decl_flags.can_be_full)
+    ld->u.f.u3sel = TREE_CODE (t) == FUNCTION_DECL ? 1 : 0;
+
   DECL_LANG_SPECIFIC (t) = ld;
   if (current_lang_name == lang_name_cplusplus)
     SET_DECL_LANGUAGE (t, lang_cplusplus);
@@ -1522,7 +1528,10 @@ copy_lang_type (node)
   if (! TYPE_LANG_SPECIFIC (node))
     return;
 
-  size = sizeof (struct lang_type);
+  if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
+    size = sizeof (struct lang_type);
+  else
+    size = sizeof (struct lang_type_ptrmem);
   lt = (struct lang_type *) ggc_alloc (size);
   memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
   TYPE_LANG_SPECIFIC (node) = lt;
@@ -1562,6 +1571,7 @@ cp_make_lang_type (code)
 	    ggc_alloc_cleared (sizeof (struct lang_type)));
 
       TYPE_LANG_SPECIFIC (t) = pi;
+      pi->u.c.h.is_lang_type_class = 1;
 
 #ifdef GATHER_STATISTICS
       tree_node_counts[(int)lang_type] += 1;
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parse.y,v
retrieving revision 1.240.6.3
diff -p -u -p -r1.240.6.3 parse.y
--- cp/parse.y	9 Apr 2002 21:57:18 -0000	1.240.6.3
+++ cp/parse.y	27 Apr 2002 19:22:21 -0000
@@ -226,7 +226,7 @@ check_class_key (key, aggr)
 
 %start program
 
-%union {
+%union { GTY(())
   long itype; 
   tree ttype; 
   char *strtype; 
@@ -339,7 +339,7 @@ check_class_key (key, aggr)
 %type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
 %type <ttype> expr_no_commas expr_no_comma_rangle
 %type <ttype> cast_expr unary_expr primary string STRING
-%type <ttype> reserved_declspecs boolean.literal
+%type <ttype> reserved_declspecs boolean_literal
 %type <ttype> reserved_typespecquals
 %type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
 %type <ttype> init initlist maybeasm maybe_init defarg defarg1
@@ -387,13 +387,13 @@ check_class_key (key, aggr)
 %token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
 %token <pi> PRE_PARSED_FUNCTION_DECL 
 %type <ttype> component_constructor_declarator
-%type <ttype> fn.def2 return_id constructor_declarator
-%type <ttype> .begin_function_body
+%type <ttype> fn_def2 return_id constructor_declarator
+%type <ttype> begin_function_body_
 %type <ttype> class_head class_head_apparent_template
 %type <ftype> class_head_decl class_head_defn
 %type <ttype> base_class_list
 %type <ttype> base_class_access_list
-%type <ttype> base_class maybe_base_class_list base_class.1
+%type <ttype> base_class maybe_base_class_list base_class_1
 %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
 %type <ttype> operator_name
 %type <ttype> object aggr
@@ -421,7 +421,7 @@ check_class_key (key, aggr)
 %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
 %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
 %type <ttype> handler_args
-%type <ttype> self_template_type .finish_template_type
+%type <ttype> self_template_type finish_template_type_
 
 %token NSNAME
 %type <ttype> NSNAME
@@ -765,7 +765,7 @@ eat_saved_input:
    mem-initializer-list, so we open one there and suppress the one that
    actually corresponds to the curly braces.  */
 function_body:
-	  .begin_function_body ctor_initializer_opt save_lineno '{'
+	  begin_function_body_ ctor_initializer_opt save_lineno '{'
 		{ $<ttype>$ = begin_compound_stmt (/*has_no_scope=*/1); }
 	  compstmtend 
                 {
@@ -859,7 +859,7 @@ component_constructor_declarator:
 
 /* more C++ complexity.  See component_decl for a comment on the
    reduce/reduce conflict introduced by these rules.  */
-fn.def2:
+fn_def2:
 	  declmods component_constructor_declarator
 		{ $$ = parse_method ($2, $1.t, $1.lookups);
 		 rest_of_mdef:
@@ -913,7 +913,7 @@ base_init:
 		}
 	;
 
-.begin_function_body:
+begin_function_body_:
 	  /* empty */
 		{
 		  $$ = begin_function_body ();
@@ -1043,10 +1043,10 @@ end_explicit_instantiation: 
 
 template_type:
 	  PTYPENAME '<' template_arg_list_opt template_close_bracket
-	    .finish_template_type
+	    finish_template_type_
                 { $$ = $5; }
 	| TYPENAME  '<' template_arg_list_opt template_close_bracket
-	    .finish_template_type
+	    finish_template_type_
                 { $$ = $5; }
 	| self_template_type
 	;
@@ -1054,16 +1054,16 @@ template_type:
 apparent_template_type:
 	  template_type
 	| identifier '<' template_arg_list_opt '>'
-	    .finish_template_type
+	    finish_template_type_
 		{ $$ = $5; }
 
 self_template_type:
 	  SELFNAME  '<' template_arg_list_opt template_close_bracket
-	    .finish_template_type
+	    finish_template_type_
                 { $$ = $5; }
 	;
 
-.finish_template_type:
+finish_template_type_:
                 { 
 		  if (yychar == YYEMPTY)
 		    yychar = YYLEX;
@@ -1560,7 +1560,7 @@ primary:
 		    $$ = finish_id_expr ($1);
 		}		
 	| CONSTANT
-	| boolean.literal
+	| boolean_literal
 	| string
 		{
 		  $$ = combine_strings ($$);
@@ -1758,7 +1758,7 @@ delete:
 		{ got_scope = NULL_TREE; $$ = 1; }
 	;
 
-boolean.literal:
+boolean_literal:
 	  CXX_TRUE
 		{ $$ = boolean_true_node; }
 	| CXX_FALSE
@@ -2322,7 +2322,6 @@ structsp:
 		}
 	  pending_inlines
                 {
-		  finish_inline_definitions ();
 		  $$.t = $<ttype>8;
 		  $$.new_type_flag = 1; 
 		}
@@ -2500,13 +2499,13 @@ base_class_list:
 	;
 
 base_class:
-	  base_class.1
+	  base_class_1
 		{ $$ = finish_base_specifier (access_default_node, $1); }
-	| base_class_access_list see_typename base_class.1
+	| base_class_access_list see_typename base_class_1
                 { $$ = finish_base_specifier ($1, $3); }
 	;
 
-base_class.1:
+base_class_1:
 	  typename_sub
 		{ if (!TYPE_P ($$))
 		    $$ = error_mark_node; }
@@ -2582,13 +2581,13 @@ component_decl:
 		  yyungetc ('}', 0); }
 	/* C++: handle constructors, destructors and inline functions */
 	/* note that INLINE is like a TYPESPEC */
-	| fn.def2 ':' /* base_init compstmt */
+	| fn_def2 ':' /* base_init compstmt */
 		{ $$ = finish_method ($$); }
-	| fn.def2 TRY /* base_init compstmt */
+	| fn_def2 TRY /* base_init compstmt */
 		{ $$ = finish_method ($$); }
-	| fn.def2 RETURN_KEYWORD /* base_init compstmt */
+	| fn_def2 RETURN_KEYWORD /* base_init compstmt */
 		{ $$ = finish_method ($$); }
-	| fn.def2 '{' /* nodecls compstmt */
+	| fn_def2 '{' /* nodecls compstmt */
 		{ $$ = finish_method ($$); }
 	| ';'
 		{ $$ = NULL_TREE; }
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.221.4.2
diff -p -u -p -r1.221.4.2 search.c
--- cp/search.c	14 Mar 2002 21:37:14 -0000	1.221.4.2
+++ cp/search.c	27 Apr 2002 19:22:21 -0000
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "rtl.h"
 #include "output.h"
+#include "ggc.h"
 #include "toplev.h"
 
 #define obstack_chunk_alloc xmalloc
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.244.2.3
diff -p -u -p -r1.244.2.3 semantics.c
--- cp/semantics.c	14 Mar 2002 21:37:14 -0000	1.244.2.3
+++ cp/semantics.c	27 Apr 2002 19:22:21 -0000
@@ -111,7 +111,7 @@ int
 anon_aggr_type_p (node)
      tree node;
 {
-  return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr);
+  return ANON_AGGR_TYPE_P (node);
 }
 
 /* Finish a scope.  */
@@ -1906,16 +1906,6 @@ begin_inline_definitions ()
 {
   if (current_scope () == current_function_decl)
     do_pending_inlines ();
-}
-
-/* Finish processing the inline function definitions cached during the
-   processing of a class definition.  */
-
-void
-finish_inline_definitions ()
-{
-  if (current_class_type == NULL_TREE)
-    clear_inline_text_obstack (); 
 }
 
 /* Finish processing the declaration of a member class template
Index: cp/spew.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/spew.c,v
retrieving revision 1.58.2.2
diff -p -u -p -r1.58.2.2 spew.c
--- cp/spew.c	9 Apr 2002 21:57:20 -0000	1.58.2.2
+++ cp/spew.c	27 Apr 2002 19:22:21 -0000
@@ -50,12 +50,12 @@ Boston, MA 02111-1307, USA.  */
    backtracking.  */
 
 /* fifo of tokens recognized and available to parser.  */
-struct token
+struct token GTY(())
 {
   /* The values for YYCHAR will fit in a short.  */
   short		yychar;
   unsigned int	lineno;
-  YYSTYPE	yylval;
+  YYSTYPE GTY ((desc ("%1.yychar"))) yylval;
 };
 
 /* Since inline methods can refer to text which has not yet been seen,
@@ -68,7 +68,14 @@ struct token
    This function's FUNCTION_DECL will have a bit set in its common so
    that we know to watch out for it.  */
 
-struct unparsed_text
+#define TOKEN_CHUNK_SIZE 20
+struct token_chunk GTY(())
+{
+  struct token_chunk *next;
+  struct token toks[TOKEN_CHUNK_SIZE];
+};
+
+struct unparsed_text GTY(())
 {
   struct unparsed_text *next;	/* process this one next */
   tree decl;		/* associated declaration */
@@ -76,26 +83,31 @@ struct unparsed_text
   int lineno;		/* line number we got the text from */
   int interface;	/* remembering interface_unknown and interface_only */
 
-  struct token *pos;	/* current position, when rescanning */
-  struct token *limit;	/* end of saved text */
+  struct token_chunk * tokens; /* Start of the token list.  */
+
+  struct token_chunk *last_chunk; /* End of the token list.  */
+  short last_pos;	/* Number of tokens used in the last chunk of 
+			   TOKENS. */
+
+  short cur_pos;	/* Current token in 'cur_chunk', when rescanning.  */
+  struct token_chunk *cur_chunk;  /* Current chunk, when rescanning.  */
 };
 
 /* Stack of state saved off when we return to an inline method or
    default argument that has been stored for later parsing.  */
-struct feed
+struct feed GTY(())
 {
   struct unparsed_text *input;
   const char *filename;
   int lineno;
   int yychar;
-  YYSTYPE yylval;
+  YYSTYPE GTY ((desc ("%1.yychar"))) yylval;
   int first_token;
-  struct obstack token_obstack;
+  struct obstack GTY ((skip (""))) token_obstack;
   struct feed *next;
-};  
+};
 
-static struct obstack feed_obstack;
-static struct feed *feed;
+static GTY(()) struct feed *feed;
 
 static SPEW_INLINE void do_aggr PARAMS ((void));
 static SPEW_INLINE int identifier_type PARAMS ((tree));
@@ -106,25 +118,32 @@ static int read_token PARAMS ((struct to
 
 static SPEW_INLINE int num_tokens PARAMS ((void));
 static SPEW_INLINE struct token *nth_token PARAMS ((int));
-static SPEW_INLINE int add_token PARAMS ((struct token *));
+static SPEW_INLINE int next_token PARAMS ((struct token *));
 static SPEW_INLINE int shift_token PARAMS ((void));
 static SPEW_INLINE void push_token PARAMS ((struct token *));
 static SPEW_INLINE void consume_token PARAMS ((void));
 static SPEW_INLINE int read_process_identifier PARAMS ((YYSTYPE *));
 
 static SPEW_INLINE void feed_input PARAMS ((struct unparsed_text *));
-static SPEW_INLINE void snarf_block PARAMS ((const char *, int));
+static SPEW_INLINE struct token * space_for_token 
+  PARAMS ((struct unparsed_text *t));
+static SPEW_INLINE struct token * remove_last_token
+  PARAMS ((struct unparsed_text *t));
+static struct unparsed_text * alloc_unparsed_text
+  PARAMS ((const char *fn, int li, tree decl, int interface));
+
+static void snarf_block PARAMS ((struct unparsed_text *t));
 static tree snarf_defarg PARAMS ((void));
 static int frob_id PARAMS ((int, int, tree *));
 
 /* The list of inline functions being held off until we reach the end of
    the current class declaration.  */
-static struct unparsed_text *pending_inlines;
-static struct unparsed_text *pending_inlines_tail;
+static GTY(()) struct unparsed_text *pending_inlines;
+static GTY(()) struct unparsed_text *pending_inlines_tail;
 
 /* The list of previously-deferred inline functions currently being parsed.
    This exists solely to be a GC root.  */
-static struct unparsed_text *processing_these_inlines;
+static GTY(()) struct unparsed_text *processing_these_inlines;
 
 static void begin_parsing_inclass_inline PARAMS ((struct unparsed_text *));
 
@@ -150,13 +169,8 @@ extern int	yychar;		/*  the lookahead sy
 extern YYSTYPE	yylval;		/*  the semantic value of the		*/
 				/*  lookahead symbol			*/
 /* The token fifo lives in this obstack.  */
-struct obstack token_obstack;
-int first_token;
-
-/* Sometimes we need to save tokens for later parsing.  If so, they are
-   stored on this obstack.  */
-struct obstack inline_text_obstack;
-char *inline_text_firstobj;
+static struct obstack token_obstack;
+static int first_token;
 
 /* When we see a default argument in a method declaration, we snarf it as
    text using snarf_defarg.  When we get up to namespace scope, we then go
@@ -181,21 +195,7 @@ static GTY(()) tree defarg_fnsdone;
 void
 init_spew ()
 {
-  gcc_obstack_init (&inline_text_obstack);
-  inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
   gcc_obstack_init (&token_obstack);
-  gcc_obstack_init (&feed_obstack);
-
-  ggc_add_root (&pending_inlines, 1, sizeof (struct unparsed_text *),
-		mark_pending_inlines);
-  ggc_add_root (&processing_these_inlines, 1, sizeof (struct unparsed_text *),
-		mark_pending_inlines);
-}
-
-void
-clear_inline_text_obstack ()
-{
-  obstack_free (&inline_text_obstack, inline_text_firstobj);
 }
 
 /* Subroutine of read_token.  */
@@ -358,10 +358,10 @@ feed_input (input)
     abort ();
 #endif
 
-  f = obstack_alloc (&feed_obstack, sizeof (struct feed));
+  f = ggc_alloc (sizeof (struct feed));
 
-  /* The token list starts just after the struct unparsed_text in memory.  */
-  input->pos = (struct token *) (input + 1);
+  input->cur_chunk = input->tokens;
+  input->cur_pos = 0;
 
 #ifdef SPEW_DEBUG
   if (spew_debug)
@@ -401,48 +401,12 @@ end_input ()
   token_obstack = f->token_obstack;
   feed = f->next;
 
-  obstack_free (&feed_obstack, f);
-
 #ifdef SPEW_DEBUG
   if (spew_debug)
     fprintf (stderr, "\treturning to %s:%d\n", input_filename, lineno);
 #endif
 }
 
-/* GC callback to mark memory pointed to by the pending inline queue.  */
-void
-mark_pending_inlines (pi)
-     PTR pi;
-{
-  struct unparsed_text *up = * (struct unparsed_text **)pi;
-
-  while (up)
-    {
-      struct token *t = (struct token *) (up + 1);
-      struct token *l = up->limit;
-
-      while (t < l)
-	{
-	  /* Some of the possible values for yychar use yylval.code
-	     instead of yylval.ttype.  We only have to worry about
-	     yychars that could have been returned by read_token.  */
-	  switch (t->yychar)
-	    {
-	    case '+':	    case '-':	    case '*':	    case '/':
-	    case '%':	    case '&':	    case '|':	    case '^':
-	    case '>':	    case '<':	    case LSHIFT:    case RSHIFT:
-	    case ASSIGN:    case MIN_MAX:   case EQCOMPARE: case ARITHCOMPARE:
-	      t++;
-	      continue;
-	    }
-	  if (t->yylval.ttype)
-	    ggc_mark_tree (t->yylval.ttype);
-	  t++;
-	}
-      up = up->next;
-    }
-}
-  
 /* Token queue management.  */
 
 /* Return the number of tokens available on the fifo.  */
@@ -472,16 +436,24 @@ static const struct token Tpad = { EMPTY
 
 /* Copy the next token into T and return its value.  */
 static SPEW_INLINE int
-add_token (t)
+next_token (t)
      struct token *t;
 {
   if (!feed)
     return read_token (t);
 
-  if (feed->input->pos < feed->input->limit)
+  if (feed->input->cur_chunk != feed->input->last_chunk
+      || feed->input->cur_pos != feed->input->last_pos)
     {
-      memcpy (t, feed->input->pos, sizeof (struct token));
-      return (feed->input->pos++)->yychar;
+      if (feed->input->cur_pos == TOKEN_CHUNK_SIZE)
+	{
+	  feed->input->cur_chunk = feed->input->cur_chunk->next;
+	  feed->input->cur_pos = 0;
+	}
+      memcpy (t, feed->input->cur_chunk->toks + feed->input->cur_pos, 
+	      sizeof (struct token));
+      feed->input->cur_pos++;
+      return t->yychar;
     }
   
   memcpy (t, &Teosi, sizeof (struct token));
@@ -494,7 +466,7 @@ shift_token ()
 {
   size_t point = obstack_object_size (&token_obstack);
   obstack_blank (&token_obstack, sizeof (struct token));
-  return add_token ((struct token *) (obstack_base (&token_obstack) + point));
+  return next_token ((struct token *) (obstack_base (&token_obstack) + point));
 }
 
 /* Consume the next token out of the fifo.  */
@@ -1029,22 +1001,73 @@ process_next_inline (i)
       extract_interface_info ();
     }
 }
+
+/* Create a new token at the end of the token list in T.  */
+static SPEW_INLINE struct token *
+space_for_token (t)
+     struct unparsed_text *t;
+{
+  if (t->last_pos != TOKEN_CHUNK_SIZE)
+    return t->last_chunk->toks + (t->last_pos++);
+
+  t->last_chunk->next = ggc_alloc (sizeof (*t->last_chunk->next));
+  t->last_chunk = t->last_chunk->next;
+  t->last_chunk->next = NULL;
+  
+  t->last_pos = 1;
+  return t->last_chunk->toks;
+}
 
+/* Shrink the token list in T by one token.  */
+static SPEW_INLINE struct token *
+remove_last_token (t)
+     struct unparsed_text *t;
+{
+  struct token *result = t->last_chunk->toks + t->last_pos - 1;
+  if (t->last_pos == 0)
+    abort ();
+  t->last_pos--;
+  if (t->last_pos == 0 && t->last_chunk != t->tokens)
+    {
+      struct token_chunk **tc;
+      for (tc = &t->tokens; (*tc)->next != NULL; tc = &(*tc)->next)
+	;
+      *tc = NULL;
+      t->last_pos = sizeof ((*tc)->toks) / sizeof ((*tc)->toks[0]);
+    }
+  return result;
+}
+
+/* Allocate an 'unparsed_text' structure, ready to use space_for_token.  */
+static struct unparsed_text *
+alloc_unparsed_text (fn, li, decl, interface)
+     const char *fn;
+     int li;
+     tree decl;
+     int interface;
+{
+  struct unparsed_text *r;
+  r = ggc_alloc_cleared (sizeof (*r));
+  r->decl = decl;
+  r->filename = fn;
+  r->lineno = li;
+  r->interface = interface;
+  r->tokens = r->last_chunk = ggc_alloc_cleared (sizeof (*r->tokens));
+  return r;
+}
 
 /* Subroutine of snarf_method, deals with actual absorption of the block.  */
 
-static SPEW_INLINE void
-snarf_block (starting_file, starting_line)
-     const char *starting_file;
-     int starting_line;
+static void
+snarf_block (t)
+     struct unparsed_text *t;
 {
   int blev = 1;
   int look_for_semicolon = 0;
   int look_for_lbrac = 0;
   int look_for_catch = 0;
   int yyc;
-  struct token tmp;
-  size_t point;
+  struct token *current;
 
   if (yychar == '{')
     /* We incremented indent_level in yylex; undo that.  */
@@ -1062,17 +1085,14 @@ snarf_block (starting_file, starting_lin
     yyerror ("parse error in method specification");
 
   /* The current token is the first one to be recorded.  */
-  tmp.yychar = yychar;
-  tmp.yylval = yylval;
-  tmp.lineno = lineno;
-  obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
+  current = space_for_token (t);
+  current->yychar = yychar;
+  current->yylval = yylval;
+  current->lineno = lineno;
 
   for (;;)
     {
-      point = obstack_object_size (&inline_text_obstack);
-      obstack_blank (&inline_text_obstack, sizeof (struct token));
-      yyc = add_token ((struct token *)
-		       (obstack_base (&inline_text_obstack) + point));
+      yyc = next_token (space_for_token (t));
 
       if (yyc == '{')
 	{
@@ -1087,27 +1107,29 @@ snarf_block (starting_file, starting_lin
 	      if (!look_for_catch)
 		break;
 	      
-	      if (add_token (&tmp) != CATCH)
+	      if (next_token (space_for_token (t)) != CATCH)
 		{
-		  push_token (&tmp);
+		  push_token (remove_last_token (t));
 		  break;
 		}
 
 	      look_for_lbrac = 1;
-	      obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
 	    }
 	}
       else if (yyc == ';')
 	{
 	  if (look_for_lbrac)
 	    {
+	      struct token *fake;
+	      
 	      error ("function body for constructor missing");
 	      /* fake a { } to avoid further errors */
-	      tmp.yylval.ttype = 0;
-	      tmp.yychar = '{';
-	      obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
-	      tmp.yychar = '}';
-	      obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
+	      fake = space_for_token (t);
+	      fake->yylval.ttype = 0;
+	      fake->yychar = '{';
+	      fake = space_for_token (t);
+	      fake->yylval.ttype = 0;
+	      fake->yychar = '}';
 	      break;
 	    }
 	  else if (look_for_semicolon && blev == 0)
@@ -1115,7 +1137,7 @@ snarf_block (starting_file, starting_lin
 	}
       else if (yyc == 0)
 	{
-	  error_with_file_and_line (starting_file, starting_line,
+	  error_with_file_and_line (t->filename, t->lineno,
 				    "end of file read inside definition");
 	  break;
 	}
@@ -1130,37 +1152,24 @@ snarf_method (decl)
 {
   int starting_lineno = lineno;
   const char *starting_filename = input_filename;
-  size_t len;
-
   struct unparsed_text *meth;
 
-  /* Leave room for the header, then absorb the block.  */
-  obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
-  snarf_block (starting_filename, starting_lineno);
+  meth = alloc_unparsed_text (starting_filename, starting_lineno, decl,
+			      (interface_unknown ? 1 
+			       : (interface_only ? 0 : 2)));
 
-  len = obstack_object_size (&inline_text_obstack);
-  meth = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
+  snarf_block (meth);
 
   /* Happens when we get two declarations of the same function in the
      same scope.  */
   if (decl == void_type_node
       || (current_class_type && TYPE_REDEFINED (current_class_type)))
-    {
-      obstack_free (&inline_text_obstack, (char *)meth);
-      return;
-    }
-
-  meth->decl = decl;
-  meth->filename = starting_filename;
-  meth->lineno = starting_lineno;
-  meth->limit = (struct token *) ((char *)meth + len);
-  meth->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
-  meth->next = 0;
+    return;
 
 #ifdef SPEW_DEBUG
   if (spew_debug)
     fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n",
-	     meth->limit - (struct token *) (meth + 1),
+	     meth->limit,
 	     starting_filename, starting_lineno);
 #endif
 
@@ -1174,8 +1183,8 @@ snarf_method (decl)
   pending_inlines_tail = meth;
 }
 
-/* Consume a no-commas expression - a default argument - and save it
-   on the inline_text_obstack.  */
+/* Consume a no-commas expression - a default argument - and return
+   a DEFAULT_ARG tree node.  */
 
 static tree
 snarf_defarg ()
@@ -1184,19 +1193,14 @@ snarf_defarg ()
   const char *starting_filename = input_filename;
   int yyc;
   int plev = 0;
-  size_t point;
-  size_t len;
   struct unparsed_text *buf;
   tree arg;
 
-  obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
+  buf = alloc_unparsed_text (starting_filename, starting_lineno, 0, 0);
 
   for (;;)
     {
-      point = obstack_object_size (&inline_text_obstack);
-      obstack_blank (&inline_text_obstack, sizeof (struct token));
-      yyc = add_token ((struct token *)
-		       (obstack_base (&inline_text_obstack) + point));
+      yyc = next_token (space_for_token (buf));
 
       if (plev <= 0 && (yyc == ')' || yyc == ','))
 	break;
@@ -1213,24 +1217,13 @@ snarf_defarg ()
     }
 
   /* Unget the last token.  */
-  push_token ((struct token *) (obstack_base (&inline_text_obstack) + point));
-  /* This is the documented way to shrink a growing obstack block.  */
-  obstack_blank (&inline_text_obstack, - (int) sizeof (struct token));
+  push_token (remove_last_token (buf));
 
  done:
-  len = obstack_object_size (&inline_text_obstack);
-  buf = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
-
-  buf->decl = 0;
-  buf->filename = starting_filename;
-  buf->lineno = starting_lineno;
-  buf->limit = (struct token *) ((char *)buf + len);
-  buf->next = 0;
-  
 #ifdef SPEW_DEBUG
   if (spew_debug)
     fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n",
-	     buf->limit - (struct token *) (buf + 1),
+	     buf->limit,
 	     starting_filename, starting_lineno);
 #endif
 
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.264.6.2
diff -p -u -p -r1.264.6.2 tree.c
--- cp/tree.c	14 Mar 2002 21:37:14 -0000	1.264.6.2
+++ cp/tree.c	27 Apr 2002 19:22:22 -0000
@@ -2529,3 +2529,18 @@ stabilize_expr (exp, initp)
   *initp = init_expr;
   return exp;
 }
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+/* Complain that some language-specific thing hanging off a tree
+   node has been accessed improperly.  */
+
+void
+lang_check_failed (file, line, function)
+     const char *file;
+     int line;
+     const char *function;
+{
+  internal_error ("lang_* check: failed in %s, at %s:%d",
+		  function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
============================================================



More information about the Gcc-patches mailing list