cp-dmp-tree.c   [plain text]


/* APPLE LOCAL file new tree dump */
/* Common condensed c++ tree display routines. Based on dmp-tree.c
   Copyright (C) 2001  Free Software Foundation, Inc.
   Contributed by Devang Patel (dpatel@apple.com)
   and Ira L. Ruben (ira@apple.com)

This file is part of GNU CC.

GNU CC 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.

GNU CC 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 GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* Both C and C++ node handling is required for C++.  The C handling is
   done in c-dmp-tree.c.  But that is a C language specific file, i.e.,
   only built for C.  Thus we need to #include it here to get the stuff
   we need defined.  But we need to tell c-dmp-tree.c that we are doing
   this so it doesn't define stuff we don't want defined.  That's the
   purpose of the CP_DMP_TREE switch.  
   
   Note that c-dmp-tree.c does all the main #includes so we don't need
   them here.  */
   
#define CP_DMP_TREE
#include "c-dmp-tree.c"

#ifdef ENABLE_DMP_TREE

#include "cp-tree.h"

int cp_dump_tree_p (FILE *, const char *, tree, int);
lang_dump_tree_p_t cp_prev_lang_dump_tree_p = NULL;

#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) \
static void print_ ## SYM (FILE *file, const char *annotation, tree node, int indent);
#include "cp-tree.def"
#undef DEFTREECODE

static void print_SRCLOC (FILE *, const char *, tree, int);
static void print_RECORD_TYPE (FILE *, const char *, tree, int);
static void print_NAMESPACE_DECL (FILE *, const char *, tree, int);
static void print_ADDR_EXPR (FILE *, const char *, tree, int);

/*-------------------------------------------------------------------*/

/* Called twice for dmp-tree() for an IDENTIFIER_NODE.  The first call
   is after the common info for the node is generated but before
   displaying the identifer (before_id==0) which is always assumed
   to be the last thing on the line.
   
   The second call is done after the id is displayed (before_id!=0).
   This is for displaying any language-specific node information that
   should be preceded by an newline_and_indent() call or a recursive
   call to dump_tree() for nodes which are language specific operands
   to a IDENTIFIER_NODE.  */
  
