This patch is an enhanced variant of -H. It prints more information about the included files. I'm using it as input to a tool to automatically generate PPH mappings for large TUs.
I don't think this will survive for long, but it is useful for now. Tested on x86_64. Committed to branch. Diego. * c.opt (fpph-include-tree): New. (fpph-logfile, fpph-map): Tidy. cp/ChangeLog.pph * parser.c (c_parse_file): Call pph_init_include_tree. * pph.c (pph_init_include_tree): New. (flatten_name): New. (pph_file_change_handler): New. (pph_include_handler_for_map): New. (pph_init_map_file): New. (pph_finish_map_file): New. * pph.h (pph_init_include_tree): New. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index d10fd7a..62ad01c 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -961,13 +961,17 @@ C++ Joined MissingArgError(missing filename after %qs) -fpph-hdr=<base-name> A mapping from <base-name>.h to <base-name>.pph fpph-logfile= -C++ Joined RejectNegative Var(flag_pph_logfile) +C++ Joined RejectNegative MissingArgError(missing filename after %qs) Var(flag_pph_logfile) -fpph-logfile=<file-name> Emit PPH debug information to <file-name> fpph-map= -C++ Joined MissingArgError(missing filename after %qs) +C++ Joined RejectNegative MissingArgError(missing filename after %qs) Var(flag_pph_map) -fpph-map=<file-name> A file of mappings from #include to PPH file +fpph-include-tree +C++ Var(flag_pph_include_tree) +-fpph-include-tree Print the include tree for the current TU to stderr + fpph-tracer= C++ Joined RejectNegative UInteger Var(flag_pph_tracer) -fpph-tracer Enable tracing of PPH streaming operations diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8947be1..5ee3c74 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -26321,6 +26321,9 @@ c_parse_file (void) if (pph_enabled_p ()) pph_init (); + if (flag_pph_include_tree) + pph_init_include_tree (); + the_parser = cp_parser_new (); push_deferring_access_checks (flag_access_control ? dk_no_deferred : dk_no_check); diff --git a/gcc/cp/pph.c b/gcc/cp/pph.c index 206a7c6..7dc2be3 100644 --- a/gcc/cp/pph.c +++ b/gcc/cp/pph.c @@ -158,7 +158,12 @@ pph_is_valid_here (const char *name, location_t loc) } -/* Record a #include or #include_next for PPH. */ +/* Record a #include or #include_next for PPH. + READER is the main pre-processor object, LOC is the location where + the #include is being emitted from, DNAME is the name of the + #include directive used, NAME is the canonical name of the file being + included, ANGLE_BRACKETS is non-zero if this #include uses <> and + TOK_P is a pointer to the current token being pre-processed. */ static bool pph_include_handler (cpp_reader *reader, @@ -265,3 +270,133 @@ pph_finish (void) if (flag_pph_logfile) fclose (pph_logfile); } + + +/* PPH include tree dumper. Each entry in this file has the format: + + DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME + + Where: + DEPTH is the include depth of the file. + SYSP 1 for a system header + 2 for a C system header that needs 'extern "C"' + 0 otherwise. + DNAME name of the #include directive used. + CANONICAL-NAME is the name of the file as specified by the + #include directive. + FULL-NAME is the full path name where the included file + was found by the pre-processor. + PPH-NAME is the name of the associated PPH file. */ +typedef struct { + /* Name of current #include directive. */ + const unsigned char *dname; + + /* Canonical name of file being included. */ + const char *name; + + /* Previous libcpp #include handler. */ + void (*prev_file_change) (cpp_reader *, const struct line_map *); + + /* Previous libcpp file change handler. */ + bool (*prev_include) (cpp_reader *, source_location, const unsigned char *, + const char *, int, const cpp_token **); +} pph_include_tree_dumper; + +static pph_include_tree_dumper tree_dumper; + + +/* Return a copy of NAME with the characters '/' and '.' replaced with + '_'. The caller is reponsible for freeing the returned string. */ + +static char * +flatten_name (const char *name) +{ + char *str = xstrdup (name); + size_t i; + + for (i = 0; i < strlen (str); i++) + if (str[i] == DIR_SEPARATOR || str[i] == '.') + str[i] = '_'; + + return str; +} + + +/* File change handler for libcpp. READER is the main pre-processor object, + MAP is the line map entry for the file that we are entering into. */ + +static void +pph_file_change_handler (cpp_reader *reader, const struct line_map *map) +{ + char *flat; + + if (tree_dumper.prev_file_change) + tree_dumper.prev_file_change (reader, map); + + /* We are only interested in line maps that describe a new file being + entered. */ + if (map == NULL || map->reason != LC_ENTER) + return; + + /* Emit a line to the map file with the format: + + DEPTH|SYSP|DNAME|CANONICAL-NAME|FULL-NAME|PPH-NAME + */ + flat = flatten_name (map->to_file); + fprintf (stderr, "%d|%d|%s|%s|%s|%s.pph\n", line_table->depth, map->sysp, + tree_dumper.dname, tree_dumper.name, map->to_file, flat); + free (flat); + tree_dumper.dname = NULL; + tree_dumper.name = NULL; +} + + +/* #include handler for libcpp. READER is the main pre-processor object, + LOC is the location where the #include is being emitted from, DNAME + is the name of the #include directive used, NAME is the canonical + name of the file being included, ANGLE_BRACKETS is non-zero if this + #include uses <> and TOK_P is a pointer to the current token being + pre-processed. */ + +static bool +pph_include_handler_for_map (cpp_reader *reader, + location_t loc, + const unsigned char *dname, + const char *name, + int angle_brackets, + const cpp_token **tok_p) +{ + bool retval = true; + + if (tree_dumper.prev_include) + retval &= tree_dumper.prev_include (reader, loc, dname, name, + angle_brackets, tok_p); + tree_dumper.dname = dname; + tree_dumper.name = name; + + return retval; +} + + +/* Initialize the #include tree dumper. */ + +void +pph_init_include_tree (void) +{ + cpp_callbacks *cb; + + memset (&tree_dumper, 0, sizeof (tree_dumper)); + + if (pph_enabled_p ()) + fatal_error ("do not use -fpph-map-gen with any other PPH flag"); + + /* Set up the libcpp handler for file change events. Each event + will generate a new entry in the map file. */ + cb = cpp_get_callbacks (parse_in); + + tree_dumper.prev_file_change = cb->file_change; + cb->file_change = pph_file_change_handler; + + tree_dumper.prev_include = cb->include; + cb->include = pph_include_handler_for_map; +} diff --git a/gcc/cp/pph.h b/gcc/cp/pph.h index 2a346fd..571927d 100644 --- a/gcc/cp/pph.h +++ b/gcc/cp/pph.h @@ -142,6 +142,7 @@ extern void pph_init (void); extern void pph_finish (void); extern void pph_dump_location (FILE *file, location_t loc); extern void pph_dump_tree_name (FILE *file, tree t, int flags); +extern void pph_init_include_tree (void); /* In pph-streamer-out.c. */ extern void pph_out_uint (pph_stream *stream, unsigned int value); -- 1.7.3.1 -- This patch is available for review at http://codereview.appspot.com/5376093