invoke.texi (-fdump-translation-unit): New option.
authorMark Mitchell <mark@codesourcery.com>
Tue, 3 Aug 1999 01:37:47 +0000 (01:37 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 3 Aug 1999 01:37:47 +0000 (01:37 +0000)
* invoke.texi (-fdump-translation-unit): New option.
* Make-lang.in (CXX_SRCS): Add dump.c.
* Makefile.in (CXX_OBJS): Add dump.o.
(dump.o): New target.
* cp-tree.h (DECL_CONV_FN_P): Document.
(DECL_OVERLOADED_OPERATOR_P): New function.
(TYPE_PTRMEM_CLASS_TYPE): New macro.
(TYPE_PTRMEM_POINTED_TO_TYPE): Likewise.
(PTRMEM_CST_CLASS): Use TYPE_PTRMEM_CLASS_TYPE.
(ASM_VOLATILE_P): New macro.
(STMT_LINENO): Likewise.
(cp_namespace_decls): New function.
(dump_node_to_file): New function.
* decl.c (cp_namespace_decls): New function.
(walk_namespaces_r): Use it.
(wrapup_globals_for_namespace): Likewise.
* decl2.c (flag_dump_translation_unit): New variable.
(lang_decode_option): Handle -fdump-translation-unit.
(finish_file): If flag_dump_translation_unit is set, dump the
translation unit.
* dump.c: New file.
* lang-options.h: Add -fdump-translation-unit.
* pt.c (tsubst_template_parms): Robustify.
(tsubst_decl): Use DECL_OVERLOADED_OPERATOR_P.
(tsubst_expr): Use STMT_LINENO.
* semantics.c (finish_asm_stmt): Eliminate duplicate code.  Check
for invalid cv-qualifiers even while building templates.

From-SVN: r28434

12 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/Makefile.in
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/dump.c [new file with mode: 0644]
gcc/cp/lang-options.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/invoke.texi

index 58d47e3ca2001aaf180eef015af182ad197bbc67..6baa3338a6653ba0ee0c179f4c2e8d883f5f4801 100644 (file)
@@ -1,3 +1,7 @@
+Mon Aug  2 18:29:32 1999  Mark Mitchell  <mark@codesourcery.com>
+
+       * invoke.texi (-fdump-translation-unit): New option.
+
 Mon Aug  2 17:10:24 1999  Mark Mitchell  <mark@codesourcery.com>
 
        * toplev.h (errorcount): Declare.
index 759442ac711b3fc51edd0939c8203c63b016ee6a..886401a2807150b16340426f48c8af415eb94fce 100644 (file)
@@ -1,3 +1,32 @@
+1999-08-02  Mark Mitchell  <mark@codesourcery.com>
+
+       * Make-lang.in (CXX_SRCS): Add dump.c.
+       * Makefile.in (CXX_OBJS): Add dump.o.
+       (dump.o): New target.
+       * cp-tree.h (DECL_CONV_FN_P): Document.
+       (DECL_OVERLOADED_OPERATOR_P): New function.
+       (TYPE_PTRMEM_CLASS_TYPE): New macro.
+       (TYPE_PTRMEM_POINTED_TO_TYPE): Likewise.
+       (PTRMEM_CST_CLASS): Use TYPE_PTRMEM_CLASS_TYPE.
+       (ASM_VOLATILE_P): New macro.
+       (STMT_LINENO): Likewise.
+       (cp_namespace_decls): New function.
+       (dump_node_to_file): New function.
+       * decl.c (cp_namespace_decls): New function.
+       (walk_namespaces_r): Use it.
+       (wrapup_globals_for_namespace): Likewise.
+       * decl2.c (flag_dump_translation_unit): New variable.
+       (lang_decode_option): Handle -fdump-translation-unit.
+       (finish_file): If flag_dump_translation_unit is set, dump the
+       translation unit.
+       * dump.c: New file.
+       * lang-options.h: Add -fdump-translation-unit.
+       * pt.c (tsubst_template_parms): Robustify.
+       (tsubst_decl): Use DECL_OVERLOADED_OPERATOR_P.
+       (tsubst_expr): Use STMT_LINENO.
+       * semantics.c (finish_asm_stmt): Eliminate duplicate code.  Check
+       for invalid cv-qualifiers even while building templates.
+       
 1999-08-02  Richard Henderson  <rth@cygnus.com>
 
        * call.c: Include defaults.h instead of expr.h.
index 72795da34993af7b80b52c294fac0a5ad863dc43..2e681b8194aea5dd019c06a4b74894146df78a55 100644 (file)
@@ -117,7 +117,8 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
  $(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
  $(srcdir)/cp/error.c $(srcdir)/cp/friend.c $(srcdir)/cp/init.c \
  $(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
- $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
+ $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c \
+ $(srcdir)/cp/dump.c
 
 cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
        $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def $(srcdir)/cp/gxx.gperf hash.o
index edd337904461e59842f917f61efeeae8640dc8f3..63f858093805cbe203dae6a662e6a8440e3656a7 100644 (file)
@@ -188,7 +188,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config -I$(srcdir)
 CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
  class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \
  except.o friend.o init.o method.o search.o semantics.o tree.o xref.o \
- repo.o @extra_cxx_objs@
+ repo.o dump.o @extra_cxx_objs@
 
 # Language-independent object files.
 OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
@@ -306,7 +306,7 @@ repo.o : repo.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
   $(srcdir)/../toplev.h
 semantics.o: semantics.c $(CONFIG_H) $(CXX_TREE_H) lex.h \
   $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h
-  
+dump.o: dump.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
 
 #\f
 # These exist for maintenance purposes.
index e624102bfd1fd9dbd7def1a88dc7ac348a7e89be..c5af6fdc736118f039c0e4cf93f7a86ddb699515 100644 (file)
@@ -315,7 +315,8 @@ struct tree_srcloc
 
 #define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE)
 
-/* Nonzero if this identifier is the prefix for a mangled C++ operator name.  */
+/* Nonzero if this identifier is the prefix for a mangled C++ operator
+   name.  */
 #define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2(NODE)
 
 /* Nonzero if this identifier is the name of a type-conversion
@@ -1296,9 +1297,14 @@ struct lang_decl
   (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE))      \
    && DECL_LANGUAGE (NODE) == lang_cplusplus)
 
+/* Non-zero if NODE is a user-defined conversion operator.  */
 #define DECL_CONV_FN_P(NODE)                                                \
   (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE)))
 
+/* Non-zero if NODE is an overloaded operator.  */
+#define DECL_OVERLOADED_OPERATOR_P(NODE)       \
+  (IDENTIFIER_OPNAME_P (DECL_NAME ((NODE))))
+
 /* For FUNCTION_DECLs: nonzero means that this function is a constructor
    for an object with virtual baseclasses.  */
 #define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
@@ -1857,12 +1863,22 @@ extern int flag_new_for_scope;
 #define DELTA2_FROM_PTRMEMFUNC(NODE) delta2_from_ptrmemfunc ((NODE))
 #define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE))
 
+/* For a pointer-to-member type of the form `T X::*', this is `X'.  */
+#define TYPE_PTRMEM_CLASS_TYPE(NODE)                   \
+  (TYPE_PTRMEM_P ((NODE))                              \
+   ? TYPE_OFFSET_BASETYPE (TREE_TYPE ((NODE)))         \
+   : TYPE_PTRMEMFUNC_OBJECT_TYPE ((NODE)))
+
+/* For a pointer-to-member type of the form `T X::*', this is `T'.  */
+#define TYPE_PTRMEM_POINTED_TO_TYPE(NODE)              \
+   (TYPE_PTRMEM_P ((NODE))                             \
+    ? TREE_TYPE (TREE_TYPE (NODE))                     \
+    : TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE ((NODE))))
+
 /* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for
    `X'.  */
