Hi Mike,

[I'm replying in this thread to the Objective-C patch you posted in
the type-traits discussion, because both that post and this one are
about reducing the number of tree codes]

On 3/13/07, Mike Stump <[EMAIL PROTECTED]> wrote:
I just converted the Objective-C front-end to free up enough tree
codes so that Objective-C++ can compile again.  I know it can be
done.  If you want a new tree code, you can convert some other tree
code into a subcode. pick one one.

Thanks for doing this!

For ideas, please see the below patch.  I glanced at the C++ front
end, I see 8 tree codes (all the tcc_type codes) that you can reclaim
using the technique below.

For those that want to begin reviewing it, have at it, I'd be
interested in, do we even want to go in this direction (we don't have
hard numbers on the compile time costs yet, I don't think)?  If so,
any better way to do this in the short term?

Emboldened by your patch, I took a quick swing at introducing subcodes
for the simplest tcc_type node in the C++ front end - TYPEOF_TYPE. The
patch is attached. Here are some observations:

 - C++ already uses the LANG_TYPE tree code, although certainly not
the way it was intended: UNKNOWN_TYPE is #define'd to LANG_TYPE. This
is probably keeping Objective-C++ from working with your patch (I
didn't try it).

 - C++ already uses TYPE_LANG_SPECIFIC, for class types and for
pointers to member functions. Those are both based on RECORD_TYPE
nodes (ugh). That's okay: it turns out that we can use
TYPE_LANG_SPECIFIC for RECORD_TYPE nodes and LANG_TYPE nodes with no
problems whatsoever.

 - If C++ uses LANG_TYPE, and Objective C uses LANG_TYPE, we're
heading for a collision with Objective-C++. Either we'll need use
different top-level codes (LANG_TYPE vs. OBJC_LANG_TYPE, for example),
or we need to consolidate LANG_TYPE by making the subtype codes
extensible by Objective-C++ (just like normal tree codes are). The
latter seems like the right thing to do.

 - We're also heading toward collisions with lang_type_class, etc.,
but those are easy to fix.

 - It doesn't seem to happen in the Objective-C front end, but in the
C++ front end we have a lot of large switches on the TREE_CODE of a
type. With subcodes, these switches become very clunky. We go from
something like this:

     switch (TREE_CODE (t))
     {
       case TYPEOF_TYPE:
         /* Handle `typeof' */
         break;

       default:
         /* Default case */
         break;
     }

  to a two-level solution:

     switch (TREE_CODE (t))
     {
       case LANG_TYPE:
         switch (LANG_TYPE_SUBCODE (t))
         {
           case TYPEOF_TYPE_SUBCODE:
              /* Handle `typeof' */
              break;
           default:
             /* Default case. */
             break;
         }
        break;

       default:
         /* Default case */
         break;
     }

    Notice how I had to duplicate the code in the default case? The
situation gets worse when the TYPEOF_TYPE case was combined with other
cases (more duplication) or there was a fall-through either into or
out of the TYPEOF_TYPE case. The latter doesn't happen often with
TYPEOF_TYPE, but it does with other C++ _TYPE nodes.

While reviewing your Objective-C patch, the approach seemed very
clean. The data structures were more explicit than they are today (I
immediately started thinking, "hey, we could use this to shrink the
size of the common bits for types!"), and the few comparisons against
existing _TYPE nodes just because predicate checks.

Unfortunately, it doesn't look like the approach transfers well to the
C++ front end, where the two-level structure forced on us by subcodes
becomes unwieldy pretty quickly. I fear that the code duplication in
switch statements for default and fall-through cases is going to cause
maintenance headaches for a long time to come.

Still, please take a peek at the attached patch to decide for
yourself... I may have missed something obvious. The patch itself
doesn't actually save any nodes, because it introduces a real
UNKNOWN_TYPE node while removing the TYPEOF_TYPE node. But, it makes
TYPEOF_TYPE a subcode'd type, and the other tcc_type nodes (including
UNKNOWN_TYPE) could then be subcode'd for an actual savings. Browse
through the patch to see if the effort is well-spent.

My conclusion from this is that, even if we don't store it in
tree_base, we really, really want a TREE_CODE that is > 8 bits, or we
want *gasp* separate codes for tcc_type vs. tcc_expression. If it
doesn't work in a switch statement, it's not a viable solution for the
C++ front end.


Just FYI on your patch:

+struct lang_type_header GTY(()) {
+  BOOL_BITFIELD subcode : 3;
+};

That should be an ENUM_BITFIELD (subcode);

 Cheers,
 Doug
Index: cp-tree.def
===================================================================
--- cp-tree.def	(revision 122840)
+++ cp-tree.def	(working copy)
@@ -166,7 +166,7 @@ DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "te
 
 /* The ordering of the following codes is optimized for the checking
    macros in tree.h.  Changing the order will degrade the speed of the
-   compiler.  TEMPLATE_TYPE_PARM, TYPENAME_TYPE, TYPEOF_TYPE,
+   compiler.  TEMPLATE_TYPE_PARM, TYPENAME_TYPE, 
    BOUND_TEMPLATE_TEMPLATE_PARM.  */
 
 /* Index into a template parameter list.  This parameter must be a type.
@@ -179,9 +179,9 @@ DEFTREECODE (TEMPLATE_ATE_TYPE_PARM, "templa
    TREE_TYPE is always NULL.  */
 DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
 
-/* A type designated by `__typeof (expr)'.  TYPEOF_TYPE_EXPR is the
-   expression in question.  */
-DEFTREECODE (TYPEOF_TYPE, "typeof_type", tcc_type, 0)
+/* An "unknown" type.  Used when we cannot determine the type of an
+   entity, e.g., because it is overloaded.  */
+DEFTREECODE (UNKNOWN_TYPE, "unknown_type", tcc_type, 0)
 
 /* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments
    like TT<int>.
Index: error.c
===================================================================
--- error.c	(revision 122840)
+++ error.c	(working copy)
@@ -382,12 +382,20 @@ dump_type (tree t, int flags)
       dump_type (DECL_NAME (TYPE_NAME (t)), flags);
       break;
 
-    case TYPEOF_TYPE:
-      pp_cxx_identifier (cxx_pp, "__typeof__");
-      pp_cxx_whitespace (cxx_pp);
-      pp_cxx_left_paren (cxx_pp);
-      dump_expr (TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
-      pp_cxx_right_paren (cxx_pp);
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  pp_cxx_identifier (cxx_pp, "__typeof__");
+	  pp_cxx_whitespace (cxx_pp);
+	  pp_cxx_left_paren (cxx_pp);
+	  dump_expr (TYPEOF_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
+	  pp_cxx_right_paren (cxx_pp);
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
       break;
 
     case TYPE_PACK_EXPANSION:
@@ -589,11 +597,25 @@ dump_type_prefix (tree t, int flags)
     case TYPENAME_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
-    case TYPEOF_TYPE:
       dump_type (t, flags);
       pp_base (cxx_pp)->padding = pp_before;
       break;
 
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  dump_type (t, flags);
+	  pp_base (cxx_pp)->padding = pp_before;
+	  break;
+	  
+	default:
+	  pp_unsupported_tree (cxx_pp, t);
+	  pp_identifier (cxx_pp, "<typeprefixerror>");
+	  break;
+	}
+      break;
+
     default:
       pp_unsupported_tree (cxx_pp, t);
       /* fall through.  */
@@ -685,7 +707,18 @@ dump_type_suffix (tree t, int flags)
     case TYPENAME_TYPE:
     case COMPLEX_TYPE:
     case VECTOR_TYPE:
-    case TYPEOF_TYPE:
+      break;
+
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  break;
+
+	default:
+	  pp_unsupported_tree (cxx_pp, t);
+	  break;
+	}
       break;
 
     default:
Index: tree.c
===================================================================
--- tree.c	(revision 122840)
+++ tree.c	(working copy)
@@ -2232,7 +2232,6 @@ cp_walk_subtrees (tree *tp, int *walk_su
     case TEMPLATE_PARM_INDEX:
     case TEMPLATE_TYPE_PARM:
     case TYPENAME_TYPE:
-    case TYPEOF_TYPE:
       /* None of these have subtrees other than those already walked
 	 above.  */
       *walk_subtrees_p = 0;
@@ -2300,6 +2299,19 @@ cp_walk_subtrees (tree *tp, int *walk_su
       *walk_subtrees_p = 0;
       break;
 
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (*tp))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  *walk_subtrees_p = 0;
+	  break;
+
+	default:
+	  input_location = save_locus;
+	  return NULL_TREE;
+	}
+      break;
+
     default:
       input_location = save_locus;
       return NULL_TREE;
Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 122840)
+++ cp-tree.h	(working copy)
@@ -921,10 +921,14 @@ enum languages { lang_c, lang_cplusplus,
 #define IS_AGGR_TYPE(T)					\
   (TREE_CODE (T) == TEMPLATE_TYPE_PARM			\
    || TREE_CODE (T) == TYPENAME_TYPE			\
-   || TREE_CODE (T) == TYPEOF_TYPE			\
+   || TYPEOF_TYPE_P (T)  		                \
    || TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM	\
    || TYPE_LANG_FLAG_5 (T))
 
+/* The subcode for LANG_TYPE nodes.  */
+#define LANG_TYPE_SUBCODE(NODE)					\
+  (TYPE_LANG_SPECIFIC (LANG_TYPE_CHECK (NODE))->u.c.h.subcode)
+
 /* Set IS_AGGR_TYPE for T to VAL.  T must be a class, struct, or
    union type.  */
 #define SET_IS_AGGR_TYPE(T, VAL) \
@@ -1018,12 +1022,20 @@ typedef tree_pair_s *tree_pair_p;
 DEF_VEC_O (tree_pair_s);
 DEF_VEC_ALLOC_O (tree_pair_s,gc);
 
+/* Enumeration containing all of the subcodes for C++ type nodes. */
+enum cp_lang_type_subcode 
+{
+  CLASS_TYPE_SUBCODE,
+  PTRMEM_TYPE_SUBCODE,
+  TYPEOF_TYPE_SUBCODE
+};
+
 /* 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(())
 {
-  BOOL_BITFIELD is_lang_type_class : 1;
+  ENUM_BITFIELD (cp_lang_type_subcode) subcode : 2;
 
   BOOL_BITFIELD has_type_conversion : 1;
   BOOL_BITFIELD has_init_ref : 1;
@@ -1031,8 +1043,6 @@ struct lang_type_header GTY(())
   BOOL_BITFIELD const_needs_init : 1;
   BOOL_BITFIELD ref_needs_init : 1;
   BOOL_BITFIELD has_const_assign_ref : 1;
-
-  BOOL_BITFIELD spare : 1;
 };
 
 /* This structure provides additional information above and beyond
@@ -1128,34 +1138,56 @@ struct lang_type_ptrmem GTY(())
   tree record;
 };
 
+/* Structure that stores information about the `typeof' type.  */
+struct lang_type_typeof GTY(())
+{
+  struct lang_type_header h;
+};
+
 struct lang_type GTY(())
 {
   union lang_type_u
   {
     struct lang_type_header GTY((skip (""))) 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;
+    struct lang_type_class  GTY((tag ("CLASS_TYPE_SUBCODE"))) c;
+    struct lang_type_ptrmem GTY((tag ("PTRMEM_TYPE_SUBCODE"))) ptrmem;
+    struct lang_type_typeof GTY((tag ("TYPEOF_TYPE_SUBCODE"))) type_of;
+  } GTY((desc ("%h.h.subcode"))) u;
 };
 
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 
 #define LANG_TYPE_CLASS_CHECK(NODE) __extension__		\
 ({  struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE);		\
-    if (! lt->u.h.is_lang_type_class)				\
+    if (lt->u.h.subcode != CLASS_TYPE_SUBCODE)			\
       lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
     &lt->u.c; })
 
 #define LANG_TYPE_PTRMEM_CHECK(NODE) __extension__		\
 ({  struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE);		\
-    if (lt->u.h.is_lang_type_class)				\
+    if (lt->u.h.subcode != PTRMEM_TYPE_SUBCODE)			\
       lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
     &lt->u.ptrmem; })
 