void 
cxx_dump_identifier (FILE *file,
		      tree node,
		      int indent ATTRIBUTE_UNUSED,
		      int after_id)
{
  if (!after_id)
    {
      if (C_IS_RESERVED_WORD (node))
        fputs (" reserved", file);
      if (IDENTIFIER_CTOR_OR_DTOR_P (node))
        fputs (" ctor/dtor", file);
      if (IDENTIFIER_NAMESPACE_BINDINGS (node))
	{
	  fprintf (file, " ns-bindings=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_NAMESPACE_BINDINGS (node));
	}
      if (IDENTIFIER_CLASS_VALUE (node))
	{
	  fprintf (file, " binding=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_CLASS_VALUE (node));
	}
      if (IDENTIFIER_BINDING (node))
	{
	  fprintf (file, " lcl-bindings=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_BINDING (node));
	}
      if (IDENTIFIER_LABEL_VALUE (node))
	{
	  fprintf (file, " gbl=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_LABEL_VALUE (node));
	}
      if (IDENTIFIER_TEMPLATE (node))
	{
	  fprintf (file, " tmpl=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_TEMPLATE (node));
	}
      if (IDENTIFIER_IMPLICIT_DECL (node))
	{
	  fprintf (file, " impl=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_IMPLICIT_DECL (node));
	}
      if (IDENTIFIER_ERROR_LOCUS (node))
	{
	  fprintf (file, " err-locus=");
	  fprintf (file, HOST_PTR_PRINTF, IDENTIFIER_ERROR_LOCUS (node));
	}
    }
  else
    {
#if 0
      dump_binding (file, "(bindings)", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + INDENT);
#endif
      dump_tree (file, "(class)", IDENTIFIER_CLASS_VALUE (node), indent + INDENT);
#if 0
      dump_binding (file, "(lcl-bindings)", IDENTIFIER_BINDING (node), indent + INDENT);
#endif
      dump_tree (file, "(lbl)", IDENTIFIER_LABEL_VALUE (node), indent + INDENT);
      dump_tree (file, "(tmpl)", IDENTIFIER_TEMPLATE (node), indent + INDENT);
      dump_tree (file, "(impl)", IDENTIFIER_IMPLICIT_DECL (node), indent + INDENT);
      dump_tree (file, "(err-locus)", IDENTIFIER_ERROR_LOCUS (node), indent + INDENT);
    }
}

/* Called twice for dmp_tree() for a ..._DECL node.  The first call
   after the common info for the node is generated but before
   displaying the identifier (before_id==0) which is always assumed
   to be the last thing on the line.
   
   The second call is done after the id is displayed (before_id!=0).
   This is for displaying any language-specific node information that
   should be preceded by an newline_and_indent() call or a recursive
   call to dump_tree() for nodes which are language specific operands
   to a ..._DECL node.  */
    
void 
cxx_dump_decl (FILE *file, tree node, int indent ATTRIBUTE_UNUSED, int after_id)
{
  switch (TREE_CODE (node))
  {
    case FUNCTION_DECL:
      if (!after_id)
        {
	  if (DECL_STATIC_FUNCTION_P (node))
	    fputs (" static", file);
	  if (DECL_FRIEND_P (node))
	    fputs (" frnd", file);
	  if (DECL_CONSTRUCTOR_P (node))
	      fprintf (file, " %sctor", 
	      		DECL_COPY_CONSTRUCTOR_P (node) ? "cpy-" : "");
	  if (DECL_DESTRUCTOR_P (node))
	    fputs (" dtor", file);
	  if (DECL_PURE_VIRTUAL_P (node))
	    fputs (" pure-virt", file);
	  if (DECL_CONST_MEMFUNC_P (node))
	    fputs (" const", file);
	  if (DECL_VOLATILE_MEMFUNC_P (node))
	    fputs (" volatile", file);
	  if (DECL_MUTABLE_P (node))
	    fputs (" mutable", file);
	  if (DECL_THUNK_P (node))
	    fputs (" thnk", file);
	  if (DECL_LANG_SPECIFIC (node))
	    {
	      if (DECL_PENDING_INLINE_INFO (node))
		{
	          fprintf (file, " pending-inline-info=");
		  fprintf (file, HOST_PTR_PRINTF,
	        	   HOST_PTR_PRINTF_VALUE (DECL_PENDING_INLINE_INFO (node)));
		}
	      if (DECL_TEMPLATE_INFO (node))
		{
	          fprintf (file, " tmpl-info=");
		  fprintf (file, HOST_PTR_PRINTF,
	        	   HOST_PTR_PRINTF_VALUE (DECL_TEMPLATE_INFO (node)));
		}
	    }
        }
      break;
    
    case FIELD_DECL:
      if (!after_id)
        {
          if (DECL_MUTABLE_P (node))
	    fputs (" mutable", file);
        }
      break;
    
    case TYPE_DECL:
      if (!after_id)
        {
	  if (DECL_LANG_SPECIFIC (node))
	    {
	      if (DECL_TEMPLATE_INFO (node))
		{
	          fprintf (file, " tmpl-info=");
		  fprintf (file, HOST_PTR_PRINTF,
	        	   HOST_PTR_PRINTF_VALUE (DECL_TEMPLATE_INFO (node)));
		}
	      if (DECL_SORTED_FIELDS (node))
		{
	          fprintf (file, " sorted-fields=");
		  fprintf (file, HOST_PTR_PRINTF,
	        	   HOST_PTR_PRINTF_VALUE (DECL_SORTED_FIELDS (node)));
		}
	    }
        }
       break;
   
    case VAR_DECL:
      if (!after_id)
        {
	  if (DECL_LANG_SPECIFIC (node))
	    {
	      if (DECL_TEMPLATE_INFO (node))
		{
	          fprintf (file, " tmpl-info=");
		  fprintf (file, HOST_PTR_PRINTF,
	        	   HOST_PTR_PRINTF_VALUE (DECL_TEMPLATE_INFO (node)));
		}
	    }
	  if (DECL_SHADOWED_FOR_VAR (node))
	    fputs (" shadowed", file);
        }
       break;
    
    default:
      break;
  }
}

/* Called twice for dmp_tree() for a ..._TYPE node.  The first call
   after the common info for the node is generated but before
   displaying the identifier (before_id==0) which is always assumed
   to be the last thing on the line.
   
   The second call is done after the id is displayed (before_id!=0).
   This is for displaying any language-specific node information that
   should be preceded by an newline_and_indent() call or a recursive
   call to dump_tree() for nodes which are language specific operands
   to a ..._TYPE node.  */

void 
cxx_dump_type (FILE *file, tree node, int indent, int after_id)
{
  if (!after_id)
    {
      if (CLASS_TYPE_P (node))	/* RECORD_TYPE, UNION_TYPE only */
        {
	  if (TYPE_NEEDS_CONSTRUCTING (node))
	    fputs (" needs-ctor", file);
	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
	    fputs (" needs-dtor", file);
	  if (TYPE_HAS_DESTRUCTOR (node))
	    fputs (" ~X()", file);
	  if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node))
	    fputs (" X()", file);
	  if (TYPE_HAS_CONVERSION (node))
	    fputs (" has-conv", file);
	  if (TYPE_HAS_INIT_REF (node))
	    {
	      if (TYPE_HAS_CONST_INIT_REF (node))
		fputs (" X(constX&)", file);
	      else
		fputs (" X(X&)", file);
	    }
	  if (TYPE_HAS_NEW_OPERATOR (node))
	    fputs (" new", file);
	  if (TYPE_HAS_ARRAY_NEW_OPERATOR (node))
	    fputs (" new[]", file);
	  if (TYPE_GETS_DELETE (node) & 1)
	    fputs (" delete", file);
	  if (TYPE_GETS_DELETE (node) & 2)
	    fputs (" delete[]", file);
	  if (TYPE_HAS_ASSIGN_REF (node))
	    fputs (" this=(X&)", file);
	  if (TYPE_OVERLOADS_CALL_EXPR (node))
	    fputs (" op()", file);
	  if (TYPE_OVERLOADS_ARRAY_REF (node))
	    fputs (" op[]", file);
	  if (TYPE_OVERLOADS_ARROW (node))
	    fputs (" op->", file);
	  if (TYPE_USES_MULTIPLE_INHERITANCE (node))
	    fputs (" uses-mult-inh", file);
        }
    }
    
  switch (TREE_CODE (node))
    {
    case FUNCTION_TYPE:
    case METHOD_TYPE:
      if (!after_id)
        {
          if (TYPE_RAISES_EXCEPTIONS (node))
	    {
              fprintf (file, " throws=");
	      fprintf (file, HOST_PTR_PRINTF,
            	HOST_PTR_PRINTF_VALUE (TYPE_RAISES_EXCEPTIONS (node)));
	    }
        }
      else
        {
          if (TYPE_RAISES_EXCEPTIONS (node))
	    dump_tree (file, "(throws)", TYPE_RAISES_EXCEPTIONS (node),
	    		indent + INDENT);
        }
      break;
          
    default:
      break;
    }
}

/* Normally a blank line is inserted before each statement node (a 
   statement node is determined by calling statement_code_p()).  This
   makes the display easier to read by keeping each statement grouped
   like a paragraph.  There may, however, be some kinds of statements
   where a blank line isn't desired (e.g., a begin SCOPE_STMT in C).
   Thus dump_lang_blank_line() is called to ask if a particular 
   statement should be preceded by a blank line dependent upon the
   node that preceded it.
   
   dump_lang_blank_line_p() is called for each statement passing the
   previous node (not necessarily a statement) and current node (a
   statement node by definition).  It should return 1 if a blank
   line is to be inserted and 0 otherwise.  */

int 
cxx_dump_blank_line_p (tree previous_node ATTRIBUTE_UNUSED,
		       tree current_node ATTRIBUTE_UNUSED)
{
  return 1;
}

/* This is called for each node to display file and/or line number
   information for those nodes that have such information.  If it
   is displayed the function should return 1.  If not, 0.
   
   The function generally does not have to handle ..._DECL nodes
   unless there some special handling is reequired.  They are
   handled by print_lineno() (dump_lang_lineno_p()'s caller).
   It is defined to not repeat the filename if it does not
   change from what's in dump_tree_state.curr_file and then
   it only displays the basename (using lbasename()).  The
   format of the display is " line=nbr(basename)" where the
   leading space is included as usual in these displays and
   the parenthesized basename omitted if not needed or is
   the same as before.  */
   
int 
cxx_dump_lineno_p (FILE *file, tree node)
{
  if (statement_code_p (TREE_CODE (node)) && STMT_LINENO (node))
    {
      if (STMT_LINENO_FOR_FN_P (node))
	fprintf (file, " end-line=%d", STMT_LINENO (node));
      else
	fprintf (file, " line=%d", STMT_LINENO (node));
      return 1;
    }
  
  return 0;
}

/* Called only by tree-dump.c when doing a full compilation tree dump
   under one of the -fdmp-xxxx options.  This makes tree_dump.c, which
   is common to all languages, independent of dmp_tree, which currently
   only supports the c languages.  */
int 
cxx_dmp_tree3 (file, node, flags)
     FILE *file;
     tree node;
     int flags;
{
  dmp_tree3 (file, node, flags);
  return 1;
}

/*-------------------------------------------------------------------*/

static void
print_OFFSET_REF (FILE *file, const char *annotation, tree node, int indent)
{
  if (PTRMEM_OK_P (node))
    fputs (" ptr-to-mbr-ok", file);
  print_ref (file, annotation, node, indent);
  
  print_operands (file, node, indent, TRUE, "(obj)", "(offset)", NULL);
}

static void
print_PTRMEM_CST (FILE *file,
		  const char *annotation ATTRIBUTE_UNUSED,
		  tree node,
		  int indent ATTRIBUTE_UNUSED)
{
  fprintf (file, " rec-type::mbr-decl=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (PTRMEM_CST_CLASS (node)));
  fprintf (file, "::");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (PTRMEM_CST_MEMBER (node)));
  /* not sure I want to follow these nodes here */
}

static void
print_NEW_EXPR (FILE *file,
		const char *annotation ATTRIBUTE_UNUSED,
		tree node,
		int indent)
{
  if (NEW_EXPR_USE_GLOBAL (node))
    fputs ("use-glbl", file);
    
  print_operands (file, node, indent, TRUE, "(placement)", "(new)", "(init)", NULL);
}

static void
print_VEC_NEW_EXPR (FILE *file,
		    const char *annotation ATTRIBUTE_UNUSED,
		    tree node,
		    int indent)
{
  print_operands (file, node, indent, TRUE, "(placement)", "(new)", "(init)", NULL);
}

static void
print_DELETE_EXPR (FILE *file,
		   const char *annotation ATTRIBUTE_UNUSED,
		   tree node,
		   int indent)
{
  if (DELETE_EXPR_USE_GLOBAL (node))
    fputs ("use-glbl", file);
  if (DELETE_EXPR_USE_VEC (node))
    fputs ("use-vec", file);
    
  print_operands (file, node, indent, TRUE, "(store)", "(how)", NULL);
}

static void
print_VEC_DELETE_EXPR (FILE *file,
		       const char *annotation ATTRIBUTE_UNUSED,
		       tree node,
		       int indent)
{
  print_operands (file, node, indent, TRUE, "(store)", "(how)", NULL);
}

static void
print_SCOPE_REF (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  print_ref (file, annotation, node, indent);
  fprintf (file, " complexity=%d", TREE_COMPLEXITY (node));
  
  print_operands (file, node, indent, TRUE, "(class)", "(field)", NULL);
}

static void
print_MEMBER_REF (FILE *file,
		  const char *annotation ATTRIBUTE_UNUSED,
		  tree node,
		  int indent)
{
  print_ref (file, annotation, node, indent);
  
  print_operands (file, node, indent, FALSE, "(obj)", "(mbr)", NULL);
  /* not sure I want to follow these nodes here */
}

static void
print_TYPE_EXPR (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  fprintf (file, " type=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TREE_TYPE (node)));
  
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_AGGR_INIT_EXPR (FILE *file,
		      const char *annotation ATTRIBUTE_UNUSED,
		      tree node,
		      int indent)
{
  if (AGGR_INIT_VIA_CTOR_P(node))
    fputs (" ctor", file);
    
  print_operands (file, node, indent, TRUE, "(init-funct)", "(args)", "(slot)", NULL);
}

static void
print_THROW_EXPR (FILE *file,
		  const char *annotation ATTRIBUTE_UNUSED,
		  tree node,
		  int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EMPTY_CLASS_EXPR (FILE *file, 
                        const char *annotation ATTRIBUTE_UNUSED, 
			tree node, 
			int indent ATTRIBUTE_UNUSED)
{
  if (TREE_TYPE (node))
    {
      fprintf (file, "class=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (TREE_TYPE (node)));
    }
}

static void
print_BASELINK (FILE *file,
		const char *annotation ATTRIBUTE_UNUSED,
		tree node,
		int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TEMPLATE_DECL (FILE *file,
		     const char *annotation ATTRIBUTE_UNUSED,
		     tree node,
		     int indent)
{
  dump_tree_state.line_cnt = 0;
  
  fprintf (file, " args=");
  fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_ARGUMENTS (node)));
  if (DECL_LANG_SPECIFIC (node) && DECL_TEMPLATE_INFO (node))
    {
      fprintf (file, " tmpl-info=");
      fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_TEMPLATE_INFO (node)));
    }
  if (DECL_VINDEX (node))
    {
      fprintf (file, " inst=");
      fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_VINDEX (node)));
    }
  if (TREE_TYPE (node))
    {
      fprintf (file, " obj-type=");
      fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (TREE_TYPE (node)));
    }
  if (DECL_TEMPLATE_RESULT (node))
    {
      fprintf (file, " obj-decl=");
      fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_TEMPLATE_RESULT (node)));
    }
  if (DECL_INITIAL (node))
    {
      fprintf (file, " assoc-tmpls=");
      fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_INITIAL (node)));
    }		
  print_decl (file, annotation, node, indent);
  (void)node_seen (node, TRUE);
  
  if (DECL_ARGUMENTS (node))
    {
      if (dump_tree_state.line_cnt > 1)
      	newline_and_indent (file, 0);
      dump_tree (file, "(args)", DECL_ARGUMENTS (node), indent + INDENT);
    }
  
  if (DECL_VINDEX (node))
    {
      if (dump_tree_state.line_cnt > 1)
      	newline_and_indent (file, 0);
      dump_tree (file, "(inst)", DECL_VINDEX (node), indent + INDENT);
    }
    
  // tsubst_decl() in cp/pt.c looks interesting
  if (TREE_TYPE (node))
    {
      if (dump_tree_state.line_cnt > 1)
      	newline_and_indent (file, 0);
      dump_tree (file, "(obj-type)", TREE_TYPE (node), indent + INDENT); // type of object to be constructed
    }
    
  if (DECL_TEMPLATE_RESULT (node))
    {
      if (dump_tree_state.line_cnt > 1)
      	newline_and_indent (file, 0);
      dump_tree (file, "(obj-decl)", DECL_TEMPLATE_RESULT (node), indent + INDENT); // decl for object to be created
    }
  
  if (DECL_INITIAL (node))
    {
      if (dump_tree_state.line_cnt > 1)
      	newline_and_indent (file, 0);
      dump_tree (file, "(assoc-tmpl)", DECL_INITIAL (node), indent + INDENT); // associated templates
    }
}