-#define PTRMEM_CST_CLASS(NODE)                           \
-   (TYPE_PTRMEM_P (TREE_TYPE (NODE))                     \
-    ? TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (NODE))) \
-    : TYPE_PTRMEMFUNC_OBJECT_TYPE (TREE_TYPE (NODE)))
+#define PTRMEM_CST_CLASS(NODE) \
+  TYPE_PTRMEM_CLASS_TYPE (TREE_TYPE (NODE))
 
 /* For a pointer-to-member constant `X::Y' this is the _DECL for 
    `Y'.  */
@@ -2172,6 +2188,14 @@ extern int flag_new_for_scope;
 #define ASM_INPUTS(NODE)        TREE_OPERAND (NODE, 3)
 #define ASM_CLOBBERS(NODE)      TREE_OPERAND (NODE, 4)
 
+/* Nonzero for an ASM_STMT if the assembly statement is volatile.  */
+#define ASM_VOLATILE_P(NODE)                   \
+  (ASM_CV_QUAL ((NODE)) != NULL_TREE)
+
+/* The line-number at which a statement began.  */
+#define STMT_LINENO(NODE)                      \
+  (TREE_COMPLEXITY ((NODE)))
+
 /* An enumeration of the kind of tags that C++ accepts.  */
 enum tag_types { record_type, class_type, union_type, enum_type,
                   signature_type };
@@ -2990,6 +3014,7 @@ typedef int (*walk_namespaces_fn)               PROTO((tree, void *));
 extern int walk_namespaces                      PROTO((walk_namespaces_fn,
                                                       void *));
 extern int wrapup_globals_for_namespace         PROTO((tree, void *));
+extern tree cp_namespace_decls                  PROTO((tree));
 
 /* in decl2.c */
 extern int check_java_method                   PROTO((tree));
@@ -3604,6 +3629,9 @@ extern void GNU_xref_assign                       PROTO((tree));
 extern void GNU_xref_hier                      PROTO((tree, tree, int, int, int));
 extern void GNU_xref_member                    PROTO((tree, tree));
 
+/* in dump.c */
+extern void dump_node_to_file                   PROTO ((tree, char *));
+
 /* -- end of C++ */
 
 #endif /* not _CP_TREE_H */
index b60a5eca46457e5b00ede7a7e434a1b95745f77f..46708ac1782b1632bdf5293bf97c5d29326e8b08 100644 (file)
@@ -1808,6 +1808,15 @@ sigtable_decl_p (t, data)
          && IS_SIGNATURE (TREE_TYPE (t)));
 }
 
+/* Return the declarations that are members of the namespace NS.  */
+
+tree
+cp_namespace_decls (ns)
+     tree ns;
+{
+  return NAMESPACE_LEVEL (ns)->names;
+}
+
 /* Walk all the namespaces contained NAMESPACE, including NAMESPACE
    itself, calling F for each.  The DATA is passed to F as well.  */
 
@@ -1822,7 +1831,7 @@ walk_namespaces_r (namespace, f, data)
 
   result |= (*f) (namespace, data);
 