+#define LANG_TYPE_TYPEOF_CHECK(NODE) __extension__		\
+({  struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE);		\
+    if (lt->u.h.subcode != TYPEOF_TYPE_SUBCODE)			\
+      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);	\
+    &lt->u.type_of; })
+
+#define TYPEOF_TYPE_CHECK(T) __extension__				\
+({  const tree __t = (T);						\
+    if (TREE_CODE (__t) != LANG_TYPE					\
+        || TYPE_LANG_SPECIFIC (T)->u.h.subcode != TYPEOF_TYPE_SUBCODE)  \
+      lang_check_failed (__FILE__, __LINE__, __FUNCTION__);		\
+    __t; })
+
 #else
 
 #define LANG_TYPE_CLASS_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.c)
 #define LANG_TYPE_PTRMEM_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.ptrmem)
+#define LANG_TYPE_TYPEOF_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.type_of)
+#define TYPEOF_TYPE_CHECK(T) (T)
 
 #endif /* ENABLE_TREE_CHECKING */
 
@@ -2801,7 +2833,7 @@ more_aggr_init_expr_args_p (const aggr_i
       {									\
 	TYPE_LANG_SPECIFIC (NODE) = GGC_CNEWVAR				\
 	 (struct lang_type, sizeof (struct lang_type_ptrmem));		\
-	TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0;	\
+	TYPE_LANG_SPECIFIC (NODE)->u.h.subcode = PTRMEM_TYPE_SUBCODE;   \
       }									\
     TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.record = (VALUE);		\
   } while (0)
