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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: We're out of tree codes; now what?


On 3/21/07, Mark Mitchell <mark@codesourcery.com> wrote:
Yes, that's true.  Here, however, we have two paths in front of us:
9-bit tree codes, or some language-dependent subcodes.  The benefit of
9-bit tree codes is that they're easy to understand; the benefit of
subcodes is that they might be faster, but, then again, they might use
more memory.  I'd be interested in understanding the tradeoff.

I have now implemented subcodes for all of the C++ type nodes. The patch is attached. It bootstraps and passes C++ compiler and libstdc++-v3 test suites. A small amount of work remains before we would be able to build other front ends, because I had to change some common bits.

The basic approach:

 I've used the LANG_TYPE tree code to identify the subcoded types
within the C++ front end. When TREE_CODE (T) = LANG_TYPE, the C++
front end will look into TYPE_LANG_SPECIFIC to dig out a subcode. All
of the "tcc_type" nodes that were in cp-tree.def are now subcoded
types.

 To keep the same switches and tests in the C++ front end, I added
LANG_TREE_CODE, which maps normal trees and subcoded trees into the
same code space (subcoded trees get codes > 256). Relying heavily on
warnings about case values being out of range and comparisons that
always produce false, I tweaked those TREE_CODE accesses in the front
end to instead use LANG_TREE_CODE.

The results, memory usage:

Memory usage rose a constant, negligible amount. I was able to fit the
subcode into padding in the existing lang_tree struct for the two
lang_tree kinds that are dynamically allocated (lang_tree_class,
lang_tree_ptrmem). For the new lang_tree kinds, we allocate only
lang_tree_headers, and I've used Daniel's trick of keeping constant
lang_tree_header pointers as statics. So, aside from a compile new
one-time allocations, --enable-gather-detailed-mem-stats doesn't show
any differences in memory usage. Good.

The results, compile time:

For a bootstrapped, --disable-checking compiler:

8-bit tree code (baseline):

real    0m51.987s
user    0m41.283s
sys     0m0.420s

subcodes (this patch):

real    0m53.168s
user    0m41.297s
sys     0m0.432s

9-bit tree code (alternative):

real    0m56.409s
user    0m43.942s
sys     0m0.429s

So, performance of subcodes is comparable to baseline with
--disable-checking. Good.

With --enable-checking, the results are quite frightening:

8-bit tree codes (baseline, --enable-checking):

real    1m56.776s
user    1m54.995s
sys     0m0.541s

subcodes (--enable-checking):

real    3m32.030s
user    2m53.606s
sys     0m0.486s

50% slower. Ouch! I only decided to check --enable-checking
performance after I noticed that the libstdc++-v3 tests were taking
way too long to run.

So without looking at the patch itself, we can get about the same
performance with no change in memory usage, but that horrific slowdown
in --enable-checking is going to seriously hurt the C++ front end
development process.

The patch itself is really big, so I'll try to point out the highlights:

cp_types.def:

All of the tcc_type nodes from cp-tree.def have moved into
cp-types.def, because they are subcoded. All of these subcoded types
share the same, top-level "LANG_TYPE".

cp-tree.h:

enum cplus_tree_code contains all of the common, C, and C++ tree
codes, followed by a separator with the value 256, then the subcoded
types. So subcoded types always have values > 256. LANG_TREE_CODE
extracts the "extended" tree code from a tree, by adding the type
subcode to 256 when we see a LANG_TYPE node.

struct lang_type_header has the new 8-bit subcode. TYPE_LANG_SPECIFIC
always points to at least a struct lang_type_header, possibly
something larger (for RECORD_TYPE nodes).

You'll see lots of TREE_CODE -> LANG_TREE_CODE changes; I'll get back
to those later.

cp/cp-lang.c:

I ended up making the tree_code_type, tree_code_length, and
tree_code_name structures larger, to accommodate the new tree codes. I
also had to make them non-const, because there is no good way to
initialize the first N elements in an array, fill the elements from N
to 256, then initialize everything beyond 256.

cp/lex.c:

cxx_make_type has been updated to check the (extended) tree code it is
given. If that tree code > 256, it builds a LANG_TYPE with the
appropriate subcode (note how we don't allocate anything for most
subcoded types; only the ones that allocated a TYPE_LANG_SPECIFIC
before).

everywhere:

The TREE_CODE -> LANG_TREE_CODE fixes took most of the development
effort for this patch. I ended up doing a lot of grep'ing, watching
GCC's warnings carefully, and debugging ICEs to get everything up and
running. It wasn't pretty, and I'm not convinced I got them all. GCC's
warning about comparisons always being false or case values that are
too large (both due to limited range of data types) were somewhat
useful, but they miss two important kinds of cases:

(a)
 enum tree_code code = TREE_CODE (t);
 switch (code)
   {
   case TYPENAME_TYPE:
     // oops, we'll never get here, because TYPENAME_TYPE is
subtyped. GCC does *not* warn about this
   break;
   }

(b)
 if (TREE_CODE (t1) != TREE_CODE (t2)) // all LANG_TYPEs are created
equal; uh-oh
   return false;

Grep found most of the latter, gdb found most of the former. Not pretty.

On significant problem remains, and it will get uglier if we don't
address it. The middle-end doesn't know anything about subcodes, so it
treats LANG_TYPE like any other type. That almost works, because all
type nodes are the same size (100 bytes!), but if one tries to
"debug_tree" the tree node name is always "lang_type." If we tried to
subcode expressions and declarations, we may run into problems where
tree_code_length is wrong.

So, while I was trying to keep my changes in the C++ front end, I
think the only way to make subcodes work is to teach the middle-end
that LANG_TYPE (and future LANG_DECL and LANG_EXPR) are subcoded. That
probably means creating hooks for tree_code_name and tree_code_length,
possibly others.

Take a skim through the patch. There might be some cleanups that one
could do, and perhaps things might be a little nicer if subcodes were
in the middle-end as described above. However, I find this solution to
be rather unwieldy, and the process that makes it possible (grepping,
watching warnings) to be problematic for future development. The 50%
slowdown in the C++ front end with --enable-checking is also a great
concern to me.

Comments always welcome, and generally appreciated :)

 Cheers,
 Doug