static void
print_TEMPLATE_PARM_INDEX (FILE *file,
			   const char *annotation ATTRIBUTE_UNUSED,
			   tree node,
			   int indent)
{
  fprintf (file, " idx/lvl=("HOST_WIDE_INT_PRINT_DEC","HOST_WIDE_INT_PRINT_DEC")"
  		 " orig-lvl="HOST_WIDE_INT_PRINT_DEC
		 " dcndnts=",
		 TEMPLATE_PARM_IDX (node), TEMPLATE_PARM_LEVEL(node),
		 TEMPLATE_PARM_ORIG_LEVEL (node));
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TEMPLATE_PARM_DESCENDANTS (node)));
		 

  print_decl (file, annotation, TEMPLATE_PARM_DECL(node), indent + INDENT);
  dump_tree (file, "(dcndnt)", TEMPLATE_PARM_DESCENDANTS (node), indent + INDENT);
}

static void
print_TEMPLATE_TYPE_PARM (FILE *file,
			  const char *annotation,
			  tree node,
			  int indent)
{
  fprintf (file, " parms=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TEMPLATE_TYPE_IDX (node)));
  fprintf (file, " idx/lvl=("HOST_WIDE_INT_PRINT_DEC","HOST_WIDE_INT_PRINT_DEC")"
  		 " orig-lvl="HOST_WIDE_INT_PRINT_DEC,
        	 TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
        	 TEMPLATE_TYPE_ORIG_LEVEL (node));
  print_type (file, annotation, node, indent);
  
  dump_tree (file, "(parm)", TEMPLATE_TYPE_PARM_INDEX (node), indent + INDENT);
}

static void
print_TEMPLATE_TEMPLATE_PARM (FILE *file,
			      const char *annotation,
			      tree node,
			      int indent)
{
  fprintf (file, " tmpl-decl=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_NAME (node)));
  
  print_TEMPLATE_TYPE_PARM (file, annotation, node, indent);
  
  dump_tree (file, "(tmpl-decl)", TYPE_NAME (node), indent + INDENT);
}

static void
print_BOUND_TEMPLATE_TEMPLATE_PARM (FILE *file,
				    const char *annotation,
				    tree node,
				    int indent)
{
  fprintf (file, " name=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (node)));
  fprintf (file, " type-decl=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_NAME (node)));
  fprintf (file, " tmpl-decl=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_TI_TEMPLATE (node)));
  		  
  print_TEMPLATE_TYPE_PARM (file, annotation, node, indent);
  
  dump_tree (file, "(name)", TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (node), indent + INDENT);
  dump_tree (file, "(type-decl)", TYPE_NAME (node), indent + INDENT);
  dump_tree (file, "(tmpl-decl)", TYPE_TI_TEMPLATE (node), indent + INDENT);
}

static void
print_TYPENAME_TYPE (FILE *file,
		     const char *annotation,
		     tree node,
		     int indent)
{
  fprintf (file, " cntxt::id=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_CONTEXT (node)));
  fprintf (file, "::");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_NAME (node)));
		
  if (TYPENAME_TYPE_FULLNAME (node))
    {
      fprintf (file, " fullname=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (TYPENAME_TYPE_FULLNAME (node)));
    }
  if (TREE_TYPE (node))
    {
      fprintf (file, " impl-type=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (TREE_TYPE (node)));
    }
  print_type (file, annotation, node, indent);
  
  dump_tree (file, "(cntxt)", TYPE_CONTEXT (node), indent + INDENT);
  dump_tree (file, "(id)", TYPE_NAME (node), indent + INDENT);
  dump_tree (file, "(fullname)", TYPENAME_TYPE_FULLNAME (node), indent + INDENT);
  dump_tree (file, "(impl-type)", TREE_TYPE (node), indent + INDENT);
}

static void
print_UNBOUND_CLASS_TEMPLATE (FILE *file,
			      const char *annotation,
			      tree node,
			      int indent)
{
  fprintf (file, " cntxt::id=");
  fprintf (file, HOST_PTR_PRINTF,
	   HOST_PTR_PRINTF_VALUE (TYPE_CONTEXT (node)));
  fprintf (file, "::");
  fprintf (file, HOST_PTR_PRINTF,
	   HOST_PTR_PRINTF_VALUE (TYPE_NAME (node)));
  print_type (file, annotation, node, indent); 
  
  dump_tree (file, "(cntxt)", TYPE_CONTEXT (node), indent + INDENT);
  dump_tree (file, "(id)", TYPE_NAME (node), indent + INDENT);
}

static void
print_TYPEOF_TYPE (FILE *file,
		   const char *annotation,
		   tree node,
		   int indent)
{
  fprintf (file, " ");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_FIELDS (node)));
  print_type (file, annotation, node, indent); 
  
  dump_tree (file, NULL, TYPE_FIELDS (node), indent + INDENT);
}

static void
print_USING_DECL (FILE *file,
		  const char *annotation,
		  tree node,
		  int indent)
{
  fprintf (file, " scope=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (DECL_INITIAL (node)));
  print_decl (file, annotation, node, indent);

  dump_tree (file, "(scope)", DECL_INITIAL (node), indent + INDENT);
}

static void
print_USING_STMT (FILE *file,
		  const char *annotation ATTRIBUTE_UNUSED,
		  tree node,
		  int indent)
{
  print_operands (file, node, indent, TRUE, "(using)", NULL);
}

static void
print_DEFAULT_ARG (FILE *file, 
                   const char *annotation ATTRIBUTE_UNUSED, 
		   tree node, 
		   int indent ATTRIBUTE_UNUSED)
{
  fprintf (file, " def-arg=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (DEFARG_POINTER (node)));
  fprintf (file, " (struct unparsed_text * in cp/spew.c)");

  if (TREE_PURPOSE (node))
    {
      fprintf (file, " purpose=");
      fprintf (file, HOST_PTR_PRINTF,
      	        HOST_PTR_PRINTF_VALUE (TREE_PURPOSE (node)));
      dump_tree (file, "(purpose)", TREE_PURPOSE (node), indent + INDENT);
    }
}

static void
print_TEMPLATE_ID_EXPR (FILE *file,
			const char *annotation ATTRIBUTE_UNUSED,
			tree node,
			int indent)
{
  print_operands (file, node, indent, TRUE, "(tmpl)", "(args)", NULL);
}

#if 0

static void
print_CPLUS_BINDING (FILE *file, 
                     const char *annotation ATTRIBUTE_UNUSED, 
		     tree node, 
		     int indent)
{
  tree n;
  
  #define BINDING_LEVEL(NODE) \
     (((struct tree_binding*)NODE)->scope.level)
  
  if (LOCAL_BINDING_P (node))
    fputs (" local", file);
  if (INHERITED_VALUE_BINDING_P (node))
    fputs (" inherited", file);
  
  fprintf (file, " value=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (BINDING_VALUE (node)));
    
  if (BINDING_HAS_LEVEL_P (node))
    {
      fprintf (file, " level=");
      fprintf (file, HOST_PTR_PRINTF,
      			HOST_PTR_PRINTF_VALUE ( (node)));
      fprintf (file, " (struct binding_level * in cp/decl.c)");
    }
  else
    {
      fprintf (file, " scope=");
      fprintf (file, HOST_PTR_PRINTF,
      			HOST_PTR_PRINTF_VALUE (BINDING_LEVEL (node)));
    }
  
  if (TREE_CHAIN (node))
    {
      fprintf (file, " chain=");
      fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (TREE_CHAIN (node)));
    }
  
  dump_tree (file, "(value)", BINDING_VALUE (node), indent + INDENT);
  if (!BINDING_HAS_LEVEL_P (node))
    dump_tree (file, "(scope)", BINDING_SCOPE (node), indent + INDENT);
  
  for (n = TREE_CHAIN (node); n; n = TREE_CHAIN (n))
    dump_tree (file, "(chain)", n, indent + INDENT);
}

#endif

static void
print_OVERLOAD (FILE *file,
	        const char *annotation ATTRIBUTE_UNUSED,
	        tree node,
	        int indent)
{
  tree n;
  
  if (OVL_FUNCTION (node))
    {
      fprintf (file, " ovld=");
      fprintf (file, HOST_PTR_PRINTF,
    	HOST_PTR_PRINTF_VALUE (OVL_FUNCTION (node)));
    }
  if (OVL_CHAIN (node))
    {
      fprintf (file, " next-ovld=");
      fprintf (file, HOST_PTR_PRINTF,
    	HOST_PTR_PRINTF_VALUE (OVL_CHAIN (node)));
    }
  
  if ((TREE_CODE (OVL_FUNCTION (node)) == FUNCTION_DECL
       || TREE_CODE (OVL_FUNCTION (node)) == TEMPLATE_DECL)
      && DECL_NAME (OVL_FUNCTION (node)))
    fprintf (file, " %s",
    	IDENTIFIER_POINTER (DECL_NAME (OVL_FUNCTION (node))));
  
  if (DECL_CONSTRUCTOR_P (OVL_FUNCTION (node)))
    dump_tree (file, NULL, OVL_FUNCTION (node), indent + INDENT);
  else
    dump_tree (file, "(ovld)", OVL_FUNCTION (node), indent + INDENT);

  for (n = OVL_CHAIN (node); n; n = OVL_CHAIN (n))
    dump_tree (file, NULL, n, indent + INDENT);
}

static void
print_WRAPPER (FILE *file,
               const char *annotation ATTRIBUTE_UNUSED,
	       tree node,
	       int indent ATTRIBUTE_UNUSED)
{
  /* TODO: Print out tree_common.  */
  fprintf (file, " ptr=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (WRAPPER_ZC (node)));
}

static void
print_LOOKUP_EXPR (FILE *file,
		   const char *annotation ATTRIBUTE_UNUSED,
		   tree node,
		   int indent)
{
  if (LOOKUP_EXPR_GLOBAL (node))
    fputs (" glbl", file);
  
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_MODOP_EXPR (FILE *file, 
                  const char *annotation ATTRIBUTE_UNUSED, 
		  tree node, 
		  int indent)
{
  print_operands (file, node, indent, TRUE, "(lhs)", "(modifycode)", "(rhs)", NULL);
}

static void
print_CAST_EXPR (FILE *file, 
                 const char *annotation ATTRIBUTE_UNUSED, 
		 tree node, 
		 int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_REINTERPRET_CAST_EXPR (FILE *file, 
                             const char *annotation ATTRIBUTE_UNUSED, 
			     tree node, 
			     int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CONST_CAST_EXPR (FILE *file, 
                       const char *annotation ATTRIBUTE_UNUSED, 
		       tree node, 
		       int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_STATIC_CAST_EXPR (FILE *file, 
                        const char *annotation ATTRIBUTE_UNUSED, 
			tree node, 
			int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_DYNAMIC_CAST_EXPR (FILE *file, 
                         const char *annotation ATTRIBUTE_UNUSED, 
			 tree node ATTRIBUTE_UNUSED, 
			 int indent ATTRIBUTE_UNUSED)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_DOTSTAR_EXPR (FILE *file, 
                    const char *annotation ATTRIBUTE_UNUSED, 
		    tree node, 
		    int indent)
{
  print_operands (file, node, indent, TRUE, "(datum)", "(cmpnt)", NULL);
}

static void
print_TYPEID_EXPR (FILE *file, 
                   const char *annotation ATTRIBUTE_UNUSED, 
		   tree node, 
		   int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PSEUDO_DTOR_EXPR (FILE *file, 
                        const char *annotation ATTRIBUTE_UNUSED, 
			tree node, 
			int indent)
{
  print_operands (file, node, indent, TRUE, "(obj)", "(scope)", "(dtor)", NULL);
}

static void
print_CTOR_INITIALIZER (FILE *file,
			const char *annotation ATTRIBUTE_UNUSED,
			tree node,
			int indent)
{
  print_operands (file, node, indent, TRUE, "(mbr-init)", "(base-init)", NULL);
}

static void
print_RETURN_INIT (FILE *file,
		   const char *annotation ATTRIBUTE_UNUSED,
		   tree node,
		   int indent)
{
  print_operands (file, node, indent, TRUE, "(id)", "(init)", NULL);
}

static void
print_TRY_BLOCK (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  if (FN_TRY_BLOCK_P (node))
    fputs (" func-try-blk", file);
  if (CLEANUP_P (node))
    fputs (" clnup", file);
    
  print_operands (file, node, indent, TRUE, "(body)", "(hndlrs)", NULL);
}

static void
print_EH_SPEC_BLOCK (FILE *file,
		     const char *annotation ATTRIBUTE_UNUSED,
		     tree node,
		     int indent)
{
  print_operands (file, node, indent, TRUE, "(body)", "(raises)", NULL);
}

static void
print_HANDLER (FILE *file,
	       const char *annotation ATTRIBUTE_UNUSED,
	       tree node,
	       int indent)
{
  fprintf (file, " hdnlr-type=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (HANDLER_TYPE (node)));
  		
  print_operands (file, node, indent, TRUE, "(parms)", "(body)", NULL);
}

static void
print_MUST_NOT_THROW_EXPR (FILE *file,
			   const char *annotation ATTRIBUTE_UNUSED,
			   tree node,
			   int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TAG_DEFN (FILE *file ATTRIBUTE_UNUSED, 
                const char *annotation ATTRIBUTE_UNUSED, 
		tree node ATTRIBUTE_UNUSED, 
		int indent ATTRIBUTE_UNUSED)
{
}

static void
print_IDENTITY_CONV (FILE *file,
		     const char *annotation ATTRIBUTE_UNUSED,
		     tree node,
		     int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LVALUE_CONV (FILE *file,
		   const char *annotation ATTRIBUTE_UNUSED,
		   tree node,
		   int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_QUAL_CONV (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_STD_CONV (FILE *file,
		const char *annotation ATTRIBUTE_UNUSED,
		tree node,
		int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PTR_CONV (FILE *file,
		const char *annotation ATTRIBUTE_UNUSED,
		tree node,
		int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PMEM_CONV (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BASE_CONV (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_REF_BIND (FILE *file,
		const char *annotation ATTRIBUTE_UNUSED,
		tree node,
		int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_USER_CONV (FILE *file,
		 const char *annotation ATTRIBUTE_UNUSED,
		 tree node,
		 int indent)
{
  fprintf (file, " from=");
  fprintf (file, HOST_PTR_PRINTF,
  	HOST_PTR_PRINTF_VALUE (TREE_OPERAND (node, 0)));
  fprintf (file, " cand=");
  fprintf (file, HOST_PTR_PRINTF,
  	HOST_PTR_PRINTF_VALUE (TREE_OPERAND (node, 1)));
  
  print_operands (file, node, indent, TRUE, "(from)", "(cand)", NULL);
}

static void
print_AMBIG_CONV (FILE *file,
		  const char *annotation ATTRIBUTE_UNUSED,
		  tree node,
		  int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RVALUE_CONV (FILE *file,
		   const char *annotation ATTRIBUTE_UNUSED,
		   tree node,
		   int indent)
{
  print_operands (file, node, indent, TRUE, NULL);
}

/*-------------------------------------------------------------------*/

/* Override routine in c-tmp-tree.c to handle SRCLOC node.  */
static void
print_SRCLOC (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  fprintf (file, " line=%d file=", SRCLOC_LINE (node));
  print_string_constant (file, (char *)SRCLOC_FILE (node), 35);
}

/* Override to routine in dmp-tree.c print Method vector Record Type.  */
static void
print_RECORD_TYPE (FILE *file,
		   const char *annotation,
		   tree node,
		   int indent)
{
  tree n;
  
  fprintf (file, " fields=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TYPE_FIELDS (node)));
  fprintf (file, " mbrs=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (CLASSTYPE_METHOD_VEC (node)));
  if (TYPE_NO_FORCE_BLK (node))
    fputs (" no-force-blk", file);
  fprintf (file, " #parents=%d", CLASSTYPE_N_BASECLASSES (node));
  if (CLASSTYPE_USE_TEMPLATE (node))
    fprintf (file, " use-tmpl=%d", CLASSTYPE_USE_TEMPLATE (node));
  if (TYPE_PTRMEMFUNC_P (node))
    {
      fprintf (file, " ptrmemfunc-fn-type=");
      fprintf (file, HOST_PTR_PRINTF,
	HOST_PTR_PRINTF_VALUE (TYPE_PTRMEMFUNC_FN_TYPE (node)));
    }
  print_type (file, annotation, node, indent);
  (void)node_seen (node, TRUE);
  
  for (n = TYPE_FIELDS (node); n; n = TREE_CHAIN (n))
    {
      if (TREE_CODE (n) == TYPE_DECL
          && TREE_TYPE (n) == DECL_CONTEXT (n)
          && TREE_TYPE (n) == node)
        dump_tree (file, "(self-reference)", n, indent + INDENT);
      else
        dump_tree (file, NULL, n, indent + INDENT);
    }

  dump_tree (file, "(mbrs)", CLASSTYPE_METHOD_VEC (node), indent + INDENT);   
  
  if (TYPE_PTRMEMFUNC_P (node))
    {
      newline_and_indent (file, 0);
      dump_tree (file, "(ptrmemfunc-fn-type)",
		  TYPE_PTRMEMFUNC_FN_TYPE (node), indent + INDENT);
    }
}

/* Override to routine in dmp-tree.c to print namespace.  */
static void
print_NAMESPACE_DECL (FILE *file,
		      const char *annotation,
		      tree node,
		      int indent)
{
  if (NAMESPACE_LEVEL (node))
    {
      fprintf (file, " binding_lvl=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (NAMESPACE_LEVEL (node)));
    }
  if (DECL_NAMESPACE_ALIAS (node))
    {
      fprintf (file, " alias=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (DECL_NAMESPACE_ALIAS (node)));
    }
  if (DECL_NAMESPACE_USING (node))
    {
      fprintf (file, " using=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (DECL_NAMESPACE_USING (node)));
    }
  if (DECL_NAMESPACE_USERS (node))
    {
      fprintf (file, " usrs=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (DECL_NAMESPACE_USERS (node)));
    }

  print_decl (file, annotation, node, indent);
    
  dump_tree (file, "(alias)", DECL_NAMESPACE_ALIAS (node), indent + INDENT);
  dump_tree (file, "(using)", DECL_NAMESPACE_USING (node), indent + INDENT);
  dump_tree (file, "(usrs)",  DECL_NAMESPACE_USERS (node), indent + INDENT);
  
  if (dump_tree_state.visit_only_once == DMP_TREE_VISIT_ONCE2)
    {
      for (node = cp_namespace_decls (node); node; node = TREE_CHAIN (node))
	dump_tree (file, NULL, node, indent + INDENT);
    }
}

static void
print_ADDR_EXPR (FILE *file,
	         const char *annotation ATTRIBUTE_UNUSED,
	         tree node,
	         int indent)
{
  if (PTRMEM_OK_P (node))
    fputs (" ptr-to-mbr-ok", file);
    
  print_operands (file, node, indent, TRUE, NULL);
}

/*-------------------------------------------------------------------*/

/* Return 1 if tree node is a C++ specific tree node from cp-tree.def
   or a tree node specific to whatever cp_prev_lang_dump_tree_p
   calls.  Otherwise return 0.
*/

int
cp_dump_tree_p (FILE *file, const char *annotation, tree node, int indent)
{
   switch (TREE_CODE (node)) 
     {
     #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) \
     case SYM: print_ ## SYM (file, annotation, node, indent); break;
     #include "cp-tree.def"
     #undef DEFTREECODE
     
     case SRCLOC:
       print_SRCLOC (file, annotation, node, indent);
       break;
       
     case RECORD_TYPE:
       print_RECORD_TYPE (file, annotation, node, indent);
       break;
    
     case NAMESPACE_DECL:
       print_NAMESPACE_DECL (file, annotation, node, indent);
       break;
     
     case ADDR_EXPR:
       print_ADDR_EXPR (file, annotation, node, indent);
       break;
     
     default:
       return cp_prev_lang_dump_tree_p (file, annotation, node, indent);
       break;
     }
   
   return 1;
}

#endif /* ENABLE_DMP_TREE */

/*-------------------------------------------------------------------*/

#if 0

cd $gcc3/gcc; \
cc -no-cpp-precomp -c -DIN_GCC  -g \
  -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes  \
  -DHAVE_CONFIG_H \
  -I$gcc3obj \
  -Icp \
  -I. \
  -Iconfig \
  -I../include \
  cp/cp-dmp-tree.c -o ~/tmp.o -w 

#endif