[pph] Add flag -fpph-include-tree (issue5376093)

Diego Novillo dnovillo@google.com
Mon Nov 14 17:35:00 GMT 2011


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



More information about the Gcc-patches mailing list