-  for (current = NAMESPACE_LEVEL (namespace)->names;
+  for (current = cp_namespace_decls (namespace);
        current;
        current = TREE_CHAIN (current))
     {
@@ -1921,7 +1930,7 @@ wrapup_globals_for_namespace (namespace, data)
      tree namespace;
      void *data;
 {
-  tree globals = NAMESPACE_LEVEL (namespace)->names;
+  tree globals = cp_namespace_decls (namespace);
   int len = list_length (globals);
   tree *vec = (tree *) alloca (sizeof (tree) * len);
   int i;
index d5125fc61d336cdb686404dd9b9e3db95e0ee49c..cbc6c23eb9d498eaecaf488c3b1380c8a94931fd 100644 (file)
@@ -246,6 +246,11 @@ int flag_optional_diags = 1;
 
 int flag_const_strings = 1;
 
+/* If non-NULL, dump the tree structure for the entire translation
+   unit to this file.  */
+
+char *flag_dump_translation_unit = 0;
+
 /* Nonzero means warn about deprecated conversion from string constant to
    `char *'.  */
 
@@ -649,6 +654,13 @@ lang_decode_option (argc, argv)
          name_mangling_version =
                read_integral_parameter (p + 22, p - 2, name_mangling_version);
        }
+      else if (!strncmp (p, "dump-translation-unit-", 22))
+       {
+         if (p[22] == '\0')
+           error ("no file specified with -fdump-translation-unit");
+         else
+           flag_dump_translation_unit = p + 22;
+       }
       else for (j = 0;
                !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
                j++)
@@ -3721,6 +3733,11 @@ finish_file ()
 
   finish_repo ();
 
+  /* The entire file is now complete.  If requested, dump everything
+     file.   */
+  if (flag_dump_translation_unit)
+    dump_node_to_file (global_namespace, flag_dump_translation_unit);
+
   this_time = get_run_time ();
   parse_time -= this_time - start_time;
   varconst_time += this_time - start_time;
diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c
new file mode 100644 (file)
index 0000000..b22565c
--- /dev/null
@@ -0,0 +1,861 @@
+/* Tree-dumping functionality for intermediate representation.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+   Written by Mark Mitchell <mark@codesourcery.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.  */
+
+/* TODO: Class types.
+         Binfos.  */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "splay-tree.h"
+
+/* Flags used with queue functions.  */
+#define DUMP_NONE     0
+#define DUMP_CHILDREN 1
+#define DUMP_BINFO    2
+
+/* Information about a node to be dumped.  */
+
+typedef struct dump_node_info
+{
+  /* The index for the node.  */
+  unsigned int index;
+  /* Nonzero if we should dump the children of the node.  */
+  unsigned int dump_children_p : 1;
+  /* Nonzero if the node is a binfo.  */
+  unsigned int binfo_p : 1;
+} *dump_node_info_p;
+
+/* A dump_queue is a link in the queue of things to be dumped.  */
+
+typedef struct dump_queue
+{
+  /* The queued tree node.  */
+  splay_tree_node node;
+  /* The next node in the queue.  */
+  struct dump_queue *next;
+} *dump_queue_p;
+
+/* A dump_info gives information about how we should perform the dump 
+   and about the current state of the dump.  */
+
+typedef struct dump_info
+{
+  /* The stream on which to dump the information.  */
+  FILE *stream;
+  /* The next unused node index.  */
+  unsigned int index;
+  /* The next column.  */
+  unsigned int column;
+  /* The first node in the queue of nodes to be written out.  */
+  dump_queue_p queue;
+  /* The last node in the queue.  */
+  dump_queue_p queue_end;
+  /* Free queue nodes.  */
+  dump_queue_p free_list;
+  /* The tree nodes which we have already written out.  The 
+     keys are the addresses of the nodes; the values are the integer
+     indices we assigned them.  */
+  splay_tree nodes;
+} *dump_info_p;
+
+static unsigned int queue PROTO ((dump_info_p, tree, int));
+static void dump_index PROTO ((dump_info_p, unsigned int));
+static void queue_and_dump_index PROTO ((dump_info_p, char *, tree, int));
+static void queue_and_dump_type PROTO ((dump_info_p, tree, int));
+static void dequeue_and_dump PROTO ((dump_info_p));
+static void dump_new_line PROTO ((dump_info_p));
+static void dump_maybe_newline PROTO ((dump_info_p));
+static void dump_int PROTO ((dump_info_p, char *, int));
+static void dump_string PROTO ((dump_info_p, char *));
+static void dump_string_field PROTO ((dump_info_p, char *, char *));
+static void dump_node PROTO ((tree, FILE *));
+
+/* Add T to the end of the queue of nodes to dump.  If DUMP_CHILDREN_P
+   is non-zero, then its children should be dumped as well.  Returns
+   the index assigned to T.  */
+
+static unsigned int
+queue (di, t, flags)
+     dump_info_p di;
+     tree t;
+     int flags;
+{
+  dump_queue_p dq;
+  dump_node_info_p dni;
+  unsigned int index;
+
+  /* Assign the next available index to T.  */
+  index = ++di->index;
+
+  /* Obtain a new queue node.  */
+  if (di->free_list)
+    {
+      dq = di->free_list;
+      di->free_list = dq->next;
+    }
+  else
+    dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
+
+  /* Create a new entry in the splay-tree.  */
+  dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
+  dni->index = index;
+  dni->dump_children_p = flags & DUMP_CHILDREN;
+  dni->binfo_p = flags & DUMP_BINFO;
+  dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t, 
+                               (splay_tree_value) dni);
+
+  /* Add it to the end of the queue.  */
+  dq->next = 0;
+  if (!di->queue_end)
+    di->queue = dq;
+  else
+    di->queue_end->next = dq;
+  di->queue_end = dq;
+
+  /* Return the index.  */
+  return index;
+}
+
+static void
+dump_index (di, index)
+     dump_info_p di;
+     unsigned int index;
+{
+  fprintf (di->stream, "@%-6u ", index);
+  di->column += 8;
+}
+
+/* If T has not already been output, queue it for subsequent output.
+   FIELD is a string to print before printing the index.  Then, the
+   index of T is printed.  */
+
+static void
+queue_and_dump_index (di, field, t, flags)
+     dump_info_p di;
+     char *field;
+     tree t;
+     int flags;
+{
+  unsigned int index;
+  splay_tree_node n;
+
+  /* If there's no node, just return.  This makes for fewer checks in
+     our callers.  */
+  if (!t)
+    return;
+
+  /* See if we've already queued or dumped this node.  */
+  n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
+  if (n)
+    index = ((dump_node_info_p) n->value)->index;
+  else
+    /* If we haven't, add it to the queue.  */
+    index = queue (di, t, flags);
+
+  /* Print the index of the node.  */
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-4s: ", field);
+  di->column += 6;
+  dump_index (di, index);
+}
+
+/* Dump the type of T.  */
+
+static void
+queue_and_dump_type (di, t, dump_children_p)
+     dump_info_p di;
+     tree t;
+     int dump_children_p;
+{
+  queue_and_dump_index (di, "type", TREE_TYPE (t), dump_children_p);
+}
+
+/* Insert a new line in the dump output, and indent to an appropriate
+   place to start printing more fields.  */
+
+static void
+dump_new_line (di)
+     dump_info_p di;
+{
+  fprintf (di->stream, "\n%25s", "");
+  di->column = 25;
+}
+
+/* If necessary, insert a new line.  */
+
+static void
+dump_maybe_newline (di)
+     dump_info_p di;
+{
+  /* See if we need a new line.  */
+  if (di->column > 53)
+    dump_new_line (di);
+  /* See if we need any padding.  */
+  else if ((di->column - 25) % 14 != 0)
+    {
+      fprintf (di->stream, "%*s", 14 - ((di->column - 25) % 14), "");
+      di->column += 14 - (di->column - 25) % 14;
+    }
+}
+
+/* Dump I using FIELD to identity it.  */
+
+static void
+dump_int (di, field, i)
+     dump_info_p di;
+     char *field;
+     int i;
+{
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-4s: %-7d ", field, i);
+  di->column += 14;
+}
+
+/* Dump the string S.  */
+
+static void
+dump_string (di, string)
+     dump_info_p di;
+     char *string;
+{
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-13s ", string);
+  if (strlen (string) > 13)
+    di->column += strlen (string) + 1;
+  else
+    di->column += 14;
+}
+
+/* Dump the string field S.  */
+
+static void
+dump_string_field (di, field, string)
+     dump_info_p di;
+     char *field;
+     char *string;
+{
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-4s: %-7s ", field, string);
+  if (strlen (string) > 7)
+    di->column += 6 + strlen (string) + 1;
+  else
+    di->column += 14;
+}
+
+/* Dump information common to statements from STMT.  */
+
+static void
+dump_stmt (di, t)
+     dump_info_p di;
+     tree t;
+{
+  dump_int (di, "line", STMT_LINENO (t));
+}
+
+/* Dump the CHILD and its children.  */
+#define dump_child(field, child) \
+  queue_and_dump_index (di, field, child, DUMP_CHILDREN)
+
+/* Dump the next node in the queue.  */
+
+static void 
+dequeue_and_dump (di)
+     dump_info_p di;
+{
+  dump_queue_p dq;
+  splay_tree_node stn;
+  dump_node_info_p dni;
+  tree t;
+  unsigned int index;
+  int dump_children_p;
+  enum tree_code code;
+  char code_class;
+
+  /* Get the next node from the queue.  */
+  dq = di->queue;
+  stn = dq->node;
+  t = (tree) stn->key;
+  dni = (dump_node_info_p) stn->value;
+  index = dni->index;
+  dump_children_p = dni->dump_children_p;
+
+  /* Remove the node from the queue, and put it on the free list.  */
+  di->queue = dq->next;
+  if (!di->queue)
+    di->queue_end = 0;
+  dq->next = di->free_list;
+  di->free_list = dq;
+
+  /* Print the node index.  */
+  dump_index (di, index);
+  /* And the type of node this is.  */
+  fprintf (di->stream, "%-16s ", tree_code_name[(int) TREE_CODE (t)]);
+  di->column = 25;
+
+  /* Figure out what kind of node this is.  */
+  code = TREE_CODE (t);
+  code_class = TREE_CODE_CLASS (code);
+
+  /* Although BINFOs are TREE_VECs, we dump them specially so as to be
+     more informative.  */
+  if (dni->binfo_p)
+    {
+      if (TREE_VIA_PUBLIC (t))
+       dump_string (di, "pub");
+      else if (TREE_VIA_PROTECTED (t))
+       dump_string (di, "prot");
+      else if (TREE_VIA_PRIVATE (t))
+       dump_string (di, "priv");
+      if (TREE_VIA_VIRTUAL (t))
+       dump_string (di, "virt");
+           
+      if (dump_children_p) 
+       {
+         dump_child ("type", BINFO_TYPE (t));
+         dump_child ("base", BINFO_BASETYPES (t));
+       }
+
+      goto done;
+    }
+
+  /* We can knock off a bunch of expression nodes in exactly the same
+     way.  */
+  if (IS_EXPR_CODE_CLASS (code_class))
+    {
+      /* If we're dumping children, dump them now.  */
+      if (dump_children_p)
+       {
+         queue_and_dump_type (di, t, 1);
+
+         switch (code_class)
+           {
+           case '1':
+             dump_child ("op 0", TREE_OPERAND (t, 0));
+             break;
+             
+           case '2':
+           case '<':
+             dump_child ("op 0", TREE_OPERAND (t, 0));
+             dump_child ("op 1", TREE_OPERAND (t, 1));
+             break;
+             
+           case 'e':
+             /* These nodes are handled explicitly below.  */
+             break;
+             
+           default:
+             my_friendly_abort (19990726);
+           }
+       }
+    }
+  else if (code_class == 'd')
+    {
+      /* All declarations have names.  */
+      if (DECL_NAME (t))
+       dump_child ("name", DECL_NAME (t));
+      /* And types.  */
+      if (dump_children_p)
+       {
+         queue_and_dump_type (di, t, 1);
+         queue_and_dump_index (di, "scpe", DECL_CONTEXT (t), 0);
+       }
+      /* And a source position.  */
+      if (DECL_SOURCE_FILE (t))
+       {
+         char *filename = rindex (DECL_SOURCE_FILE (t), '/');
+         if (!filename)
+           filename = DECL_SOURCE_FILE (t);
+         else
+           /* Skip the slash.  */
+           ++filename;
+
+         dump_maybe_newline (di);
+         fprintf (di->stream, "srcp: %s:%-6d ", filename, 
+                  DECL_SOURCE_LINE (t));
+         di->column += 6 + strlen (filename) + 8;
+       }
+      /* And any declaration can be compiler-generated.  */
+      if (DECL_ARTIFICIAL (t))
+       dump_string (di, "artificial");
+      if (TREE_CHAIN (t))
+       dump_child ("chan", TREE_CHAIN (t));
+    }
+  else if (code_class == 't')
+    {
+      /* All types have qualifiers.  */
+      int quals = CP_TYPE_QUALS (t);
+      if (quals != TYPE_UNQUALIFIED)
+       {
+         fprintf (di->stream, "qual: %c%c%c     ",
+                  (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
+                  (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
+                  (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
+         di->column += 14;
+       }
+
+      /* All types have associated declarations.  */
+      dump_child ("name", TYPE_NAME (t));
+
+      if (dump_children_p)
+       {
+         /* All types have a main variant.  */
+         if (TYPE_MAIN_VARIANT (t) != t)
+           dump_child ("unql", TYPE_MAIN_VARIANT (t));
+      
+         /* And sizes.  */
+         dump_child ("size", TYPE_SIZE (t));
+       }
+
+      /* All types have alignments.  */
+      dump_int (di, "algn", TYPE_ALIGN (t));
+    }
+
+  /* Now handle the various kinds of nodes.  */
+  switch (code)
+    {
+      int i;
+
+    case IDENTIFIER_NODE:
+      if (IDENTIFIER_OPNAME_P (t))
+       dump_string (di, "operator");
+      else if (IDENTIFIER_TYPENAME_P (t))
+       queue_and_dump_index (di, "tynm", TREE_TYPE (t), 0);
+      else if (t == anonymous_namespace_name)
+       dump_string (di, "unnamed");
+      else
+       {
+         dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
+         dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
+       }
+      break;
+
+    case TREE_LIST:
+      if (dump_children_p)
+       {
+         dump_child ("purp", TREE_PURPOSE (t));
+         dump_child ("valu", TREE_VALUE (t));
+         dump_child ("chan", TREE_CHAIN (t));
+       }
+      break;
+
+    case TREE_VEC:
+      dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
+      if (dump_children_p)
+       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
+         {
+           char buffer[32];
+           sprintf (buffer, "%u", i);
+           queue_and_dump_index (di, buffer, TREE_VEC_ELT (t, i), 1);
+         }
+      break;
+
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+      dump_int (di, "prec", TYPE_PRECISION (t));
+      if (TREE_UNSIGNED (t))
+       dump_string (di, "unsigned");
+      if (dump_children_p)
+       {
+         dump_child ("min", TYPE_MIN_VALUE (t));
+         dump_child ("max", TYPE_MAX_VALUE (t));
+       }
+
+      if (code == ENUMERAL_TYPE && dump_children_p)
+       dump_child ("csts", TYPE_VALUES (t));
+      break;
+
+    case REAL_TYPE:
+      dump_int (di, "prec", TYPE_PRECISION (t));
+      break;
+
+    case POINTER_TYPE:
+      if (dump_children_p)
+       {
+         if (TYPE_PTRMEM_P (t))
+           {
+             dump_string (di, "ptrmem");
+             queue_and_dump_index (di, "ptd", 
+                                   TYPE_PTRMEM_POINTED_TO_TYPE (t), 1);
+             queue_and_dump_index (di, "cls", 
+                                   TYPE_PTRMEM_CLASS_TYPE (t), 1);
+           }
+         else
+           dump_child ("ptd", TREE_TYPE (t));
+       }
+      break;
+
+    case REFERENCE_TYPE:
+      if (dump_children_p)
+       dump_child ("refd", TREE_TYPE (t));
+      break;
+
+    case METHOD_TYPE:
+      if (dump_children_p)
+       dump_child ("clas", TYPE_METHOD_BASETYPE (t));
+      /* Fall through.  */
+
+    case FUNCTION_TYPE:
+      if (dump_children_p)
+       {
+         dump_child ("retn", TREE_TYPE (t));
+         dump_child ("prms", TYPE_ARG_TYPES (t));
+       }
+      break;
+
+    case ARRAY_TYPE:
+      if (dump_children_p)
+       {
+         dump_child ("elts", TREE_TYPE (t));
+         dump_child ("domn", TYPE_DOMAIN (t));
+       }
+      break;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (TYPE_PTRMEMFUNC_P (t))
+       {
+         dump_string (di, "ptrmem");
+         queue_and_dump_index (di, "ptd", 
+                               TYPE_PTRMEM_POINTED_TO_TYPE (t), 1);
+         queue_and_dump_index (di, "cls", 
+                               TYPE_PTRMEM_CLASS_TYPE (t), 1);
+       }
+      else
+       {
+         if (CLASSTYPE_DECLARED_CLASS (t))
+           dump_string (di, "class");
+         else if (TREE_CODE (t) == RECORD_TYPE)
+           dump_string (di, "struct");
+         else
+           dump_string (di, "union");
+
+         if (dump_children_p)
+           {
+             dump_child ("flds", TYPE_FIELDS (t));
+             dump_child ("fncs", TYPE_METHODS (t));
+             queue_and_dump_index (di, "binf", TYPE_BINFO (t), 
+                                   DUMP_CHILDREN | DUMP_BINFO);
+           }
+       }
+      break;
+
+    case CONST_DECL:
+      if (dump_children_p)
+       dump_child ("cnst", DECL_INITIAL (t));
+      break;
+
+    case VAR_DECL:
+    case PARM_DECL:
+    case FIELD_DECL:
+      if (dump_children_p)
+       {
+         dump_child ("init", DECL_INITIAL (t));
+         dump_child ("size", DECL_SIZE (t));
+       }
+      dump_int (di, "algn", DECL_ALIGN (t));
+
+      if (TREE_CODE (t) == FIELD_DECL && dump_children_p)
+       dump_child ("bpos", DECL_FIELD_BITPOS (t));
+      break;
+
+    case FUNCTION_DECL:
+      if (dump_children_p)
+       {
+         queue_and_dump_index (di, "scpe", DECL_REAL_CONTEXT (t), 0);
+         dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
+         dump_child ("args", DECL_ARGUMENTS (t));
+       }
+      if (TREE_PUBLIC (t))
+       dump_string(di, "extern");
+      else
+       dump_string (di, "static");
+      if (DECL_FUNCTION_MEMBER_P (t))
+       dump_string (di, "member");
+      if (DECL_CONSTRUCTOR_P (t))
+       dump_string (di, "constructor");
+      if (DECL_DESTRUCTOR_P (t))
+       dump_string (di, "destructor");
+      if (DECL_OVERLOADED_OPERATOR_P (t))
+       dump_string (di, "operator");
+      if (DECL_CONV_FN_P (t))
+       dump_string (di, "conversion");
+      if (dump_children_p)
+       dump_child ("body", DECL_INITIAL (t));
+      break;
+
+    case NAMESPACE_DECL:
+      /* The fake `::std' namespace does not have DECL_LANG_SPECIFIC,
+        and therefore many other macros do not work on it.  */
+      if (t == std_node)
+       break;
+      if (dump_children_p)
+       dump_child ("dcls", cp_namespace_decls (t));
+      break;
+
+    case OVERLOAD:
+      if (dump_children_p)
+       {
+         dump_child ("crnt", OVL_CURRENT (t));
+         dump_child ("chan", OVL_CHAIN (t));
+       }
+      break;
+
+    case ASM_STMT:
+      dump_stmt (di, t);
+      if (ASM_VOLATILE_P (t))
+       dump_string (di, "volatile");
+      if (dump_children_p)
+       {
+         dump_child ("strg", ASM_STRING (t));
+         dump_child ("outs", ASM_OUTPUTS (t));
+         dump_child ("ins", ASM_INPUTS (t));
+         dump_child ("clbr", ASM_CLOBBERS (t));
+       }
+      break;
+
+    case BREAK_STMT:
+    case CONTINUE_STMT:
+      dump_stmt (di, t);
+      break;
+
+    case CASE_LABEL:
+      /* Note that a case label is not like other statments; there is
+        no way to get the line-number of a case label.  */
+      if (dump_children_p)
+       {
+         dump_child ("low", CASE_LOW (t));
+         dump_child ("high", CASE_HIGH (t));
+       }
+      break;
+
+    case COMPOUND_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       dump_child ("body", COMPOUND_BODY (t));
+      break;
+
+    case DECL_STMT:
+      dump_stmt (di, t);
+#if 0
+      /* We do not yet have DECL_STMT_DECL; there are declarators and
+        such hanging about in DECL_STMTs.  */
+      if (dump_children_p)
+       dump_child ("decl", DECL_STMT_DECL (t));
+#endif
+      break;
+      
+    case DO_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       {
+         dump_child ("body", DO_BODY (t));
+         dump_child ("cond", DO_COND (t));
+       }
+      break;
+
+    case EXPR_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       dump_child ("expr", EXPR_STMT_EXPR (t));
+      break;
+
+    case FOR_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       {
+         dump_child ("init", FOR_INIT_STMT (t));
+         dump_child ("cond", FOR_COND (t));
+         dump_child ("expr", FOR_EXPR (t));
+         dump_child ("body", FOR_BODY (t));
+       }
+      break;
+
+    case GOTO_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       dump_child ("dest", GOTO_DESTINATION (t));
+      break;
+
+    case IF_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       {
+         dump_child ("cond", IF_COND (t));
+         dump_child ("then", THEN_CLAUSE (t));
+         dump_child ("else", ELSE_CLAUSE (t));
+       }
+      break;
+
+    case RETURN_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       dump_child ("expr", RETURN_EXPR (t));
+      break;
+
+    case SWITCH_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       {
+         dump_child ("cond", SWITCH_COND (t));
+         dump_child ("body", SWITCH_BODY (t));
+       }
+      break;
+
+    case TRY_BLOCK:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       {
+         dump_child ("body", TRY_STMTS (t));
+         dump_child ("hdlr", TRY_HANDLERS (t));
+       }
+      break;
+
+    case WHILE_STMT:
+      dump_stmt (di, t);
+      if (dump_children_p)
+       {
+         dump_child ("cond", WHILE_COND (t));
+         dump_child ("body", WHILE_BODY (t));
+       }
+      break;
+
+    case INTEGER_CST:
+      if (TREE_INT_CST_HIGH (t))
+       dump_int (di, "high", TREE_INT_CST_HIGH (t));
+      dump_int (di, "low", TREE_INT_CST_LOW (t));
+      break;
+
+    case STRING_CST:
+      fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
+      dump_int (di, "lngt", TREE_STRING_LENGTH (t));
+      break;
+
+    case PTRMEM_CST:
+      if (dump_children_p)
+       {
+         dump_child ("clas", PTRMEM_CST_CLASS (t));
+         dump_child ("mbr", PTRMEM_CST_MEMBER (t));
+       }
+      break;
+
+    case TRUTH_NOT_EXPR:
+    case ADDR_EXPR:
+    case INDIRECT_REF:
+    case THROW_EXPR:
+      /* These nodes are unary, but do not have code class `1'.  */
+      if (dump_children_p)
+       dump_child ("op 0", TREE_OPERAND (t, 0));
+      break;
+
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case MODIFY_EXPR:
+    case COMPONENT_REF:
+    case COMPOUND_EXPR:
+    case COND_EXPR:
+      /* These nodes are binary, but do not have code class `2'.  */
+      if (dump_children_p)
+       {
+         dump_child ("op 0", TREE_OPERAND (t, 0));
+         dump_child ("op 1", TREE_OPERAND (t, 1));
+       }
+      break;
+
+    case CALL_EXPR:
+      if (dump_children_p)
+       {
+         dump_child ("fn", TREE_OPERAND (t, 0));
+         dump_child ("args", TREE_OPERAND (t, 1));
+       }
+      break;
+
+    case CONSTRUCTOR:
+      if (dump_children_p)
+       dump_child ("elts", TREE_OPERAND (t, 1));
+      break;
+
+    default:
+      /* There are no additional fields to print.  */
+      break;
+    }
+
+ done:
+  /* Terminate the line.  */
+  fprintf (di->stream, "\n");
+}
+
+/* Dump T, and all its children, on STREAM.  */
+
+static void
+dump_node (t, stream)
+     tree t;
+     FILE *stream;
+{
+  struct dump_info di;
+  dump_queue_p dq;
+  dump_queue_p next_dq;
+
+  /* Initialize the dump-information structure.  */
+  di.stream = stream;
+  di.index = 0;
+  di.column = 0;
+  di.queue = 0;
+  di.queue_end = 0;
+  di.free_list = 0;
+  di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
+                            (splay_tree_delete_value_fn) &free);
+
+  /* Queue up the first node.  */
+  queue (&di, t, DUMP_CHILDREN);
+
+  /* Until the queue is empty, keep dumping nodes.  */
+  while (di.queue)
+    dequeue_and_dump (&di);
+
+  /* Now, clean up.  */
+  for (dq = di.free_list; dq; dq = next_dq)
+    {
+      next_dq = dq->next;
+      free (dq);
+    }
+  splay_tree_delete (di.nodes);
+}
+
+/* Dump T, and all its children, to FILE.  */
+
+void
+dump_node_to_file (t, file)
+     tree t;
+     char *file;
+{
+  FILE *f;
+
+  f = fopen (file, "w");
+  if (!f)
+    cp_error ("could not open `%s'", file);
+  else
+    {
+      dump_node (t, f);
+      fclose (f);
+    }
+}
index cfc64564028f965eb822801e436f7546f6e52699..e9199656667312cbb3aaf85207f36540b8f9b068 100644 (file)
@@ -38,6 +38,7 @@ DEFINE_LANG_NAME ("C++")
   { "-fconst-strings", "" },
   { "-fno-const-strings", "Make string literals `char[]' instead of `const char[]'" },
   { "-fdefault-inline", "" },
+  { "-fdump-translation-unit-", "Dump the entire translation unit to a file"},
   { "-fno-default-inline", "Do not inline member functions by default"},
   { "-frtti", "" },
   { "-fno-rtti", "Do not generate run time type descriptor information" },
index a8477552b7864fba2634fdf2c209366810a17940..4e9b4120040e31cd2db9149cde6dbc7230e59a57 100644 (file)
@@ -5307,8 +5307,8 @@ tsubst_template_parms (parms, args, complain)
      tree args;
      int complain;
 {
-  tree r;
-  tree* new_parms = &r;
+  tree r = NULL_TREE;
+  tree* new_parms;
 
   for (new_parms = &r;
        TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
@@ -5822,7 +5822,7 @@ tsubst_decl (t, args, type, in_decl)
            maybe_retrofit_in_chrg (r);
            grok_ctor_properties (ctx, r);
          }
-       if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+       else if (DECL_OVERLOADED_OPERATOR_P (r))
          grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
       }
       break;
@@ -7077,13 +7077,13 @@ tsubst_expr (t, args, complain, in_decl)
   switch (TREE_CODE (t))
     {
     case RETURN_STMT:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
                                       args, complain, in_decl));
       break;
 
     case EXPR_STMT:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
                                     args, complain, in_decl));
       break;
@@ -7093,7 +7093,7 @@ tsubst_expr (t, args, complain, in_decl)
        int i = suspend_momentary ();
        tree dcl, init;
 
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
        emit_line_note (input_filename, lineno);
        dcl = start_decl
          (tsubst (TREE_OPERAND (t, 0), args, complain, in_decl),
@@ -7109,7 +7109,7 @@ tsubst_expr (t, args, complain, in_decl)
     case FOR_STMT:
       {
        tree tmp;
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
 
        begin_for_stmt ();
        for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
@@ -7127,7 +7127,7 @@ tsubst_expr (t, args, complain, in_decl)
 
     case WHILE_STMT:
       {
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
        begin_while_stmt ();
        finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
                                             args, complain, in_decl),
@@ -7139,7 +7139,7 @@ tsubst_expr (t, args, complain, in_decl)
 
     case DO_STMT:
       {
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
        begin_do_stmt ();
        tsubst_expr (DO_BODY (t), args, complain, in_decl);
        finish_do_body (NULL_TREE);
@@ -7153,7 +7153,7 @@ tsubst_expr (t, args, complain, in_decl)
       {
        tree tmp;
 
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
        begin_if_stmt ();
        finish_if_stmt_cond (tsubst_expr (IF_COND (t),
                                          args, complain, in_decl),
@@ -7180,7 +7180,7 @@ tsubst_expr (t, args, complain, in_decl)
       {
        tree substmt;
 
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
        begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
        for (substmt = COMPOUND_BODY (t); 
             substmt != NULL_TREE;
@@ -7192,12 +7192,12 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case BREAK_STMT:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       finish_break_stmt ();
       break;
 
     case CONTINUE_STMT:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       finish_continue_stmt ();
       break;
 
@@ -7205,7 +7205,7 @@ tsubst_expr (t, args, complain, in_decl)
       {
        tree val, tmp;
 
-       lineno = TREE_COMPLEXITY (t);
+       lineno = STMT_LINENO (t);
        begin_switch_stmt ();
        val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
        finish_switch_cond (val);
@@ -7230,7 +7230,7 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case GOTO_STMT:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       t = GOTO_DESTINATION (t);
       if (TREE_CODE (t) != IDENTIFIER_NODE)
        /* Computed goto's must be tsubst'd into.  On the other hand,
@@ -7241,7 +7241,7 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case ASM_STMT:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       finish_asm_stmt (ASM_CV_QUAL (t),
                       tsubst_expr (ASM_STRING (t), args, complain, in_decl),
                       tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
@@ -7251,7 +7251,7 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case TRY_BLOCK:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       begin_try_block ();
       tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
       finish_try_block (NULL_TREE);
@@ -7264,7 +7264,7 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case HANDLER:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       begin_handler ();
       if (HANDLER_PARMS (t))
        {
@@ -7281,7 +7281,7 @@ tsubst_expr (t, args, complain, in_decl)
       break;
 
     case TAG_DEFN:
-      lineno = TREE_COMPLEXITY (t);
+      lineno = STMT_LINENO (t);
       t = TREE_TYPE (t);
       if (TREE_CODE (t) == ENUMERAL_TYPE)
        tsubst (t, args, complain, NULL_TREE);
index b66efdfebc7f58f5fcb3a7499280a0f0a880a90f..18575ee1d475f5d78c1577220be4f810accf9ea3 100644 (file)
@@ -741,6 +741,14 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
        pop_obstacks ();
     }
 
+  if (cv_qualifier != NULL_TREE
+      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
+    {
+      cp_warning ("%s qualifier ignored on asm",
+                 IDENTIFIER_POINTER (cv_qualifier));
+      cv_qualifier = NULL_TREE;
+    }
+
   if (processing_template_decl)
     {
       tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
@@ -756,30 +764,17 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
        {
          tree t;
 
-         if (cv_qualifier != NULL_TREE
-             && cv_qualifier != ridpointers[(int) RID_VOLATILE])
-           cp_warning ("%s qualifier ignored on asm",
-                       IDENTIFIER_POINTER (cv_qualifier));
-
          for (t = input_operands; t; t = TREE_CHAIN (t))
            TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
 
          c_expand_asm_operands (string, output_operands,
                                 input_operands, 
                                 clobbers,
-                                cv_qualifier 
-                                == ridpointers[(int) RID_VOLATILE],
+                                cv_qualifier != NULL_TREE,
                                 input_filename, lineno);
        }
       else
-       {
-         /* Don't warn about redundant specification of 'volatile' here.  */
-         if (cv_qualifier != NULL_TREE
-             && cv_qualifier != ridpointers[(int) RID_VOLATILE])
-           cp_warning ("%s qualifier ignored on asm",
-                       IDENTIFIER_POINTER (cv_qualifier));
-         expand_asm (string);
-       }
+       expand_asm (string);
       
       finish_stmt ();
     }
index 692f7537ae32b3560711797927ad9a98054ec912..69be85b7837dc526b41aa5270426af935a0bb100 100644 (file)
@@ -139,8 +139,8 @@ in the following sections.
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @smallexample
--a  -ax  -d@var{letters}  -fdump-unnumbered -fpretend-float
--fprofile-arcs  -ftest-coverage
+-a  -ax  -d@var{letters}  -fdump-unnumbered -fdump-translation-unit-@var{file}
+-fpretend-float -fprofile-arcs  -ftest-coverage
 -g  -g@var{level}  -gcoff  -gdwarf  -gdwarf-1  -gdwarf-1+  -gdwarf-2
 -ggdb  -gstabs  -gstabs+  -gxcoff  -gxcoff+
 -p  -pg  -print-file-name=@var{library}  -print-libgcc-file-name
@@ -2120,6 +2120,10 @@ numbers and line number note output.  This makes it more feasible to
 use diff on debugging dumps for compiler invokations with different
 options, in particular with and without -g.
 
+@item -fdump-translation-unit-@var{file} (C++ only)
+Dump a representation of the tree structure for the entire translation
+unit to @var{file}.
+
 @item -fpretend-float
 When running a cross-compiler, pretend that the target machine uses the
 same floating point format as the host machine.  This causes incorrect