@@ -2831,7 +2863,12 @@ more_aggr_init_expr_args_p (const aggr_i
    `Y'.  */
 #define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member)
 
-/* The expression in question for a TYPEOF_TYPE.  */
+/* Whether NODE is a `typeof' type.  */
+#define TYPEOF_TYPE_P(NODE)			\
+  (TREE_CODE (NODE) == LANG_TYPE		\
+   && LANG_TYPE_SUBCODE (NODE) == TYPEOF_TYPE_SUBCODE)
+
+/* The expression in question for a `typeof' type.  */
 #define TYPEOF_TYPE_EXPR(NODE) (TYPEOF_TYPE_CHECK (NODE))->type.values
 
 /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
@@ -2863,8 +2900,6 @@ more_aggr_init_expr_args_p (const aggr_i
 #define ANON_UNION_TYPE_P(NODE) \
   (TREE_CODE (NODE) == UNION_TYPE && ANON_AGGR_TYPE_P (NODE))
 
-#define UNKNOWN_TYPE LANG_TYPE
-
 /* Define fields and accessors for nodes representing declared names.  */
 
 #define TYPE_WAS_ANONYMOUS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->was_anonymous)
@@ -4261,6 +4296,8 @@ extern tree copy_decl				(tree);
 extern tree copy_type				(tree);
 extern tree cxx_make_type			(enum tree_code);
 extern tree make_aggr_type			(enum tree_code);
+extern void cp_set_type_subcode                 (tree, 
+						 enum cp_lang_type_subcode);
 extern void yyerror				(const char *);
 extern void yyhook				(int);
 extern bool cxx_init				(void);
Index: cxx-pretty-print.c
===================================================================
--- cxx-pretty-print.c	(revision 122840)
+++ cxx-pretty-print.c	(working copy)
@@ -1574,7 +1574,6 @@ pp_cxx_type_id (cxx_pretty_printer *pp, 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_PARM_INDEX:
     case TEMPLATE_DECL:
-    case TYPEOF_TYPE:
     case TEMPLATE_ID_EXPR:
       pp_cxx_type_specifier_seq (pp, t);
       break;
@@ -1584,6 +1583,18 @@ pp_cxx_type_id (cxx_pretty_printer *pp, 
       pp_cxx_identifier (pp, "...");
       break;
 
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t)) {
+      case TYPEOF_TYPE_SUBCODE:
+	pp_cxx_type_specifier_seq (pp, t);
+	break;
+
+      default:
+	gcc_unreachable ();
+	break;
+      }
+      break;
+
     default:
       pp_c_type_id (pp_c_base (pp), t);
       break;
Index: pt.c
===================================================================
--- pt.c	(revision 122840)
+++ pt.c	(working copy)
@@ -5616,10 +5616,18 @@ for_each_template_parm_r (tree *tp, int 
       }
       break;
 
-    case TYPEOF_TYPE:
-      if (for_each_template_parm (TYPE_FIELDS (t), fn, data,
-				  pfd->visited))
-	return error_mark_node;
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  if (for_each_template_parm (TYPE_FIELDS (t), fn, data,
+				      pfd->visited))
+	    return error_mark_node;
+	  break;
+
+	default:
+	  break;
+	}
       break;
 
     case FUNCTION_DECL:
@@ -8861,20 +8869,6 @@ tsubst (tree t, tree args, tsubst_flags_
 				     e1, e2, QUALIFIED_NAME_IS_TEMPLATE (t));
       }
 