Index: tree.c
===================================================================
--- tree.c	(revision 123123)
+++ tree.c	(working copy)
@@ -490,6 +490,8 @@ make_node_stat (enum tree_code code MEM_
 #ifdef GATHER_STATISTICS
   tree_node_kind kind;
 
+  gcc_assert (code < MAX_TREE_CODES);
+
   switch (type)
     {
     case tcc_declaration:  /* A decl node */
Index: tree.h
===================================================================
--- tree.h	(revision 123123)
+++ tree.h	(workiorking copy)
@@ -81,7 +81,7 @@ extern const char *const tree_code_class
         tree_code_class_strings[(int) (CLASS)]
 
 #define MAX_TREE_CODES 256
-extern const enum tree_code_class tree_code_type[];
+extern enum tree_code_class tree_code_type[];
 #define TREE_CODE_CLASS(CODE)	tree_code_type[(int) (CODE)]
 
 /* Nonzero if CODE represents an exceptional code.  */
@@ -197,12 +197,12 @@ extern const enum tree_code_class tree_c
 
 /* Number of argument-words in each kind of tree-node.  */
 
-extern const unsigned char tree_code_length[];
+extern unsigned char tree_code_length[];
 #define TREE_CODE_LENGTH(CODE)	tree_code_length[(int) (CODE)]
 
 /* Names of tree components.  */
 
-extern const char *const tree_code_name[];
+extern const char * tree_code_name[];
 
 /* A vectors of trees.  */
 DEF_VEC_P(tree);
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 123123)
+++ cp/typeck.c	(working copy)
@@ -944,7 +944,7 @@ structural_comptypes (tree t1, tree t2, 
 
   /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
      current instantiation.  */
-  if (TREE_CODE (t1) == TYPENAME_TYPE)
+  if (LANG_TREE_CODE (t1) == TYPENAME_TYPE)
     {
       tree resolved = resolve_typename_type (t1, /*only_current_p=*/true);
 
@@ -952,7 +952,7 @@ structural_comptypes (tree t1, tree t2, 
 	t1 = resolved;
     }
 
-  if (TREE_CODE (t2) == TYPENAME_TYPE)
+  if (LANG_TREE_CODE (t2) == TYPENAME_TYPE)
     {
       tree resolved = resolve_typename_type (t2, /*only_current_p=*/true);
 
@@ -966,7 +966,7 @@ structural_comptypes (tree t1, tree t2, 
     t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
 
   /* Different classes of types can't be compatible.  */
-  if (TREE_CODE (t1) != TREE_CODE (t2))
+  if (LANG_TREE_CODE (t1) != LANG_TREE_CODE (t2))
     return false;
 
   /* Qualifiers must match.  For array types, we will check when we
@@ -986,7 +986,7 @@ structural_comptypes (tree t1, tree t2, 
     return true;
 
   /* Compare the types.  Break out if they could be the same.  */
-  switch (TREE_CODE (t1))
+  switch (LANG_TREE_CODE (t1))
     {
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -999,7 +999,7 @@ structural_comptypes (tree t1, tree t2, 
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
-      if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
+      if (LANG_TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
       strict = COMPARE_STRICT;
@@ -1009,7 +1009,7 @@ structural_comptypes (tree t1, tree t2, 
     case UNION_TYPE:
       if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2)
 	  && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2)
-	      || TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM)
+	      || LANG_TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM)
 	  && comp_template_args (TYPE_TI_ARGS (t1), TYPE_TI_ARGS (t2)))
 	break;
 
@@ -6776,7 +6776,7 @@ comp_ptr_ttypes_real (tree to, tree from
 
   for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
     {
-      if (TREE_CODE (to) != TREE_CODE (from))
+      if (LANG_TREE_CODE (to) != LANG_TREE_CODE (from))
 	return 0;
 
       if (TREE_CODE (from) == OFFSET_TYPE
@@ -6836,7 +6836,7 @@ ptr_reasonably_similar (tree to, tree fr
 	  || TREE_CODE (from) == VOID_TYPE)
 	return 1;
 
-      if (TREE_CODE (to) != TREE_CODE (from))
+      if (LANG_TREE_CODE (to) != LANG_TREE_CODE (from))
 	return 0;
 
       if (TREE_CODE (from) == OFFSET_TYPE
@@ -6872,7 +6872,7 @@ comp_ptr_ttypes_const (tree to, tree fro
 {
   for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
     {
-      if (TREE_CODE (to) != TREE_CODE (from))
+      if (LANG_TREE_CODE (to) != LANG_TREE_CODE (from))
 	return false;
 
       if (TREE_CODE (from) == OFFSET_TYPE
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 123123)
+++ cp/init.c	(working copy)
@@ -1284,8 +1284,8 @@ is_aggr_type (tree type, int or_else)
     return 0;
 
   if (! IS_AGGR_TYPE (type)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM)
+      && LANG_TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && LANG_TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM)
     {
       if (or_else)
 	error ("%qT is not an aggregate type", type);
@@ -2538,7 +2538,7 @@ build_vec_init (tree base, tree maxindex
 	  base2 = get_temp_regvar (itype, base2);
 	  itype = TREE_TYPE (itype);
 	}
-      else if (TYPE_LANG_SPECIFIC (type)
+      else if (TYPE_LANG_SPECIFIC_P (type)
 	       && TYPE_NEEDS_CONSTRUCTING (type)
 	       && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
 	{
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 123123)
+++ cp/class.c	(working copy)
@@ -986,7 +986,7 @@ add_method (tree type, tree method, tree
       tree parms1;
       tree parms2;
 
-      if (TREE_CODE (fn) != TREE_CODE (method))
+      if (LANG_TREE_CODE (fn) != LANG_TREE_CODE (method))
 	continue;
 
       /* [over.load] Member function declarations with the
@@ -2001,7 +2001,7 @@ update_vtable_entry_for_fn (tree t, tree
   base_return = TREE_TYPE (TREE_TYPE (target_fn));
 
   if (POINTER_TYPE_P (over_return)
-      && TREE_CODE (over_return) == TREE_CODE (base_return)
+      && LANG_TREE_CODE (over_return) == LANG_TREE_CODE (base_return)
       && CLASS_TYPE_P (TREE_TYPE (over_return))
       && CLASS_TYPE_P (TREE_TYPE (base_return))
       /* If the overrider is invalid, don't even try.  */
@@ -5606,8 +5606,8 @@ push_nested_class (tree type)
       || type == error_mark_node
       || TREE_CODE (type) == NAMESPACE_DECL
       || ! IS_AGGR_TYPE (type)
-      || TREE_CODE (type) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+      || LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM
+      || LANG_TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
     return;
 
   context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
@@ -5993,7 +5993,7 @@ instantiate_type (tree lhstype, tree rhs
 
   flags &= ~tf_ptrmem_ok;
 
-  if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
+  if (LANG_TREE_CODE (lhstype) == UNKNOWN_TYPE)
     {
       if (flags & tf_error)
 	error ("not enough type information");
Index: cp/repo.c
===================================================================
--- cp/repo.c	(revision 123123)
+++ cp/repo.c	(working copy)
@@ -302,7 +302,7 @@ repo_emit_p (tree decl)
       else if (DECL_TINFO_P (decl))
 	type = TREE_TYPE (DECL_NAME (decl));
       if (!DECL_TEMPLATE_INSTANTIATION (decl)
-	  && (!TYPE_LANG_SPECIFIC (type)
+	  && (!TYPE_LANG_SPECIFIC_P (type)
 	      || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
 	return 2;
       /* Static data members initialized by constant expressions must
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 123123)
+++ cp/decl.c	(working copy)
@@ -940,7 +940,7 @@ decls_match (tree newdecl, tree olddecl)
 		&& DECL_EXTERN_C_P (olddecl)))
 	return 0;
 
-      if (TREE_CODE (f1) != TREE_CODE (f2))
+      if (LANG_TREE_CODE (f1) != LANG_TREE_CODE (f2))
 	return 0;
 
       if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
@@ -1605,7 +1605,7 @@ duplicate_decls (tree newdecl, tree oldd
       tree oldtype = TREE_TYPE (olddecl);
 
       if (newtype != error_mark_node && oldtype != error_mark_node
-	  && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
+	  && TYPE_LANG_SPECIFIC_P (newtype) && TYPE_LANG_SPECIFIC_P (oldtype))
 	CLASSTYPE_FRIEND_CLASSES (newtype)
 	  = CLASSTYPE_FRIEND_CLASSES (oldtype);
 
@@ -2801,7 +2801,7 @@ make_typename_type (tree context, tree n
 
   if (TYPE_P (name))
     {
-      if (!(TYPE_LANG_SPECIFIC (name)
+      if (!(TYPE_LANG_SPECIFIC_P (name)
 	    && (CLASSTYPE_IS_TEMPLATE (name)
 		|| CLASSTYPE_USE_TEMPLATE (name))))
 	name = TYPE_IDENTIFIER (name);
@@ -3196,7 +3196,7 @@ cxx_init_decl_processing (void)
 
   /* C++ extensions */
 
-  unknown_type_node = make_node (UNKNOWN_TYPE);
+  unknown_type_node = cxx_make_type (UNKNOWN_TYPE);
   record_unknown_type (unknown_type_node, "unknown type");
 
   /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node.  */
@@ -3620,7 +3620,7 @@ check_tag_decl (cp_decl_specifier_seq *d
 
   if (declspecs->type
       && TYPE_P (declspecs->type)
-      && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
+      && ((LANG_TREE_CODE (declspecs->type) != TYPENAME_TYPE
 	   && IS_AGGR_TYPE (declspecs->type))
 	  || TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
     declared_type = declspecs->type;
@@ -8077,13 +8077,13 @@ grokdeclarator (const cp_declarator *dec
 	    if (TYPE_NAME (t) == oldname)
 	      TYPE_NAME (t) = decl;
 
-	  if (TYPE_LANG_SPECIFIC (type))
+	  if (TYPE_LANG_SPECIFIC_P (type))
 	    TYPE_WAS_ANONYMOUS (type) = 1;
 
 	  /* If this is a typedef within a template class, the nested
 	     type is a (non-primary) template.  The name for the
 	     template needs updating as well.  */
-	  if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
+	  if (TYPE_LANG_SPECIFIC_P (type) && CLASSTYPE_TEMPLATE_INFO (type))
 	    DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
 	      = TYPE_IDENTIFIER (type);
 
@@ -8183,9 +8183,9 @@ grokdeclarator (const cp_declarator *dec
 	  if (!current_aggr)
 	    {
 	      /* Don't allow friend declaration without a class-key.  */
-	      if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+	      if (LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM)
 		pedwarn ("template parameters cannot be friends");
-	      else if (TREE_CODE (type) == TYPENAME_TYPE)
+	      else if (LANG_TREE_CODE (type) == TYPENAME_TYPE)
 		pedwarn ("friend declaration requires class-key, "
 			 "i.e. %<friend class %T::%D%>",
 			 TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
@@ -9554,7 +9554,7 @@ check_elaborated_type_specifier (enum ta
 
   /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
      is false for this case as well.  */
-  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+  if (LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM)
     {
       error ("using template type parameter %qT after %qs",
 	     type, tag_name (tag_code));
@@ -9960,9 +9960,9 @@ xref_basetypes (tree ref, tree base_list
       if (TREE_CODE (basetype) == TYPE_DECL)
 	basetype = TREE_TYPE (basetype);
       if (TREE_CODE (basetype) != RECORD_TYPE
-	  && TREE_CODE (basetype) != TYPENAME_TYPE
-	  && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
-	  && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
+	  && LANG_TREE_CODE (basetype) != TYPENAME_TYPE
+	  && LANG_TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+	  && LANG_TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
 	{
 	  error ("base type %qT fails to be a struct or class type",
 		 basetype);
@@ -11555,7 +11555,7 @@ maybe_register_incomplete_var (tree var)
 
       if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
 	  /* RTTI TD entries are created while defining the type_info.  */
-	  || (TYPE_LANG_SPECIFIC (inner_type)
+	  || (TYPE_LANG_SPECIFIC_P (inner_type)
 	      && TYPE_BEING_DEFINED (inner_type)))
 	incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
     }
Index: cp/config-lang.in
===================================================================
--- cp/config-lang.in	(revision 123123)
+++ cp/config-lang.in	(working copy)
@@ -31,4 +31,4 @@ compilers="cc1plus\$(exeext)"
 
 target_libs="target-libstdc++-v3"
 
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c"
+gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/lex.c"
Index: cp/cp-tree.def
===================================================================
--- cp/cp-tree.def	(revision 123123)
+++ cp/cp-tree.def	(working copy)
@@ -155,46 +155,6 @@ DEFTREECODE (TEMPLATE_DECL, "template_de
    worrying about instantiating things.  */
 DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", tcc_exceptional, 0)
 
-/* Index into a template parameter list for template template parameters.
-   This parameter must be a type.  The TYPE_FIELDS value will be a
-   TEMPLATE_PARM_INDEX.
-
-   It is used without template arguments like TT in C<TT>,
-   TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO is NULL_TREE
-   and TYPE_NAME is a TEMPLATE_DECL.  */
-DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", tcc_type, 0)
-
-/* 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,
-   BOUND_TEMPLATE_TEMPLATE_PARM.  */
-
-/* Index into a template parameter list.  This parameter must be a type.
-   The type.values field will be a TEMPLATE_PARM_INDEX.  */
-DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", tcc_type, 0)
-
-/* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
-   TYPE_NAME is an IDENTIFIER_NODE for `t'.  If the type was named via
-   template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
-   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)
-
-/* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments
-   like TT<int>.
-   In this case, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO contains the
-   template name and its bound arguments.  TYPE_NAME is a TYPE_DECL.  */
-DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
-	     tcc_type, 0)
-
-/* For template template argument of the form `T::template C'.
-   TYPE_CONTEXT is `T', the template parameter dependent object.
-   TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template.  */
-DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", tcc_type, 0)
-
 /* A using declaration.  USING_DECL_SCOPE contains the specified
    scope.  In a member using decl, unless DECL_DEPENDENT_P is true,
    USING_DECL_DECLS contains the _DECL or OVERLOAD so named.  This is
@@ -352,25 +312,6 @@ DEFTREECODE (UNARY_PLUS_EXPR, "unary_plu
    literal) to be displayed if the condition fails to hold.  */
 DEFTREECODE (STATIC_ASSERT, "static_assert", tcc_exceptional, 0)
 
-/* Represents an argument pack of types (or templates). An argument
-   pack stores zero or more arguments that will be used to instantiate
-   a parameter pack. 
-
-   ARGUMENT_PACK_ARGS retrieves the arguments stored in the argument
-   pack.
-
-   Example:
-     template<typename... Values>
-     class tuple { ... };
-
-     tuple<int, float, double> t;
-
-   Values is a (template) parameter pack. When tuple<int, float,
-   double> is instantiated, the Values parameter pack is instantiated
-   with the argument pack <int, float, double>. ARGUMENT_PACK_ARGS will
-   be a TREE_VEC containing int, float, and double.  */
-DEFTREECODE (TYPE_ARGUMENT_PACK, "type_argument_pack", tcc_type, 0)
-
 /* Represents an argument pack of values, which can be used either for
    non-type template arguments or function call arguments. 
 
@@ -380,29 +321,6 @@ DEFTREECODE (TYPE_ARGUMENT_PACK, "type_a
    Args&... args"). */
 DEFTREECODE (NONTYPE_ARGUMENT_PACK, "nontype_argument_pack", tcc_expression, 1)
 
-/* Represents a type expression that will be expanded into a list of
-   types when instantiated with one or more argument packs.
-
-   PACK_EXPANSION_PATTERN retrieves the expansion pattern. This is
-   the type or expression that we will substitute into with each
-   argument in an argument pack.
-
-   SET_PACK_EXPANSION_PATTERN sets the expansion pattern.
-
-   PACK_EXPANSION_PARAMETER_PACKS contains a TREE_LIST of the parameter
-   packs that are used in this pack expansion.
-
-   Example:
-     template<typename... Values>
-     struct tied : tuple<Values&...> { 
-       // ...
-     };
-
-   The derivation from tuple contains a TYPE_PACK_EXPANSION for the
-   template arguments. Its EXPR_PACK_EXPANSION is "Values&" and its
-   PACK_EXPANSION_PARAMETER_PACKS will contain "Values".  */
-DEFTREECODE (TYPE_PACK_EXPANSION, "type_pack_expansion", tcc_type, 0)
-
 /* Represents an expression that will be expanded into a list of
    expressions when instantiated with one or more argument packs.
 
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 123123)
+++ cp/call.c	(working copy)
@@ -2010,7 +2010,7 @@ add_builtin_candidate (struct z_candidat
   /* If we're dealing with two pointepes or two enumeral types,
      we need candidates for both of them.  */
   if (type2 && !same_type_p (type1, type2)
-      && TREE_CODE (type1) == TREE_CODE (type2)
+      && LANG_TREE_CODE (type1) == LANG_TREE_CODE (type2)
       && (TREE_CODE (type1) == REFERENCE_TYPE
 	  || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
 	  || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
@@ -6214,7 +6214,7 @@ joust (struct z_candidate *cand1, struct
 	  tree t = TREE_TYPE (TREE_TYPE (l->fn));
 	  tree f = TREE_TYPE (TREE_TYPE (w->fn));
 
-	  if (TREE_CODE (t) == TREE_CODE (f) && POINTER_TYPE_P (t))
+	  if (LANG_TREE_CODE (t) == LANG_TREE_CODE (f) && POINTER_TYPE_P (t))
 	    {
 	      t = TREE_TYPE (t);
 	      f = TREE_TYPE (f);
Index: cp/ptree.c
===================================================================
--- cp/ptree.c	(revision 123123)
+++ cp/ptree.c	(working copy)
@@ -62,7 +62,7 @@ cxx_print_decl (FILE *file, tree node, i
 void
 cxx_print_type (FILE *file, tree node, int indent)
 {
-  switch (TREE_CODE (node))
+  switch (LANG_TREE_CODE (node))
     {
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
Index: cp/Make-lang.in
===================================================================
--- cp/Make-lang.in	(revision 123123)
+++ cp/Make-lang.in	(working copy)
@@ -229,7 +229,7 @@ CXX_TREE_H = $(TREE_H) cp/name-lookup.h 
 CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
 
 cp/lex.o: cp/lex.c $(CXX_TREE_H) _H) $(TM_H) $(FLAGS_H) \
-  $(C_PRAGMA_H) toplev.h output.h input.h cp/operators.def $(TM_P_H)
+  $(C_PRAGMA_H) toplev.h output.h input.h cp/operators.def gt-cp-lex.h $(TM_P_H)
 cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h debug.h langhooks.h \
   $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h \
   $(DIAGNOSTIC_H) cp/cp-objcp-common.h
Index: cp/error.c
===================================================================
--- cp/error.c	(revision 123123)
+++ cp/error.c	(working copy)
@@ -276,7 +276,7 @@ dump_type (tree t, int flags)
   if (TYPE_PTRMEMFUNC_P (t))
     goto offset_type;
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case UNKNOWN_TYPE:
       pp_identifier (cxx_pp, "<unresolved overloaded function type>");
@@ -413,7 +413,7 @@ dump_typename (tree t, int flags)
 {
   tree ctx = TYPE_CONTEXT (t);
 
-  if (TREE_CODE (ctx) == TYPENAME_TYPE)
+  if (LANG_TREE_CODE (ctx) == TYPENAME_TYPE)
     dump_typename (ctx, flags);
   else
     dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
@@ -430,7 +430,7 @@ class_key_or_enum_as_string (tree t)
     return "enum";
   else if (TREE_CODE (t) == UNION_TYPE)
     return "union";
-  else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
+  else if (TYPE_LANG_SPECIFIC_P (t) && CLASSTYPE_DECLARED_CLASS (t))
     return "class";
   else
     return "struct";
@@ -461,7 +461,7 @@ dump_aggr_type (tree t, int flags)
     {
       typdef = !DECL_ARTIFICIAL (name);    tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
-		&& TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
+		&& TYPE_LANG_SPECIFIC_P (t) && CLASSTYPE_TEMPLATE_INFO (t)
 		&& (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
 		    || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
       
@@ -516,7 +516,7 @@ dump_type_prefix (tree t, int flags)
       goto offset_type;
     }
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -612,7 +612,7 @@ dump_type_suffix (tree t, int flags)
   if (TYPE_PTRMEMFUNC_P (t))
     t = TYPE_PTRMEMFUNC_FN_TYPE (t);
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -741,14 +741,14 @@ dump_decl (tree t, int flags)
   if (t == NULL_TREE)
     return;
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case TYPE_DECL:
       /* Don't say 'typedef class A' */
       if (DECL_ARTIFICIAL (t))
 	{
 	  if ((flags & TFF_DECL_SPECIFIERS)
-	      && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
+	      && LANG_TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
 	    /* Say `class T' not just `T'.  */
 	    pp_cxx_identifier (cxx_pp, "class");
 
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 123123)
+++ cp/tree.c	(working copy)
@@ -739,8 +739,8 @@ cp_build_qualified_type_real (tree tee t
   /* A restrict-qualified type must be a pointer (or reference)
      to object or incomplete type, or a function type. */
   if ((type_quals & TYPE_QUAL_RESTRICT)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (type) != TYPENAME_TYPE
+      && LANG_TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && LANG_TREE_CODE (type) != TYPENAME_TYPE
       && TREE_CODE (type) != FUNCTION_TYPE
       && !POINTER_TYPE_P (type))
     {
@@ -1792,7 +1792,7 @@ cp_tree_equal (tree t1, tree t2)
 	tree o1 = TREE_OPERAND (t1, 0);
 	tree o2 = TREE_OPERAND (t2, 0);
 
-	if (TREE_CODE (o1) != TREE_CODE (o2))
+	if (LANG_TREE_CODE (o1) != LANG_TREE_CODE (o2))
 	  return false;
 	if (TYPE_P (o1))
 	  return same_type_p (o1, o2);
@@ -2202,7 +2202,7 @@ tree
 cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
 		  void *data, struct pointer_set_t *pset)
 {
-  enum tree_code code = TREE_CODE (*tp);
+  enum tree_code code = LANG_TREE_CODE (*tp);
   location_t save_locus;
   tree result;
 
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 123123)
+++ cp/mangle.c	(working copy)
@@ -86,8 +86,9 @@
    without parameters inside the template.  */
 #define CLASSTYPE_TEMPLATE_ID_P(NODE)					\
   (TYPE_LANG_SPECIFIC (NODE) != NULL					\
-   && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM			\
-       || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL			\
+   && (LANG_TREE_CODE ODE E) == BOUND_TEMPLATE_TEMPLATE_PARM		\
+       || (TYPE_LANG_SPECIFIC_P (NODE)					\
+           && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL			\
 	   && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
 
 /* Things we only need one of.  This module is not reentrant.  */
@@ -456,7 +457,7 @@ is_std_substitution (const tree node,
     return 0;
 
   return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
-	  && TYPE_LANG_SPECIFIC (type)
+	  && TYPE_LANG_SPECIFIC_P (type)
 	  && TYPE_TEMPLATE_INFO (type)
 	  && (DECL_NAME (TYPE_TI_TEMPLATE (type))
 	      == subst_identifiers[index]));
@@ -985,11 +986,11 @@ write_prefix (const tree node)
     }
 
   /* In G++ 3.2, the name of the template parameter was used.  */
-  if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+  if (LANG_TREE_CODE (node) == TEMPLATE_TYPE_PARM
       && !abi_version_at_least (2))
     G.need_abi_warning = true;
 
-  if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+  if (LANG_TREE_CODE (node) == TEMPLATE_TYPE_PARM
       && abi_version_at_least (2))
     write_template_param (node);
   else if (template_info != NULL)
@@ -1065,11 +1066,11 @@ write_template_prefix (const tree node)
     return;
 
   /* In G++ 3.2, the name of the template template parameter was used.  */
-  if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+  if (LANG_TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
       && !abi_version_at_least (2))
     G.need_abi_warning = true;
 
-  i-  if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+  if (LANG_TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
       && abi_version_at_least (2))
     write_template_param (TREE_TYPE (template));
   else
@@ -1562,7 +1563,7 @@ write_type (tree type)
 
       if (TYPE_PTRMEM_P (type))
 	write_pointer_to_member_type (type);
-      else switch (TREE_CODE (type))
+      else switch (LANG_TREE_CODE (type))
 	{
 	case VOID_TYPE:
 	case BOOLEAN_TYPE:
@@ -2012,7 +2013,7 @@ write_expression (tree expr)
 {
   enum tree_code code;
 
-  code = TREE_CODE (expr);
+  code = LANG_TREE_CODE (expr);
 
   /* Skip NOP_EXPRs.  They can occur when (say) a pointer argument
      is converted (via qualification conversions) to another
@@ -2021,13 +2022,13 @@ write_expression (tree expr)
 	 || TREE_CODE (expr) == NON_LVALUE_EXPR)
     {
       expr = TREE_OPERAND (expr, 0);
-      code = TREE_CODE (expr);
+      code = LANG_TREE_CODE (expr);
     }
 
   if (code == BASELINK)
     {
       expr = BASELINK_FUNCTIONS (expr);
-      code = TREE_CODE (expr);
+      code = LANG_TREE_CODE (expr);
     }
 
   /* Handle pointers-to-members by making them look like expression
@@ -2039,7 +2040,7 @@ write_expression (tree expr)
 					     PTRMEM_CST_CLASS (expr),
 					     PTRMEM_CST_MEMBER (expr),
 					     /*template_p=*/false));
-      code = TREE_CODE (expr);
+      code = LANG_TREE_CODE (expr);
     }
 
   /* Handle template parameters.  */
@@ -2444,7 +2445,7 @@ write_template_param (const tree parm)
 
   MANGLE_TRACE_TREE ("template-parm", parm);
 
-  switch (TREE_CODE (parm))
+  switch (LANG_TREE_CODE (parm))
     {
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
@@ -2483,7 +2484,7 @@ write_template_template_param (const tre
   /* PARM, a TEMPLATE_TEMPLATE_PARM, is an instantiation of the
      template template parameter.  The substitution candidate here is
      only the template.  */
-  if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (LANG_TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
     {
       template
 	= TI_TEMPLATE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm));
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 123123)
+++ cp/cp-tree.h	(working copy)
@@ -164,6 +164,21 @@ struct diagnostic_context;
      the virtual function this one overrides, and whose TREE_CHAIN is
      the old DECL_VINDEX.  */
 
+#undef TREE_CODE
+/* We redefine TREE_CODE here to omit the explicit case to "enum
+   tree_code", which has the side-effect of silencing the "case value
+   NNN not in enumerated type" warnings.  */
+#define TREE_CODE(NODE) ((NODE)->base.code)
+
+/* Extracts an extended tree code from a node. */
+#define LANG_TREE_CODE(NODE)                            \
+  (TREE_CODE (NODE) == LANG_TYPE?                       \
+     (enum cplus_tree_code)(LANG_TYPE_SUBCODE (NODE) + MAX_TREE_CODES)    \
+     : (enum cplus_tree_code)(TREE_CODE (NODE)))
+
+/* Access the SUBCODE of a LANG_TYPE node.  */
+#define LANG_TYPE_SUBCODE(NODE) (TYPE_LANG_SPECIFIC (NODE)->u.h.subcode)
+
 /* Language-specific tree checkers.  */
 
 #define VAR_OR_FUNCTION_DECL_CHECK(NODE) \
@@ -176,7 +191,7 @@ struct diagnostic_context;
   TREE_CHECK4(NODE,VAR_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL)
 
 #define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
-  TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
+  LANG_TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
 
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 #define NON_THUNK_FUNCTION_CHECK(NODE) __extension__			\
@@ -192,10 +207,41 @@ struct diagnostic_context;
 	|| !__t->decl_common.lang_specific->decl_flags.thunk_p)		\
       tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0);	\
      __t; })
+#define LANG_TREE_CHECK(T,CODE) __extension__			\
+({  const tree __x = (T);					\
+    if (LANG_TREE_CODE ((T)) != (CODE))				\
+      tree_check_failed (__x, __FILE__, __LINE__, __FUNCTION__, \
+                         (CODE), 0);				\
+    __x; })
+#define LANG_TREE_CHECK3(T, CODE1, CODE2, CODE3) __extension__	\
+({  const tree __y = (T);					\
+    const enum cplus_tree_code __code = LANG_TREE_CODE (__y);	\
+    if (__code != (CODE1)					\
+	&& __code != (CODE2)					\
+	&& __code != (CODE3))					\
+      tree_check_failed (__y, __FILE__, __LINE__, __FUNCTION__,	\
+			     (CODE(CODE2), (CODE3), 0);	\
+    __y; })
 #else
 #define NON_THUNK_FUNCTION_CHECK(NODE) (NODE)
 #define THUNK_FUNCTION_CHECK(NODE) (NODE)
+#define LANG_TREE_CHECK(T,CODE) (T)
+#define LANG_TREE_CHECK3(T, CODE1, CODE2, CODE3) (T)
 #endif
+
+/* Tree checkers for subcoded trees.  */
+#define TEMPLATE_TYPE_PARM_CHECK(T)  (LANG_TREE_CHECK (T,TEMPLATE_TYPE_PARM))
+#define TYPENAME_TYPE_CHECK(T)       (LANG_TREE_CHECK (T,TYPENAME_TYPE))
+#define TEMPLATE_TEMPLATE_PARM_CHECK(T)		\
+  (LANG_TREE_CHECK (T,TEMPLATE_TEMPLATE_PARM))
+#define BOUND_TEMPLATE_TEMPLATE_PARM_CHECK(T)		\
+  (LANG_TREE_CHECK (T,BOUND_TEMPLATE_TEMPLATE_PARM))
+#define UNBOUND_CLASS_TEMPLATE_CHECK(T)		\
+  (LANG_TREE_CHECK (T,UNBOUND_CLASS_TEMPLATE))
+#define TYPEOF_TYPE_CHECK(T)         (LANG_TREE_CHECK (T,TYPEOF_TYPE))
+#define UNKNOWN_TYPE_CHECK(T)        (LANG_TREE_CHECK (T,UNKNOWN_TYPE))
+#define TYPE_ARGUMENT_PACK_CHECK(T)  (LANG_TREE_CHECK (T,TYPE_ARGUMENT_PACK))
+#define TYPE_PACK_EXPANSION_CHECK(T) (LANG_TREE_CHECK (T,TYPE_PACK_EXPANSION))
 
 /* Language-dependent contents of an identifier.  */
 
@@ -884,10 +930,21 @@ struct language_function GTY(())
 enum cplus_tree_code {
   CP_DUMMY_TREE_CODE = LAST_C_TREE_CODE,
 #include "cp-tree.def"
-  LAST_CPLUS_TREE_CODE
+  LAST_CPLUS_TREE_CODE,
+  CPLUS_FIRST_SUBCODE = MAX_TREE_CODES,
+  CPLUS_FIRST_TYPE_SUBCODE = CPLUS_FIRST_SUBCODE,
+#include "cp-types.def"
+  CPLUS_LAST_TYPE_SUBCODE,
+  CPLUS_LAST_SUBCODE = CPLUS_LAST_TST_TYPE_SUBCODE
 };
 #undef DEFTREECODE
 
+/* The number of C++ subcodes in use.  */
+#define CPLUS_SUBCODES (CPLUS_LAST_SUBCODE - CPLUS_FIRST_SUBCODE)
+/* The number of C++ type subcodes in use.  */
+#define CPLUS_TYPE_SUBCODES					\
+  (CPLUS_LAST_TYPE_SUBCODE - CPLUS_FIRST_TYPE_SUBCODE - 1)
+
 /* TRUE if a tree code represents a statement.  */
 extern bool statement_code_p[MAX_TREE_CODES];
 
@@ -915,11 +972,11 @@ enum languages { lang_c, lang_cplusplus,
    this macro has nothing to do with the definition of aggregate given
    in the standard.  Think of this macro as MAYBE_CLASS_TYPE_P.  Keep
    these checks in ascending code order.  */
-#define IS_AGGR_TYPE(T)					\
-  (TREE_CODE (T) == TEMPLATE_TYPE_PARM			\
-   || TREE_CODE (T) == TYPENAME_TYPE			\
-   || TREE_CODE (T) == TYPEOF_TYPE			\
-   || TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM	\
+#define IS_AGGR_TYPE(T)						\
+  (LANG_TREE_CODE (T) == TEMPLATE_TYPE_PARM			\
+   || LANG_TREE_CODE (T) == TYPENAME_TYPE			\
+   || LANG_TREE_CODE (T) == TYPEOF_TYPE				\
+   || LANG_TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM	\
    || TYPE_LANG_FLAG_5 (T))
 
 /* Set IS_AGGR_TYPE for T to VAL.  T must be a class, struct, or
@@ -1020,6 +1077,8 @@ DEF_VEC_ALLOC_O (tree_pair_s,gc);
    are put in this structure to save space.  */
 struct lang_type_header GTY(())
 {
+  int subcode : 8;
+
   BOOL_BITFIELD is_lang_type_class : 1;
 
   BOOL_BITFIELD has_type_conversion : 1;
@@ -1097,7 +1156,7 @@ struct lang_type_class GTY(())
   /* 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 : 12;
+  unsigned dummy : 4;
 
   tree primary_base;
   VEC(tree_pair_s,gc) *vcall_indices;
@@ -1132,7 +1191,9 @@ struct lang_type GTY(())
     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;
+  } GTY((desc ("%h.h.is_lang_type_class"
+	       " ? 1"
+	       " : (%h.h.subcode == 0) ? 0 : 2"))) u;
 };
 
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
@@ -1156,6 +1217,15 @@ struct lang_type GTY(())
 
 #endif /* ENABLE_TREE_CHECKING */
 
+/* True when NODE has a "real" TYPE_LANG_SPECIFIC that contains
+   additional information, as in RECORD_TYPE nodes.  Some nodes used
+   TYPE_LANG_SPECIFIC only for the subcode.  This predicate will be
+   false for such nodes.  */
+#define TYPE_LANG_SPECIFIC_P(NODE)					\
+  (TYPE_LANG_SPECIFIC (NODE)						\
+   && (TYPE_LANG_SPECIFIC (NODE)->u.h.subcode == 0			\
+       || LANG_TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM))
+
 /* Fields used for storing information before the class is defined.
    After the class is defined, these fields hold other information.  */
 
@@ -1390,7 +1460,7 @@ struct lang_type GTY(())
 /* Nonzero if this class has const members
    which have no specified initialization.  */
 #define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE)	\
-  (TYPE_LANG_SPECIFIC (NODE)				\
+  (TYPE_LANG_SPECIFIC_P (NODE)				\
    ? LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init : 0)
 #define SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE, VALUE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init = (VALUE))
@@ -1398,7 +1468,7 @@ struct lang_type GTY(())
 /* Nonzero if this class has ref members
    which have no specified initialization.  */
 #define CLASSTYPE_REF_FIELDS_NEED_INIT(NODE)		\
-  (TYPE_LANG_SPECIFIC (NODE)				\
+  (TYPE_LANG_SPECIFIC_P (NODE)				\
    ? LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init : 0)
 #define SET_CLASSTYPE_REF_FIELDS_NEED_INIT(NODE, VALUE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init = (VALUE))
@@ -2165,13 +2235,13 @@ extern void decl_shadowed_for_var_insert
    ->template_info)
 
 /* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE.  */
-#define TYPE_TEMPLATE_INFO(NODE)			\
-  (TREE_CODE (NODE) == ENUMERAL_TYPE			\
-   ? ENUM_TEMPLATE_INFO (NODE) :			\
-   (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM	\
-    ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) :	\
-    (TYPE_LANG_SPECIFIC (NODE)				\
-     ? CLASSTYPE_TEMPLATE_INFO (NODE)			\
+#define TYPE_TEMPLATE_INFO(NODE)				\
+  (TREE_CODE (NODE) == ENUMERAL_TYPE				\
+   ? ENUM_TEMPLATE_INFO (NODE) :				\
+   (LANG_TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM	\
+    ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) :		\
+    (TYPE_LANG_SPECIFIC_P (NODE)					\
+     ? CLASSTYPE_TEMPLATE_INFO (NODE)				\
      : NULL_TREE)))
 
 /* Set the template information for an ENUMERAL_, RECORD_, or
@@ -2314,22 +2384,22 @@ extern void decl_shadowed_for_var_insert
 
 /* Determines if NODE is an expansion of one or more parameter packs,
    e.g., a TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION.  */
-#define PACK_EXPANSION_P(NODE)                 \
-  (TREE_CODE (NODE) == TYPE_PACK_EXPANSION     \
+#define PACK_EXPANSION_P(NODE)			\
+  (LANG_TREE_CODE (NODE) == TYPE_PACK_EXPANSION	\
    || TREE_CODE (NODE) == EXPR_PACK_EXPANSION)
 
 /* Extracts the type or expression pattern from a TYPE_PACK_EXPANSION or
    EXPR_PACK_EXPANSION.  */
-#define PACK_EXPANSION_PATTERN(NODE)                            \
-  (TREE_CODE (NODE) == TYPE_PACK_EXPANSION? TREE_TYPE (NODE)    \
+#define PACK_EXPANSION_PATTERN(NODE)					\
+  (LANG_TREE_CODE (NODE) == TYPE_PACK_EXPANSION? TREE_TYPE (NODE)	\
    : TREE_OPERAND (NODE, 0))
 
 /* Sets the type or expression pattern for a TYPE_PACK_EXPANSION or
    EXPR_PACK_EXPANSION.  */
-#define SET_PACK_EXPANSION_PATTERN(NODE,VALUE)  \
-  if (TREE_CODE (NODE) == TYPE_PACK_EXPANSION)  \
-    TREE_TYPE (NODE) = VALUE;                   \
-  else                                          \
+#define SET_PACK_EXPANSION_PATTERN(NODE,VALUE)		\
+  if (LANG_TREE_CODE (NODE) == TYPE_PACK_EXPANSION)	\
+    TREE_TYPE (NODE) = VALUE;				\
+  else							\
     TREE_OPERAND (NODE, 0) = VALUE
 
 /* The list of parameter packs used in the PACK_EXPANSION_* node. The
@@ -2338,19 +2408,19 @@ extern void decl_shadowed_for_var_insert
 
 /* Determine if this is an argument pack.  */
 #define ARGUMENT_PACK_P(NODE)                          \
-  (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK              \
+  (LANG_TREE_CODE (NODE) == TYPE_ARGUMENT_PACK         \
    || TREE_CODE (NODE) == NONTYPE_ARGUMENT_PACK)
 
 /* The arguments stored in an argument pack. Arguments are stored in a
    TREE_VEC, which may have length zero.  */
-#define ARGUMENT_PACK_ARGS(NODE)                               \
-  (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK? TREE_TYPE (NODE)    \
+#define ARGUMENT_PACK_ARGS(NODE)					\
+  (LANG_TREE_CODE (NODE) == TYPE_ARGUMENT_PACK? TREE_TYPE (NODE)	\
    : TREE_OPERAND (NODE, 0))
 
 /* Set the arguments stored in an argument pack. VALUE must be a
    TREE_VEC.  */
-#define SET_ARGUMENT_PACK_ARGS(NODE,VALUE)     \
-  if (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK)  \
+#define SET_ARGUMENT_PACK_ARGS(NODE,VALUE)		\
+  if (LANG_TREE_CODE (NODE) == TYPE_ARGUMENT_PACK)	\
     TREE_TYPE (NODE) = VALUE;                           \
   else                                                  \
     TREE_OPERAND (NODE, 0) = VALUE
@@ -2763,7 +2833,7 @@ more_aggr_init_expr_args_p (const aggr_i
    function type.  */
 #define TYPE_PTRMEMFUNC_P(NODE)		\
   (TREE_CODE (NODE) == RECORD_TYPE	\
-   && TYPE_LANG_SPECIFIC (NODE)		\
+   && TYPE_LANG_SPECIFIC_P (NODE)		\
    && TYPE_PTRMEMFUNC_FLAG (NODE))
 
 #define TYPE_PTRMEMFUNC_FLAG(NODE) \
@@ -2791,7 +2861,7 @@ more_aggr_init_expr_args_p (const aggr_i
 /* 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) \
-  (TYPE_LANG_SPECIFIC (NODE) ? LANG_TYPE_PTRMEM_CHECK (NODE)->record : NULL)
+  (TYPE_LANG_SPECIFIC_P (NODE) ? LANG_TYPE_PTRMEM_CHECK (NODE)->record : NULL)
 #define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE)				\
   do {									\
     if (TYPE_LANG_SPECIFIC (NODE) == NULL)				\
@@ -2860,8 +2930,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)
@@ -3707,9 +3775,9 @@ enum overload_flags { NO_SPECIAL = 0, DT
 
 /* These macros are for accessing the fields of TEMPLATE_TYPE_PARM,
    TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM nodes.  */
-#define TEMPLATE_TYPE_PARM_INDEX(NODE)					 \
-  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,	\
-		BOUND_TEMPLATE_TEMPLATE_PARM))->type.values
+#define TEMPLATE_TYPE_PARM_INDEX(NODE)					\
+  (LANG_TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, \
+		     BOUND_TEMPLATE_TEMPLATE_PARM))->type.values
 #define TEMPLATE_TYPE_IDX(NODE) \
   (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_LEVEL(NODE) \
@@ -3756,9 +3824,9 @@ enum overload_flags { NO_SPECIAL = 0, DT
 
 /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
    node.  */
-#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL(NODE)	\
-  ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)	\
-   ? TYPE_TI_TEMPLATE (NODE)				\
+#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL(NODE)		\
+  ((LANG_TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)	\
+   ? TYPE_TI_TEMPLATE (NODE)					\
    : TYPE_NAME (NODE))
 
 /* in lex.c  */
Index: cp/dump.c
===================================================================
--- cp/dump.c	(revision 123123)
+++ cp/dump.c	(working copy)
@@ -251,7 +251,8 @@ cp_dump_tree (void* dump_info, tree t)
 
     case UNION_TYPE:
       /* Is it a type used as a base? */
-      if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t)
+      if (TYPE_CONTEXT (t) 
+	  && LANG_TREE_CODE (TYPE_CONTEXT (t)) == LANG_TREE_CODE (t)
 	  && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
 	{
 	  dump_child ("bfld", TYPE_CONTEXT (t));
Index: cp/search.c
===================================================================
--- cp/search.c	(revision 123123)
+++ cp/search.c	(working copy)
@@ -383,9 +383,9 @@ lookup_field_1 (tree type, tree name, bo
 {
   tree field;
 
-  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
-      || TREE_CODE (type) == TYPENAME_TYPE)
+  if (LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM
+      || LANG_TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
+      || LANG_TREE_CODE (type) == TYPENAME_TYPE)
     /* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM and
        BOUND_TEMPLATE_TEMPLATE_PARM are not fields at all;
        instead TYPE_FIELDS is the TEMPLATE_PARM_INDEX.  (Miraculously,
Index: cp/friend.c
===================================================================
--- cp/friend.c	(revision 123123)
+++ cp/friend.c	(working copy)
@@ -267,7 +267,7 @@ make_friend_class (tree type, tree frien
      class.  */
   if (!friend_depth)
     ;/* ok */
-  else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
+  else if (LANG_TREE_CODE (friend_type) == TYPENAME_TYPE)
     {
       if (TREE_CODE (TYPENAME_TYPE_FULLNAME (friend_type))
 	  == TEMPLATE_ID_EXPR)
@@ -335,7 +335,7 @@ make_friend_class (tree type, tree frien
 	    }
 	}
     }
-  else if (TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
+  else if (LANG_TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
     {
       /* template <class T> friend class T; */
       error ("template parameter type %qT declared %<friend%>", friend_type);
Index: cp/cp-types.def
===================================================================
--- cp/cp-types.def	(revision 0)
+++ cp/cp-types.def	(revision 0)
@@ -0,0 +1,114 @@
+/* This file contains the definitions and documentation for the C++-specific
+   type subcodes used in the GNU C++ compiler (see tree.def and cp-tree.def
+   for the standard codes).
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Hacked by Douglas Gregor (doug.gregor@gmail.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/* 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,
+   BOUND_TEMPLATE_TEMPLATE_PARM.  */
+
+/* Index into a template parameter list.  This parameter must be a type.
+   The type.values field will be a TEMPLATE_PARM_INDEX.  */
+DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", tcc_type, 0)
+
+/* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
+   TYPE_NAME is an IDENTIFIER_NODE for `t'.  If the type was named via
+   template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
+   TREE_TYPE is always NULL.  */
+DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
+
+/* Index into a template parameter list for template template parameters.
+   This parameter must be a type.  The TYPE_FIELDS value will be a
+   TEMPLATE_PARM_INDEX.
+
+   It is used without template arguments like TT in C<TT>,
+   TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO is NULL_TREE
+   and TYPE_NAME is a TEMPLATE_DECL.  */
+DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", tcc_type, 0)
+
+/* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments
+   like TT<int>.
+   In this case, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO contains the
+   template name and its bound arguments.  TYPE_NAME is a TYPE_DECL.  */
+DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
+	     tcc_type, 0)
+
+/* For template template argument of the form `T::template C'.
+   TYPE_CONTEXT is `T', the template parameter dependent object.
+   TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template.  */
+DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", 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)
+
+/* Represents an argument pack of types (or templates). An argument
+   pack stores zero or more arguments that will be used to instantiate
+   a parameter pack. 
+
+   ARGUMENT_PACK_ARGS retrieves the arguments stored in the argument
+   pack.
+
+   Example:
+     template<typename... Values>
+     class tuple { ... };
+
+     tuple<int, float, double> t;
+
+   Values is a (template) parameter pack. When tuple<int, float,
+   double> is instantiated, the Values parameter pack is instantiated
+   with the argument pack <int, float, double>. ARGUMENT_PACK_ARGS will
+   be a TREE_VEC containing int, float, and double.  */
+DEFTREECODE (TYPE_ARGUMENT_PACK, "type_argument_pack", tcc_type, 0)
+
+/* Represents a type expression that will be expanded into a list of
+   types when instantiated with one or more argument packs.
+
+   PACK_EXPANSION_PATTERN retrieves the expansion pattern. This is
+   the type or expression that we will substitute into with each
+   argument in an argument pack.
+
+   SET_PACK_EXPANSION_PATTERN sets the expansion pattern.
+
+   PACK_EXPANSION_PARAMETER_PACKS contains a TREE_LIST of the parameter
+   packs that are used in this pack expansion.
+
+   Example:
+     template<typename... Values>
+     struct tied : tuple<Values&...> { 
+       // ...
+     };
+
+   The derivation from tuple contains a TYPE_PACK_EXPANSION for the
+   template arguments. Its EXPR_PACK_EXPANSION is "Values&" and its
+   PACK_EXPANSION_PARAMETER_PACKS will contain "Values".  */
+DEFTREECODE (TYPE_PACK_EXPANSION, "type_pack_expansion", tcc_type, 0)
+
+/*
+Local variables:
+mode:c
+End:
+*/
Index: cp/cxx-pretty-print.c
===================================================================
--- cp/cxx-pretty-print.c	(revision 123123)
+++ cp/cxx-pretty-print.c	(working copy)
@@ -342,7 +342,7 @@ pp_cxx_id_expression (cxx_pretty_printer
 static void
 pp_cxx_primary_expression (cxx_pretty_printer *pp, tree t)
 {
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case INTEGER_CST:
     case REAL_CST:
@@ -917,7 +917,7 @@ pp_cxx_assignment_expression (cxx_pretty
 static void
 pp_cxx_expression (cxx_pretty_printer *pp, tree t)
 {
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case STRING_CST:
     case INTEGER_CST:
@@ -1136,7 +1136,7 @@ pp_cxx_decl_specifier_seq (cxx_pretty_pr
 static void
 pp_cxx_simple_type_specifier (cxx_pretty_printer *pp, tree t)
 {
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -1175,7 +1175,7 @@ pp_cxx_simple_type_specifier (cxx_pretty
 static void
 pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
 {
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case TEMPLATE_DECL:
     case TEMPLATE_TYPE_PARM:
@@ -1368,7 +1368,7 @@ pp_cxx_exception_specification (cxx_pret
 static void
 pp_cxx_direct_declarator (cxx_pretty_printer *pp, tree t)
 {
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case VAR_DECL:
     case PARM_DECL:
@@ -1515,7 +1515,7 @@ pp_cxx_abstract_declarator (cxx_pretty_p
 static void
 pp_cxx_direct_abstract_declarator (cxx_pretty_printer *pp, tree t)
 {
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case REFERENCE_TYPE:
       pp_cxx_abstract_declarator (pp, t);
@@ -1561,7 +1561,7 @@ pp_cxx_type_id (cxx_pretty_printer *pp, 
   pp_flags saved_flags = pp_c_base (pp)->flags;
   pp_c_base (pp)->flags |= pp_c_flag_abstract;
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case TYPE_DECL:
     case UNION_TYPE:
@@ -1972,7 +1972,7 @@ pp_cxx_template_parameter (cxx_pretty_pr
 void
 pp_cxx_canonical_template_parameter (cxx_pretty_printer *pp, tree parm)
 {
-  const enum tree_code code = TREE_CODE (parm);
+  const enum tree_code code = LANG_TREE_CODE (parm);
 
   /* Brings type template parameters to the canonical forms.  */
   if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM
Index: cp/cp-lang.c
===================================================================
--- cp/cp-lang.c	(revision 123123)
+++ cp/cp-la	(working copy)
@@ -61,13 +61,18 @@ const struct lang_hooks lang_hooks = LAN
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
 
-const enum tree_code_class tree_code_type[] = {
+enum tree_code_class tree_code_type[CPLUS_LAST_SUBCODE] = {
 #include "tree.def"
   tcc_exceptional,
 #include "c-common.def"
   tcc_exceptional,
 #include "cp-tree.def"
 };
+
+const enum tree_code_class tree_subcode_type[CPLUS_SUBCODES] = {
+  tcc_exceptional,
+#include "cp-types.def"
+};
 #undef DEFTREECODE
 
 /* Table indexed by tree code giving number of expression
@@ -76,26 +81,36 @@ const enum tree_code_class tree_code_typ
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
 
-const unsigned char tree_code_length[] = {
+unsigned char tree_code_length[CPLUS_LAST_SUBCODE] = {
 #include "tree.def"
   0,
 #include "c-common.def"
   0,
 #include "cp-tree.def"
 };
+
+const unsigned char tree_subcode_length[CPLUS_SUBCODES] = {
+  0,
+#include "cp-types.def"
+};
 #undef DEFTREECODE
 
 /* Names of tree components.
    Used for printing out the tree and error messages.  */
 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
 
-const char *const tree_code_name[] = {
+const char * tree_code_name[CPLUS_LAST_SUBCODE] = {
 #include "tree.def"
   "@@dummy",
 #include "c-common.def"
   "@@dummy",
 #include "cp-tree.def"
 };
+
+const char* const tree_subcode_name[CPLUS_SUBCODES] = {
+  "@@dummy",
+#include "cp-types.def"
+};
 #undef DEFTREECODE
 
 /* Lang hook rou routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c;
@@ -117,6 +132,8 @@ objcp_tsubst_copy_and_build (tree t ATTR
 static void
 cp_init_ts (void)
 {
+  int i;
+
   tree_contains_struct[NAMESPACE_DECL][TS_DECL_NON_COMMON] = 1;
   tree_contains_struct[USING_DECL][TS_DECL_NON_COMMON] = 1;
   tree_contains_struct[TEMPLATE_DECL][TS_DECL_NON_COMMON] = 1;
@@ -137,6 +154,22 @@ cp_init_ts (void)
   tree_contains_struct[USING_DECL][TS_DECL_MINIMAL] = 1;
   tree_contains_struct[TEMPLATE_DECL][TS_DECL_MINIMAL] = 1;
 
+  /* Populate TREE_CODE_TYPE, TREE_CODE_LENGTH, and TREE_CODE_NAME
+     fields for subcoded nodes, including appropriate padding
+     beforehand. */
+  for (i = LAST_CPLUS_TREE_CODE; i < CPLUS_FIRST_SUBCODE; ++i)
+    {
+      tree_code_type[i] = tcc_exceptional;
+      tree_code_length[i] = 0;
+      tree_code_name[i] = "@@dummy";
+    }
+  for (; i < CPLUS_LAST_SUBCODE; ++i)
+    {
+      tree_code_type[i] = tree_subcode_type[i - CPLUS_FIRST_SUBCODE];
+      tree_code_length[i] = tree_subcode_length[i - CPLUS_FIRST_SUBCODE];
+      tree_code_name[i] = tree_subcode_name[i - CPLUS_FIRST_SUBCODE];
+    }
+
   init_shadowed_var_for_decl ();
 
 }
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 123123)
+++ cp/typeck2.c	(working copy)
@@ -363,7 +363,7 @@ cxx_incomplete_type_diagnostic (tree val
  retry:
   /* We must print an error message.  Be clever about whatsays.  */
 
-  switch (TREE_CODE (type))
+  switch (LANG_TREE_CODE (type))
     {
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -1381,7 +1381,7 @@ add_exception_specifier (tree list, tree
     ok = true;
   else if (VOID_TYPE_P (core))
     ok = is_ptr;
-  else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM)
+  else if (LANG_TREE_CODE (core) == TEMPLATE_TYPE_PARM)
     ok = true;
   else if (processing_template_decl)
     ok = true;
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 123123)
+++ cp/pt.c	(working copy)
@@ -700,7 +700,7 @@ maybe_process_partial_specialization (tr
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (LANG_TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
     {
       error ("name of class shadows template template parameter %qD",
 	     TYPE_NAME (type));
@@ -2264,10 +2264,10 @@ comp_template_parms (tree parms1, tree p
           if (parm1 == error_mark_node || parm2 == error_mark_node)
             return 1;
 
-	  if (TREE_CODE (parm1) != TREE_CODE (parm2))
+	  if (LANG_TREE_CODE (parm1) != LANG_TREE_CODE (parm2))
 	    return 0;
 
-	  if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM
+	  if (LANG_TREE_CODE (parm1) == TEMPLATE_TYPE_PARM
               && (TEMPLATE_TYPE_PARAMETER_PACK (parm1)
                   == TEMPLATE_TYPE_PARAMETER_PACK (parm2)))
 	    continue;
@@ -2298,8 +2298,298, template_parameter_pack_p (tree parm)
   if (TREE_CODE (parm) == TYPE_DECL || TREE_CODE (parm) == TEMPLATE_DECL)
     parm = TREE_TYPE (parm);
 
-  return ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
-	   || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
+  return ((LANG_TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+	   || LANG_TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
 	  && TEMPLATE_TYPE_PARAMETER_PACK (parm));
 }
 
@@ -2377,7 +2377,7 @@ find_parameter_packs_r (tree *tp, int *w
 
   /* This switch statement will return immediately if we don't find a
      parameter pack.  */
-  switch (TREE_CODE (t)) 
+  switch (LANG_TREE_CODE (t)) 
     {
     case TEMPLATE_PARM_INDEX:
       if (TEMPLATE_PARM_PARAMETER_PACK (t))
@@ -2536,7 +2536,7 @@ make_pack_expansion (tree arg)
       pointer_set_destroy (ppd.visited);
 
       /* Create the pack expansion type for the base type.  */
-      purpose = make_node (TYPE_PACK_EXPANSION);
+      purpose = cxx_make_type (TYPE_PACK_EXPANSION);
       SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
       PACK_EXPANSION_PARAMETER_PACKS (purpose) = parameter_packs;
 
@@ -2551,7 +2551,10 @@ make_pack_expansion (tree arg)
     for_types = true;
 
   /* Build the PACK_EXPANSION_* node.  */
-  result = make_node (for_types ? TYPE_PACK_EXPANSION : EXPR_PACK_EXPANSION);
+  if (for_types)
+    result = cxx_make_type (TYPE_PACK_EXPANSION);
+  else
+    result = make_node (EXPR_PACK_EXPANSION);
   SET_PACK_EXPAEXPANSION_PATTERN (result, arg);
   if (TREE_CODE (result) == EXPR_PACK_EXPANSION)
     {
@@ -2619,8 +2622,8 @@ check_for_bare_parameter_packs (tree t)
         tree pack = TREE_VALUE (parameter_packs);
         tree name = NULL_TREE;
 
-        if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
-            || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
+        if (LANG_TREE_CODE (pack) == TEMPLATE_TYPE_PARM
+            || LANG_TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
           name = TYPE_NAME (pack);
         else
           name = DECL_NAME (pack);
@@ -3039,7 +3042,7 @@ current_template_args (void)
                           tree vec = make_tree_vec (1);
                           TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
                           
-                          t = make_node (TYPE_ARGUMENT_PACK);
+                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
                           SET_ARGUMENT_PACK_ARGS (t, vec);
                         }
                     }
@@ -4451,7 +4454,7 @@ coerce_template_template_parms (tree par
 	  || parm == NULL_TREE || parm == error_mark_node)
 	return 0;
 
-      if (TREE_CODE (arg) != TREE_CODE (parm))
+      if (LANG_TREE_CODE (arg) != LANG_TREE_CODE (parm))
 	return 0;
 
       switch (TREE_CODE (parm))
@@ -4541,24 +4544,24 @@ convert_template_argument (tree parm,
 
   /* When determining whether a argument pack expansion is a template,
      look at the pattern.  */
-  if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
+  if (LANG_TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
     check_arg = PACK_EXPANSION_PATTERN (check_arg);
 
   is_tmpl_type = 
     ((TREE_CODE (check_arg) == TEMPLATE_DECL
       && TREE_CODE (DECL_TEMPLATE_RESULT (check_arg)) == TYPE_DECL)
-     || TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
-     || TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE);
+     || LANG_TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
+     || LANG_TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE);
 
   if (is_tmpl_type
-      && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
-	  || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
+      && (LANG_TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+	  || LANG_TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
     arg = TYPE_STUB_DECL (arg);
 
   is_type = TYPE_P (arg) || is_tmpl_type;
 
   if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
-      && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
+      && LANG_TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
     {
       pedwarn ("to refer to a type member of a template parameter, "
 	       "use %<typename %E%>", arg);
@@ -4609,7 +4612,7 @@ convert_template_argument (tree parm,
     {
       if (requires_tmpl_type)
 	{
-	  if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
+	  if (LANG_TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
 	    /* The number of argument required is not known yet.
 	       Just accept it for now.  */
 	    val = TREE_TYPE (arg);
@@ -4621,7 +4624,7 @@ convert_template_argument (tree parm,
               check_arg = arg;
               /* When determining whether a pack expansion is a template,
                  look at the pattern.  */
-              if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
+              if (LANG_TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
                 check_arg = PACK_EXPANSION_PATTERN (check_arg);
 
               argparm = DECL_INNERMOST_TEMPLATE_PARMS (check_arg);
@@ -4638,7 +4641,7 @@ convert_template_argument (tree parm,
                     {
                       if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
                         val = TREE_TYPE (val);
-                      else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
+                      else if (LANG_TREE_CODE (val) == TYPE_PACK_EXPANSION
                                && DECL_TEMPLATE_TEMPLATE_PARM_P (check_arg))
                         {
                           val = TREE_TYPE (check_arg);
@@ -4918,7 +4921,7 @@ coerce_template_parms (tree parms,
 
       if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
           || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
-          argument_pack = make_node (TYPE_ARGUMENT_PACK);
+          argument_pack = cxx_make_type (TYPE_ARGUMENT_PACK);
       else
         {
           argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
@@ -5129,7 +5132,7 @@ lookup_template_class (tree d1,
 
       /* If we are declaring a constructor, say A<T>::A<T>, we will get
 	 an implicit typename for the second A.  Deal with it.  */
-      if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+      if (LANG_TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
 	type = TREE_TYPE (type);
 
       if (CLASSTYPE_TEMPLATE_INFO (type))
@@ -5565,7 +5568,7 @@ for_each_template_parm_r (tree *tp, int 
       && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
     return error_mark_node;
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
@@ -6469,7 +6472,7 @@ instantiate_class_template (tree type)
 	      bool class_template_p;
 
 	      class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
-				  && TYPE_LANG_SPECIFIC (t)
+				  && TYPE_LANG_SPECIFIC_P (t)
 				  && CLASSTYPE_IS_TEMPLATE (t));
 	      /* If the member is a class template, then -- even after
 		 substitution -- there may be dependent types in the
@@ -6623,7 +6626,7 @@ instantiate_class_template (tree type)
 		  friend_type = tsubst_friend_class (friend_type, args);
 		  adjust_processing_template_decl = true;
 		}
-	      else if (TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
+	      else if (LANG_TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
 		{
 		  /* template <class T> friend class C::D;  */
 		  friend_type = tsubst (friend_type, ar@@ -6632,7 +6635,7 @@ instantiate_class_template (tree type)
 		    friend_type = TREE_TYPE (friend_type);
 		  adjust_processing_template_decl = true;
 		}
-	      else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
+	      else if (LANG_TREE_CODE (friend_type) == TYPENAME_TYPE)
 		{
 		  /* This could be either
 
@@ -6848,7 +6851,7 @@ tsubst_pack_expansion (tree t, tree args
             }
           else if (len != my_len)
             {
-              if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
+              if (LANG_TREE_CODE (t) == TYPE_PACK_EXPANSION)
                 error ("mismatched argument pack lengths while expanding "
                        "%<%T%>",
                        pattern);
@@ -7004,7 +7007,10 @@ tsubst_template_args (tree t, tree args,
       else if (ARGUMENT_PACK_P (orig_arg))
         {
           /* Substitute into each of the arguments.  */
-          new_arg = make_node (TREE_CODE (orig_arg));
+	  if (LANG_TREE_CODE (orig_arg) == TYPE_ARGUMENT_PACK)
+	    new_arg = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  else
+	    new_arg = make_node (NONTYPE_ARGUMENT_PACK);
           
           SET_ARGUMENT_PACK_ARGS (
             new_arg,
@@ -7684,7 +7690,7 @@ tsubst_decl (tree t, tree args, tsubst_f
               spec = retrieve_local_specialization (t);
             if (spec 
                 && TREE_CODE (spec) == PARM_DECL
-                && TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
+                    && LANG_TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
               return spec;
 
             /* Expand the TYPE_PACK_EXPANSION that provides the types for
@@ -7830,7 +7836,7 @@ tsubst_decl (tree t, tree args, tsubst_f
 	if (TREE_CODE (t) == TYPE_DECL)
 	  {
 	    type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-	    if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+	    if (LANG_TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
 		|| t == TYPE_MAIN_DECL (TREE_TYPE (t)))
 	      {
 		/* If this is the canonical decl, we don't have to
@@ -8282,7 +8288,7 @@ tsubst (tree t, tree args, tsubst_flags_
   gcc_assert (type != unknown_type_node);
 
   if (type
-      && TREE_CODE (t) != TYPENAME_TYPE
+      && LANG_TREE_CODE (t) != TYPENAME_TYPE
       && TREE_CODE (t) != IDENTIFIER_NODE
       && TREE_CODE (t) != FUNCTION_TYPE
       && TREE_CODE (t) != METHOD_TYPE)
@@ -8290,7 +8296,7 @@ tsubst (tree t, tree args, tsubst_flags_
   if (type == error_mark_node)
     return error_mark_node;
 
-  switch (TREE_CODE (t))
+  switch (LANG_TREE_CODE (t))
     {
     case RECORD_TYPE:
     case UNION_TYPE:
@@ -8371,9 +8377,9 @@ tsubst (tree t, tree args, tsubst_flags_
 	r = NULL_TREE;
 
 	gcc_assert (TREE_VEC_LENGTH (args) > 0);
-	if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-	    || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
-	    || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+	if (LANG_TREE_CODE (t) == TEMPLATE_TYPE_PARM
+	    || LANG_TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+	    || LANG_TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
 	  {
 	    idx = TEMPLATE_TYPE_IDX (t);
 	    level = TEMPLATE_TYPE_LEVEL (t);
@@ -8412,7 +8418,7 @@ tsubst (tree t, tree args, tsubst_flags_
                  };  */
 	      return t;
 
-	    if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+	    if (LANG_TREE_CODE (t) == TEMPLATE_TYPE_PARM)
 	      {
 		int quals;
 		gcc_assert (TYPE_P (arg));
@@ -8429,7 +8435,7 @@ tsubst (tree t, tree args, tsubst_flags_
 		return cp_build_qualified_type_real
 		  (arg, quals, complain | tf_ignore_bad_quals);
 	      }
-	    else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+	    else if (LANG_TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
 	      {
 		/* We are processing a type constructed from a
 		   template template parameter.  */
@@ -8443,7 +8449,7 @@ tsubst (tree t, tree args, tsubst_flags_
 		   member function templates.  Otherwise ARG is a
 		   TEMPLATE_DECL and is the real template to be
 		   instantiated.  */
-		if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+		if (LANG_TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
 		  arg = TYPE_NAME (arg);
 
 		r = lookup_template_class (arg,
@@ -8468,7 +8474,7 @@ tsubst (tree t, tree args, tsubst_flags_
 	/* If we get here, we must have been looking at a parm for a
 	   more deeply nested template.  Make a new version of this
 	   template parameter, but with a lower level.  */
-	switch (TREE_CODE (t))
+	switch (LANG_TREE_CODE (t))
 	  {
 	  case TEMPLATE_TYPE_PARM:
 	  case TEMPLATE_TEMPLATE_PARM:
@@ -8478,7 +8484,7 @@ tsubst (tree t, tree args, tsubst_flags_
 		r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
 		r = cp_build_qualified_type_real
 		  (r, cp_type_quals (t),
-		   complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+		   complain | (LANG_TREE_CODE (t) == TEMPLATE_TYPE_PARM
 			       ? tf_ignore_bad_quals : 0));
 	      }
 	    else
@@ -8492,7 +8498,7 @@ tsubst (tree t, tree args, tsubst_flags_
 		TYPE_POINTER_TO (r) = NULL_TREE;
 		TYPE_REFERENCE_TO (r) = NULL_TREE;
 
-		if (TREE_CODE (r) == TEMPLATE_TEMPLATE_PARM)
+		if (LANG_TREE_CODE (r) == TEMPLATE_TEMPLATE_PARM)
 		  /* We have reduced the level of the template
 		     template parameter, but not the levels of its
 		     template parameters, so canonical_type_parameter
@@ -8506,7 +8512,7 @@ tsubst (tree t, tree args, tsubst_flags_
 		else
 		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
 
-		if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+		if (LANG_TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
 		    tree argvec = tsubst (TYPE_TI_ARGS (t), args,
 					  complain, in_decl);
@@ -8811,7 +8817,7 @@ tsubst (tree t, tree args, tsubst_flags_
 	    f = TREE_TYPE (f);
 	  }
 
-	if (TREE_CODE (f) != TYPENAME_TYPE)
+	if (LANG_TREE_CODE (f) != TYPENAME_TYPE)
 	  {
 	    if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
 	      error ("%qT resolves to %qT, which is not an enumeration type",
@@ -9097,13 +9103,13 @@ tsubst_qualified_id (tree qualified_id, 
 static tree
 tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
-  enum tree_code code;
+  enum cplus_tree_code code;
   tree r;
 
   if (t == NULL_TREE || t == error_mark_node)
     return t;
 
-  code = TREE_CODE (t);
+  code = LANG_TREE_CODE (t);
 
   switch (code)
     {
@@ -11211,7 +11217,7 @@ type_unification_real (tree tparms,
   while (parms && parms != void_list_node
 	 && args && args != void_list_node)
     {
-      if (TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
+      if (LANG_TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
         break;
 
       parm = TREE_VALUE (parms);
@@ -11285,7 +11291,7 @@ type_unification_real (tree tparms,
 
   if (parms 
       && parms != void_list_node
-      && TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
+      && LANG_TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
     {
       /* Unify the remaining arguments with the pack expansion type.  */
       tree argvec;
@@ -11655,7 +11661,7 @@ check_cv_quals_for_unify (int strict, tr
   int arg_quals = cp_type_quals (arg);
   int parm_quals = cp_type_quals (parm);
 
-  if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+  if (LANG_TREE_CODE (parm) == TEMPLATE_TYPE_PARM
       && !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
     {
       /*  Although a CVR qualifier is ignored when being applied to a
@@ -11670,7 +11676,7 @@ check_cv_quals_for_unify (int strict, tr
 	  && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
 	return 0;
 
-      if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
+      if ((!POINTER_TYPE_P (arg) && LANG_TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
 	  && (parm_quals & TYPE_QUAL_RESTRICT))
 	return 0;
     }
@@ -11690,9 +11696,9 @@ check_cv_quals_for_unify (int strict, tr
 void 
 template_parm_level_and_index (tree parm, int* level, int* index)
 {
-  if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
-      || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (LANG_TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+      || LANG_TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+      || LANG_TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
     {
       *index = TEMPLATE_TYPE_IDX (parm);
       *level = TEMPLATE_TYPE_LEVEL (parm);
@@ -11883,7 +11889,7 @@ unify_pack_expansion (tree tparms, tree 
               TREE_CONSTANT (result) = 1;
             }
           else
-            result = make_node (TYPE_ARGUMENT_PACK);
+            result = cxx_make_type (TYPE_ARGUMENT_PACK);
 
           SET_ARGUMENT_PACK_ARGS (result, new_args);
 
@@ -11998,7 +12004,7 @@ unify (tree tparms, tree targs, tree par
 
   /* Immediately reject some pairs that won't unify because of
      cv-qualification mismatches.  */
-  if (TREE_CODE (arg) == TREE_CODE (parm)
+  if (LANG_TREE_CODE (arg) == LANG_TREE_CODE (parm)
       && TYPE_P (arg)
       /* It is the elements of the array which hold the cv quals of an array
 	 type, and the elements might be template type parms. We'll check
@@ -12008,7 +12014,7 @@ unify (tree tparms, tree targs, tree par
 	 parameters below.  We want to allow ARG `const T' to unify with
 	 PARM `T' for example, when computing which of two templates
 	 is more specialized, for example.  */
-      && TREE_CODE (arg) != TEMPLATE_TYPE_PARM
+      && LANG_TREE_CODE (arg) != TEMPLATE_TYPE_PARM
       && !check_cv_quals_for_unify (strict_in, arg, parm))
     return 1;
 
@@ -12020,7 +12026,7 @@ unify (tree tparms, tree targs, tree par
   strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
   strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
 
-  switch (TREE_CODE (parm))
+  switch (LANG_TREE_CODE (parm))
     {
     case TYPENAME_TYPE:
     case SCOPE_REF:
@@ -12039,24 +12045,24 @@ unify (tree tparms, tree targs, tree par
 	  != template_decl_level (tparm))
 	/* The PARM is not one we're trying to unify.  Just check
 	   to see if it matches ARG.  */
-	return (TREE_CODE (arg) == TREE_CODE (parm)
+	return (LANG_TREE_CODE (arg) == LANG_TREE_CODE (parm)
 		&& same_type_p (parm, arg)) ? 0 : 1;
       idx = TEMPLATE_TYPE_IDX (parm);
       targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
 
       /* Check for mixed types and values.  */
-      if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+      if ((LANG_TREE_CODE (parm) == TEMPLATE_TYPE_PARM
 	   && TREE_CODE (tparm) != TYPE_DECL)
-	  || (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+	  || (LANG_TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
 	      && TREE_CODE (tparm) != TEMPLATE_DECL))
 	return 1;
 
-      if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+      if (LANG_TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
 	{
 	  /* ARG must be constructed from a template class or a template
 	     template parameter.  */
-	  if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
+	  if (LANG_TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
 	      && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
 	    return 1;
 
@@ -12121,8 +12127,8 @@ unify (tree tparms, tree targs, tree par
 	  /* Fall through to deduce template name.  */
 	}
 
-      if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
-	  || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+      if (LANG_TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
+	  || LANG_TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
 	{
 	  /* Deduce template name TT from TT, TT<>, TT<T> and TT<i>.  */
 
@@ -12184,7 +12190,7 @@ unify (tree tparms, tree targs, tree par
 	  != template_decl_level (tparm))
 	/* The PARM is not one we're trying to unify.  Just check
 	   to see if it matches ARG.  */
-	return !(TREE_CODE (arg) == TREE_CODE (parm)
+	return !(LANG_TREE_CODE (arg) == LANG_TREE_CODE (parm)
 		 && cp_tree_equal (parm, arg));
 
       idx = TEMPLATE_PARM_IDX (parm);
@@ -12356,7 +12362,7 @@ unify (tree tparms, tree targs, tree par
     case BOOLEAN_TYPE:
     case ENUMERAL_TYPE:
     case VOID_TYPE:
-      if (TREE_CODE (arg) != TREE_CODE (parm))
+      if (LANG_TREE_CODE (arg) != LANG_TREE_CODE (parm))
 	return 1;
 
       /* We have already checked cv-qualification at the top of the
@@ -12739,8 +12745,8 @@ more_specialized_fn (tree pat1, tree pat
       int quals1 = -1;
       int quals2 = -1;
 
-      if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION
-          && TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
+      if (LANG_TREE_CODE (arg1) == TYPE_PACK_EXPANSION
+          && LANG_TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
         {
           /* When both arguments are pack expansions, we need only
              unify the patterns themselves.  */
@@ -12806,7 +12812,7 @@ more_specialized_fn (tree pat1, tree pat
       arg1 = TYPE_MAIN_VARIANT (arg1);
       arg2 = TYPE_MAIN_VARIANT (arg2);
 
-      if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
+      if (LANG_TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
         {
           int i, len2 = len + 1;
           tree parmvec = make_tree_vec (1);
@@ -12830,7 +12836,7 @@ more_specialized_fn (tree pat1, tree pat
              a pack expansion but ARG2 is not.  */
           deduce2 = 0;
         }
-      else if (TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
+      else if (LANG_TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
         {
           int i, len1 = len + 1;
           tree parmvec = make_tree_vec (1);
@@ -12886,8 +12892,8 @@ more_specialized_fn (tree pat1, tree pat
       if (deduce2 && !deduce1 && !better1)
 	better1 = 1;
 
-      if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION
-          || TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
+      if (LANG_TREE_CODE (arg1) == TYPE_PACK_EXPANSION
+          || LANG_TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
         /* We have already processed all of the arguments in our
            handing of the pack expansion type.  */
         len = 0;
@@ -12905,9 +12911,10 @@ more_specialized_fn (tree pat1, tree pat
       && args1 && TREE_VALUE (args1)
       && args2 && TREE_VALUE (args2))
     {
-      if (TREE_CODE (TREE_VALUE (args1)) == TYPE_PACK_EXPANSION)
-        return TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION ? 0 : -1;
-      else if (TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION)
+      if (LANG_TREE_CODE (TREE_VALUE (args1)) == TYPE_PACK_EXPANSION)
+        return LANG_TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION 
+	       ? 0 : -1;
+      else if (LANG_TREE_CODE (TREE_VALUE (args2)) == TYPE_PACK_EXPANSION)
         return 1;
     }
 
@@ -14125,7 +14132,7 @@ instantiate_decl (tree d, int defer_ok,
           tree parmvec;
           tree parmtypevec;
           tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
-          tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
+          tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
           int i, len = 0;
           tree t;
           
@@ -14307,7 +14314,7 @@ tsubst_initializer_list (tree t, tree ar
       tree expanded_arguments = NULL_TREE;
       int i, len = 1;
 
-      if (TREE_CODE (TREE_PURPOSE (t)) == TYPE_PACK_EXPANSION)
+      if (LANG_TREE_CODE (TREE_PURPOSE (t)) == TYPE_PACK_EXPANSION)
         {
           tree expr;
           tree arg;
@@ -14547,9 +14554,9 @@ invalid_nontype_parm_type_p (tree type, 
     return 0;
   else if (TYPE_PTR_TO_MEMBER_P (type))
     return 0;
-  else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+  else if (LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM)
     return 0;
-  else if (TREE_CODE (type) == TYPENAME_TYPE)
+  else if (LANG_TREE_CODE (type) == TYPENAME_TYPE)
     return 0;
 
   if (complain & tf_error)
@@ -14572,13 +14579,13 @@ dependent_type_p_r (tree type)
      -- a template parameter. Template template parameters are types
 	for us (since TYPE_P holds true for them) so we handle
 	them here.  */
-  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+  if (LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM
+      || LANG_TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
     return true;
   /* -- a qualified-id with a nested-name-specifier which contains a
 	class-name that names a dependent type or whose unqualified-id
 	names a dependent type.  */
-  if (TREE_CODE (type) == TYPENAME_TYPE)
+  if (LANG_TREE_CODE (type) == TYPENAME_TYPE)
     return true;
   /* -- a cv-qualified type where the cv-unqualified type is
 	dependent.  */
@@ -14621,7 +14628,7 @@ dependent_type_p_r (tree type)
 
   /* -- a template-id in which either the template name is a template
      parameter ...  */
-  if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (LANG_TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
     return true;
   /* ... or any of the template arguments is a dependent type or
 	an expression that is type-dependent or value-dependent.  */
@@ -14633,12 +14640,12 @@ 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 (LANG_TREE_CODE (type) == TYPEOF_TYPE)
     return true;
 
   /* A template argument pack is dependent if any of its packed
      arguments are.  */
-  if (TREE_CODE (type) == TYPE_ARGUMENT_PACK)
+  if (LANG_TREE_CODE (type) == TYPE_ARGUMENT_PACK)
     {
       tree args = ARGUMENT_PACK_ARGS (type);
       int i, len = TREE_VEC_LENGTH (args);
@@ -14649,7 +14656,7 @@ dependent_type_p_r (tree type)
 
   /* All TYPE_PACK_EXPANSIONs are dependent, because parameter packs must
      be template parameters.  */
-  if (TREE_CODE (type) == TYPE_PACK_EXPANSION)
+  if (LANG_TREE_CODE (type) == TYPE_PACK_EXPANSION)
     return true;
 
   /* The standard does not specifically mention types that are local
@@ -14686,7 +14693,7 @@ dependent_type_p (tree type)
       /* If we are not processing a template, then nobody should be
 	 providing us with a dependent type.  */
       gcc_assert (type);
-      gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM);
+      gcc_assert (LANG_TREE_CODE (type) != TEMPLATE_TYPE_PARM);
       return false;
     }
 
@@ -15041,7 +15048,7 @@ dependent_template_arg_p (tree arg)
     return false;
 
   if (TREE_CODE (arg) == TEMPLATE_DECL
-      || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+      || LANG_TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
     return dependent_template_p (arg);
   else if (ARGUMENT_PACK_P (arg))
     {
@@ -15100,7 +15107,7 @@ any_template_arguments_need_structural_e
 	      if (error_operand_p (arg))
 		return true;
 	      else if (TREE_CODE (arg) == TEMPLATE_DECL
-		       || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+		       || LANG_TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
 		continue;
 	      else if (TYPE_P (arg) && TYPE_STRUCTURAL_EQUALITY_P (arg))
 		return true;
@@ -15157,7 +15164,7 @@ dependent_template_p (tree tmpl)
 
   /* Template template parameters are dependent.  */
   if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
-      || TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
+      || LANG_TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
     return true;
   /* So are names that have not been looked up.  */
   if (TREE_CODE (tmpl) == SCOPE_REF
@@ -15194,22 +15201,22 @@ resolve_typename_type (tree type, bool o
   int quals;
   tree pushed_scope;
 
-  gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
+  gcc_assert (LANG_TREE_CODE (type) == TYPENAME_TYPE);
 
   scope = TYPE_CONTEXT (type);
   name = TYPE_IDENTIFIER (type);
 
   /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
      it first before we can figure out what NAME refers to.  */
-  if (TREE_CODE (scope) == TYPENAME_TYPE)
+  if (LANG_TREE_CODE (scope) == TYPENAME_TYPE)
     scope = resolve_typename_type (scope, only_current_p);
   /* If we don't know what SCOPE refers to, then we cannot resolve the
      TYPENAME_TYPE.  */
-  if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
+  if (scope == error_mark_node || LANG_TREE_CODE (scope) == TYPENAME_TYPE)
     return error_mark_node;
   /* If the SCOPE is a template type parameter, we have no way of
      resolving the name.  */
-  if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
+  if (LANG_TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
     return type;
   /* If the SCOPE is not the current instantiation, there's no reason
      to look inside it.  */
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 123123)
+++ cp/semantics.c	(working copy)
@@ -1385,7 +1385,7 @@ finish_mem_initializers (tree mem_in
              any parameter packs in the TREE_VALUE have already been
              bound as part of the TREE_PURPOSE.  See
              make_pack_expansion for more information.  */
-          if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
+          if (LANG_TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
             check_for_bare_parameter_packs (TREE_VALUE (mem));
         }
 
@@ -2166,8 +2166,8 @@ tree
 check_template_template_default_arg (tree argument)
 {
   if (TREE_CODE (argument) != TEMPLATE_DECL
-      && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
-      && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+      && LANG_TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
+      && LANG_TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
     {
       if (TREE_CODE (argument) == TYPE_DECL)
 	error ("invalid use of type %qT as a default value for a template "
@@ -2199,7 +2199,7 @@ begin_class_definition (tree t, tree att
 	 template <typename U> struct A<T>::B ...
 
      This is erroneous.  */
-  else if (TREE_CODE (t) == TYPENAME_TYPE)
+  else if (LANG_TREE_CODE (t) == TYPENAME_TYPE)
     {
       error ("invalid definition of qualified type %qT", t);
       t = error_mark_node;
@@ -2959,7 +2959,7 @@ finish_offsetof (tree expr)
     }
   if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
-      || TREE_CODE (TREE_TYPE (expr)) == UNKNOWN_TYPE)
+      ||  || LANG_TREE_CODE (TREE_TYPE (expr)) == UNKNOWN_TYPE)
     {
       if (TREE_CODE (expr) == COMPONENT_REF
 	  || TREE_CODE (expr) == COMPOUND_EXPR)
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 123123)
+++ cp/name-lookup.c	(working copy)
@@ -846,7 +846,7 @@ pushdecl_maybe_friend (tree x, bool is_f
 	  if (decl && decl != error_mark_node
 	      && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
 	      /* If different sort of thing, we already gave an error.  */
-	      && TREE_CODE (decl) == TREE_CODE (x)
+	      && LANG_TREE_CODE (decl) == LANG_TREE_CODE (x)
 	      && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
 	    {
 	      pedwarn ("type mismatch with previous external decl of %q#D", x);
@@ -1070,7 +1070,7 @@ maybe_push_decl (tree decl)
 	     possible.  */
 	  && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
       || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
-      || TREE_CODE (type) == UNKNOWN_TYPE
+      || LANG_TREE_CODE (type) == UNKNOWN_TYPE
       /* The declaration of a template specialization does not affect
 	 the functions available for overload resolution, so we do not
 	 call pushdecl.  */
@@ -4416,8 +4416,8 @@ arg_assoc_template_arg (struct arg_looku
      contribute to the set of associated namespaces.  ]  */
 
   /* Consider first template template arguments.  */
-  if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
   || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
+  if (LANG_TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+      || LANG_TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
     return false;
   else if (TREE_CODE (arg) == TEMPLATE_DECL)
     {
@@ -4524,7 +4524,7 @@ arg_assoc_type (struct arg_lookup *k, tr
 	return true;
       return arg_assoc_type (k, TYPE_PTRMEM_POINTED_TO_TYPE (type));
     }
-  else switch (TREE_CODE (type))
+  else switch (LANG_TREE_CODE (type))
     {
     case ERROR_MARK:
       return false;
Index: cp/lex.c
===================================================================
--- cp/lex.c	(revision 123123)
+++ cp/lex.c	(working copy)
@@ -342,6 +342,36 @@ init_cp_pragma (void)
   c_register_pragma ("GCC", "java_exceptions", handle_pragma_java_exceptions);
 }
 
+
+/* Predefined TYPE_LANG_SPECIFIC values. */
+static GTY(()) struct lang_type *lang_type_headers[CPLUS_TYPE_SUBCODES];
+
+/* Initialize C++-specific tree nodes.  */
+static void
+init_cxx_tree (void)
+{
+  int i;
+
+  /* Initialize the predefined TYPE_LANG_SPECIFIC values for all
+     subcoded types.  */
+  for (i = 0; i < CPLUS_TYPE_SUBCODES; ++i)
+    {
+      if (CPLUS_FIRST_TYPE_SUBCODE + i + 1 == BOUND_TEMPLATE_TEMPLATE_PARM)
+	/* BOUND_TEMPLATE_TEMPLATE_PARM is special because it has a
+	   full lang_type_class in its TYPE_LANG_SPECIFIC.  So, don't
+	   preallocate a lang_type header for it.  */
+	lang_type_headers[i] = NULL;
+      else
+	{
+	  lang_type_ype_ers[i] 
+	    = GGC_NEWVAR (struct lang_type, sizeof(struct lang_type_header));
+	  memset (lang_type_headers[i], 0, sizeof (struct lang_type_header));
+
+	  lang_type_headers[i]->u.h.subcode = CPLUS_FIRST_TYPE_SUBCODE + i + 1;
+	}	
+    }
+}
+
 /* TRUE if a code represents a statement.  */
 
 bool statement_code_p[MAX_TREE_CODES];
@@ -377,6 +407,7 @@ cxx_init (void)
 
   init_reswords ();
   init_tree ();
+  init_cxx_tree ();
   init_cp_semantics ();
   init_operators ();
   init_method ();
@@ -763,7 +794,17 @@ copy_lang_type (tree node)
   if (! TYPE_LANG_SPECIFIC (node))
     return;
 
-  if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
+  if (TREE_CODE (node) == LANG_TYPE
+      && LANG_TREE_CODE (node) != BOUND_TEMPLATE_TEMPLATE_PARM)
+    {
+      /* These nodes have fixed pointers in TYPE_LANG_SPECIFIC, so
+	 there is no reason to copy them.  */
+#ifdef GATHER_STATISTICS
+      tree_node_counts[(int)lang_type] += 1;
+#endif
+      return;
+    }
+  else if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
     size = sizeof (struct lang_type);
   else
     size = sizeof (struct lang_type_ptrmem);
@@ -792,7 +833,24 @@ copy_type (tree type)
 tree
 cxx_make_type (enum tree_code code)
 {
-  tree t = make_node (code);
+  tree t;
+
+  if (code < MAX_TREE_CODES)
+    t = make_node (code);
+  else
+    {
+      t = make_node (LANG_TYPE);
+
+      if (code != BOUND_TEMPLATE_TEMPLATE_PARM)
+	{
+	  TYPE_LANG_SPECIFIC (t) 
+	        = lang_type_headers[code - CPLUS_FIRST_TYPE_SUBCODE - 1];
+#ifdef GATHER_STATISTICS
+	  tree_node_counts[(int)lang_type] += 1;
+#endif
+	  return t;
+	}
+    }
 
   /* Create lang_type structure.  */
   if (IS_AGGR_TYPE_CODE (code)
@@ -803,6 +861,9 @@ cxx_make_type (enum tree_code code)
       TYPE_LANG_SPECIFIC (t) = pi;
       pi->u.c.h.is_lang_type_class = 1;
 
+      if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
+	pi->u.c.h.subcode = code - MAX_TREE_CODES;
+
 #ifdef GATHER_STATISTICS
       tree_node_counts[(int)lang_type] += 1;
       tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
@@ -830,3 +891,5 @@ make_aggr_type (enum tree_code code)
 
   return t;
 }
+
+#include "gt-cp-lex.h"
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 123123)
+++ cp/decl2.c	(working copy)
@@ -139,7 +139,7 @@ cp_build_parm_decl (tree name, tree type
 
   /* If the type is a pack expansion, then we have a function
      parameter pack. */
-  if (type && TREE_CODE (type) == TYPE_PACK_EXPANSION)
+  if (type && LANG_TREE_CODE (type) == TYPE_PACK_EXPANSION)
     FUNCTION_PARAMETER_PACK_P (parm) = 1;
 
   return parm;
@@ -812,8 +812,8 @@ grokfield (const cp_declarator *declarat
 	  /* Avoid storing attributes in template parameters:
 	     tsubst is not ready to handle them.  */
 	  tree type = TREE_TYPE (value);
-	  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
-	      || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+	  if (LANG_TREE_CODE (type) == TEMPLATE_TYPE_PARM
+	      || LANG_TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
 	    sorry ("applying attributes to template parameters is not implemented");
 	  else
 	    cplus_decl_attributes (&value, attrlist, 0);
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 123123)
+++ cp/parser.c	(working copy)
@@ -3800,7 +3800,7 @@ cp_parser_nested_name_specifier_opt (cp_
 	     with IS_DECLARATION set to false, we will not have
 	     resolved TYPENAME_TYPEs, so we must do so here.  */
 	  if (is_declaration
-	      && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+	      && LANG_TREE_CODE (parser->scope) == TYPENAME_TYPE)
 	    {
 	      new_scope = resolve_typename_type (parser->scope,
 						 /*only_current_p=*/false);
@@ -3857,7 +3857,7 @@ cp_parser_nested_name_specifier_opt (cp_
       if (is_declaration
 	  && !typename_keyword_p
 	  && parser->scope
-	  && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+	  && LANG_TREE_CODE (parser->scope) == TYPENAME_TYPE)
 	parser->scope = resolve_typename_type (parser->scope,
 					       /*only_current_p=*/false);
       /* Parse the qualifying entity.  */
@@ -3948,7 +3948,7 @@ cp_parser_nested_name_specifier_opt (cp_
 	       && ((CLASSTYPE_USE_TEMPLATE (new_scope)
 		    && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (new_scope)))
 		   || CLASSTYPE_IS_TEMPLATE (new_scope)))
-	  && !(TREE_CODE (new_scope) == TYPENAME_TYPE
+	  && !(LANG_TREE_CODE (new_scope) == TYPENAME_TYPE
 	       && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
 		   == TEMPLATE_ID_EXPR)))
 	pedwarn (TYPE_P (new_scope)
@@ -9676,7 +9676,7 @@ cp_parser_template_argument (cp_parser* 
 					  /*check_dependency=*/true,
 					  /*ambiguous_decls=*/NULL);
       if (TREE_CODE (argument) != TEMPLATE_DECL
-	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+	  && LANG_TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
 	cp_parser_error (parser, "expected template-name");
     }
   if (cp_parser_parse_definitely (parser))
@@ -10641,7 +10641,7 @@ cp_parser_elaborated_type_specifier (cp_
 	      return error_mark_node;
 	    }
 
-	  if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
+	  if (LANG_TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
             {
               bool allow_template = (parser->num_template_parameter_lists
 		                      || DECL_SELF_REFERENCE_P (decl));
@@ -10732,7 +10732,7 @@ cp_parser_elaborated_type_specifier (cp_
   /* Allow attributes on forward declarations of classes.  */
   if (attributes)
     {
-      if (TREE_CODE (type) == TYPENAME_TYPE)
+      if (LANG_TREE_CODE (type) == TYPENAME_TYPE)
 	warning (OPT_Wattributes,
 		 "attributes ignored on uninstantiated type");
       else if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
@@ -12151,7 +12151,7 @@ cp_parser_direct_declarator (cp_parser* 
 	    }
 
 	  if (qualifying_scope && at_namespace_scope_p ()
-	      && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
+	      && LANG_TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
 	    {
 	      /* In the declaration of a member of a template class
 		 outside of the class itself, the SCOPE will sometimes
@@ -12933,7 +12933,7 @@ cp_parser_parameter_declaration (cp_pars
       if (DECL_P (type))
         type = TREE_TYPE (type);
 
-      if (TREE_CODE (type) != TYPE_PACK_EXPANSION
+      if (LANG_TREE_CODE (type) != TYPE_PACK_EXPANSION
           && (!declarator || !declarator->parameter_pack_p)
           && uses_parameter_packs (type))
         {
@@ -13971,7 +13971,7 @@ cp_parser_class_head (cp_parser* parser,
 	 we will get a TYPENAME_TYPE when processing the definition of
 	 `S::T'.  We need to resolve it to the actual type before we
 	 try to define it.  */
-      if (TREE_CODE (TREE_TYPE (type)) == TYPENAME_TYPE)
+      if (LANG_TREE_CODE (TREE_TYPE (type)) == TYPENAME_TYPE)
 	{
 	  class_type = resolve_typename_type (TREE_TYPE (type),
 					      /*only_current_p=*/false);
@@ -15651,7 +15651,7 @@ cp_parser_lookup_name (cp_parser *parser
   gcc_assert (DECL_P (decl)
 	      || TREE_CODE (decl) == OVERLOAD
 	      || TREE_CODE (decl) == SCOPE_REF
-	      || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE
+	      || LANG_TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE
 	      || BASELINK_P (decl));
 
   /* If we have resolved the name of a member declaration, check to
@@ -15976,7 +15976,7 @@ cp_parser_constructor_declarator_p (cp_p
 	  else
 	    {
 	      type = TREE_TYPE (type_decl);
-	      if (TREE_CODE (type) == TYPENAME_TYPE)
+	      if (LANG_TREE_CODE (type) == TYPENAME_TYPE)
 		{
 		  type = resolve_typename_type (type,
 						/*only_current_p=*/false);
Index: c-lang.c
===================================================================
--- c-lang.c	(revision 123123)
+++ c-lang.c	(working copy)
@@ -52,7 +52,7 @@ const struct lang_hooks lang_hooks = LAN
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
 
-const enum tree_code_class tree_code_type[] = {
+enum tree_code_class tree_code_type[] = {
 #include "tree.def"
   tcc_exceptional,
 #include "c-common.def"
@@ -65,7 +65,7 @@ const enum tree_code_class tree_code_typ
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
 
-const unsigned char tree_code_length[] = {
+unsigned char tree_code_length[] = {
 #include "tree.def"
   0,
 #include "c-common.def"
@@ -76,7 +76,7 @@ const unsigned char tree_code_length[] =
    Used for printing out the tree and error messages.  */
 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
 
-const char *const tree_code_name[] = {
+const char * tree_code_name[] = {
 #include "tree.def"
   "@@dummy",
 #include "c-common.def"

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