From f71f87f9ebc585a5092659aadc45ab2f12921a2d Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 3 Aug 1999 01:37:47 +0000 Subject: [PATCH] invoke.texi (-fdump-translation-unit): New option. * 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 --- gcc/ChangeLog | 4 + gcc/cp/ChangeLog | 29 ++ gcc/cp/Make-lang.in | 3 +- gcc/cp/Makefile.in | 4 +- gcc/cp/cp-tree.h | 38 +- gcc/cp/decl.c | 13 +- gcc/cp/decl2.c | 17 + gcc/cp/dump.c | 861 ++++++++++++++++++++++++++++++++++++++++++ gcc/cp/lang-options.h | 1 + gcc/cp/pt.c | 38 +- gcc/cp/semantics.c | 25 +- gcc/invoke.texi | 8 +- 12 files changed, 995 insertions(+), 46 deletions(-) create mode 100644 gcc/cp/dump.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58d47e3ca200..6baa3338a665 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +Mon Aug 2 18:29:32 1999 Mark Mitchell + + * invoke.texi (-fdump-translation-unit): New option. + Mon Aug 2 17:10:24 1999 Mark Mitchell * toplev.h (errorcount): Declare. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 759442ac711b..886401a28071 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,32 @@ +1999-08-02 Mark Mitchell + + * 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 * call.c: Include defaults.h instead of expr.h. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 72795da34993..2e681b8194ae 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -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 diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index edd337904461..63f858093805 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -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 # # These exist for maintenance purposes. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e624102bfd1f..c5af6fdc7361 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b60a5eca4645..46708ac1782b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d5125fc61d33..cbc6c23eb9d4 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 index 000000000000..b22565cc7ba4 --- /dev/null +++ b/gcc/cp/dump.c @@ -0,0 +1,861 @@ +/* Tree-dumping functionality for intermediate representation. + Copyright (C) 1999 Free Software Foundation, Inc. + Written by Mark Mitchell + +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); + } +} diff --git a/gcc/cp/lang-options.h b/gcc/cp/lang-options.h index cfc64564028f..e91996566673 100644 --- a/gcc/cp/lang-options.h +++ b/gcc/cp/lang-options.h @@ -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" }, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a8477552b786..4e9b4120040e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b66efdfebc7f..18575ee1d475 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 (); } diff --git a/gcc/invoke.texi b/gcc/invoke.texi index 692f7537ae32..69be85b7837d 100644 --- a/gcc/invoke.texi +++ b/gcc/invoke.texi @@ -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 -- 2.47.2