-    case TYPEOF_TYPE:
-      {
-	tree type;
-
-	type = finish_typeof (tsubst_expr 
-			      (TYPEOF_TYPE_EXPR (t), args,
-			       complain, in_decl,
-			       /*integral_constant_expression_p=*/false));
-	return cp_build_qualified_type_real (type,
-					     cp_type_quals (t)
-					     | cp_type_quals (type),
-					     complain);
-      }
-
     case TYPE_ARGUMENT_PACK:
     case NONTYPE_ARGUMENT_PACK:
       {
@@ -8895,6 +8889,28 @@ tsubst (tree t, tree args, tsubst_flags_
       }
       break;
 
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  {
+	    tree type;
+
+	    type = finish_typeof (tsubst_expr 
+				  (TYPEOF_TYPE_EXPR (t), args,
+				   complain, in_decl,
+				   /*integral_constant_expression_p=*/false));
+	    return cp_build_qualified_type_real (type,
+						 cp_type_quals (t)
+						 | cp_type_quals (type),
+						 complain);
+	  }
+
+	default:
+	  break;
+	}
+      /* Fall through.  */
+
     default:
       sorry ("use of %qs in template",
 	     tree_code_name [(int) TREE_CODE (t)]);
@@ -9437,7 +9453,6 @@ tsubst_copy (tree t, tree args, tsubst_f
     case ARRAY_TYPE:
     case TYPENAME_TYPE:
     case UNBOUND_CLASS_TEMPLATE:
-    case TYPEOF_TYPE:
     case TYPE_DECL:
       return tsubst (t, args, complain, in_decl);
 
@@ -9477,6 +9492,17 @@ tsubst_copy (tree t, tree args, tsubst_f
       error ("use %<...%> to expand argument pack");
       return error_mark_node;
 
+    case LANG_TYPE:
+      switch (LANG_TYPE_SUBCODE (t))
+	{
+	case TYPEOF_TYPE_SUBCODE:
+	  return tsubst (t, args, complain, in_decl);
+
+	default:
+	  break;
+	}
+      /* Fall through.  */
+
     default:
       return t;
     }
@@ -14627,7 +14653,7 @@ dependent_type_p_r (tree type)
   /* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
      expression is not type-dependent, then it should already been
      have resolved.  */
-  if (TREE_CODE (type) == TYPEOF_TYPE)
+  if (TYPEOF_TYPE_P (type))
     return true;
 
   /* A template argument pack is dependent if any of its packed
Index: semantics.c
===================================================================
--- semantics.c	(revision 122840)
+++ semantics.c	(working copy)
@@ -2921,7 +2921,8 @@ finish_typeof (tree expr)
 
   if (type_dependent_expression_p (expr))
     {
-      type = make_aggr_type (TYPEOF_TYPE);
+      type = make_node (LANG_TYPE);
+      cp_set_type_subcode (type, TYPEOF_TYPE_SUBCODE);
       TYPEOF_TYPE_EXPR (type) = expr;
 
       return type;
Index: lex.c
===================================================================
--- lex.c	(revision 122840)
+++ lex.c	(working copy)
@@ -763,10 +763,24 @@ copy_lang_type (tree node)
   if (! TYPE_LANG_SPECIFIC (node))
     return;
 
-  if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
-    size = sizeof (struct lang_type);
-  else
-    size = sizeof (struct lang_type_ptrmem);
+  switch (TYPE_LANG_SPECIFIC (node)->u.h.subcode)
+    {
+    case CLASS_TYPE_SUBCODE:  
+      size = sizeof (struct lang_type_class); 
+      break;
+
+    case PTRMEM_TYPE_SUBCODE: 
+      size = sizeof (struct lang_type_ptrmem); 
+      break;
+
+    case TYPEOF_TYPE_SUBCODE: 
+      size = sizeof (struct lang_type_typeof);
+      break;
+
+    default:
+      gcc_unreachable();
+    }
+      
   lt = GGC_NEWVAR (struct lang_type, size);
   memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
   TYPE_LANG_SPECIFIC (node) = lt;
@@ -801,7 +815,7 @@ cxx_make_type (enum tree_code code)
       struct lang_type *pi = GGC_CNEW (struct lang_type);
 
       TYPE_LANG_SPECIFIC (t) = pi;
-      pi->u.c.h.is_lang_type_class = 1;
+      pi->u.c.h.subcode = CLASS_TYPE_SUBCODE;
 
 #ifdef GATHER_STATISTICS
       tree_node_counts[(int)lang_type] += 1;
@@ -830,3 +844,31 @@ make_aggr_type (enum tree_code code)
 
   return t;
 }
+
+void 
+cp_set_type_subcode (tree t, enum cp_lang_type_subcode subcode)
+{
+ switch (subcode)
+   {
+   case CLASS_TYPE_SUBCODE:
+     TYPE_LANG_SPECIFIC (t) =
+       GGC_CNEWVAR (struct lang_type, sizeof (struct lang_type_class));
+     break;
+
+   case PTRMEM_TYPE_SUBCODE:
+     TYPE_LANG_SPECIFIC (t) =
+       GGC_CNEWVAR (struct lang_type, sizeof (struct lang_type_ptrmem));
+     break;
+
+
+   case TYPEOF_TYPE_SUBCODE:
+     TYPE_LANG_SPECIFIC (t) =
+       GGC_CNEWVAR (struct lang_type, sizeof (struct lang_type_typeof));
+     break;
+
+   default:
+     gcc_unreachable ();
+   }
+
+ LANG_TYPE_SUBCODE (t) = subcode;
+}

Reply via email to