A comment on IRC yesterday made me think it shouldn't be too hard to give more insight into constexpr evaluation in the form of a dump, so here's a quick sketch.

This also adds -fdump-lang-tinst for tracing template instantiations.

Thoughts?
Checking c01cef92b1d79175853214f9121f6d98e5cd5030: OK
From 79fee55e07795ba57dd0788fd6bc29907b3a3608 Mon Sep 17 00:00:00 2001
From: Jason Merrill <ja...@redhat.com>
Date: Thu, 17 Apr 2025 16:29:49 -0400
Subject: [PATCH 1/4] c++: add cxx_dump_pretty_printer
To: gcc-patches@gcc.gnu.org

A class to simplify implementation of -fdump-lang-foo with support for
pp_printf using %D and such.

gcc/cp/ChangeLog:

	* cxx-pretty-print.h (class cxx_dump_pretty_printer): New.
	* error.cc (cxx_dump_pretty_printer): Ctor/dtor definitions.
---
 gcc/cp/cp-tree.h | 23 +++++++++++++++++++++++
 gcc/cp/error.cc  | 26 ++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7798efba3db..4107fc971c8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7309,6 +7309,29 @@ extern void cp_check_const_attributes (tree);
 extern void maybe_propagate_warmth_attributes (tree, tree);
 
 /* in error.cc */
+/* A class for pretty-printing to -flang-dump-XXX files.  Used like
+
+   if (cxx_dump_pretty_printer pp {foo_dump_id})
+     {
+       pp_printf (&pp, ...);
+     }
+
+   If the dump is enabled, the pretty printer will open the dump file and
+   attach to it, and flush and close the file on destruction.  */
+
+class cxx_dump_pretty_printer: public pretty_printer
+{
+  int phase;
+  FILE *outf;
+  dump_flags_t flags;
+
+public:
+  cxx_dump_pretty_printer (int phase);
+  operator bool() { return outf != nullptr; }
+  bool has_flag (dump_flags_t f) { return (flags & f); }
+  ~cxx_dump_pretty_printer ();
+};
+
 extern const char *type_as_string		(tree, int);
 extern const char *type_as_string_translate	(tree, int);
 extern const char *decl_as_string		(tree, int);
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 499eb1b15a8..cae27c2fae4 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -194,6 +194,32 @@ class cxx_format_postprocessor : public format_postprocessor
   deferred_printed_type m_type_b;
 };
 
+/* Constructor and destructor for cxx_dump_pretty_printer, defined here to
+   avoid needing to move cxx_format_postprocessor into the header as well.  */
+
+cxx_dump_pretty_printer::
+cxx_dump_pretty_printer (int phase)
+  : phase (phase)
+{
+  outf = dump_begin (phase, &flags);
+  if (outf)
+    {
+      pp_format_decoder (this) = cp_printer;
+      pp_format_postprocessor (this) = new cxx_format_postprocessor ();
+      set_output_stream (outf);
+    }
+}
+
+cxx_dump_pretty_printer::
+~cxx_dump_pretty_printer ()
+{
+  if (outf)
+    {
+      pp_flush (this);
+      dump_end (phase, outf);
+    }
+}
+
 /* Return the in-scope template that's currently being parsed, or
    NULL_TREE otherwise.  */
 
-- 
2.49.0


From b0f9e49791da0d96f9fd1e98ba7678fcf4b31298 Mon Sep 17 00:00:00 2001
From: Jason Merrill <ja...@redhat.com>
Date: Fri, 18 Apr 2025 10:18:49 -0400
Subject: [PATCH 2/4] more-dumps
To: gcc-patches@gcc.gnu.org

---
 gcc/dumpfile.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index 65bd5c549b9..c5d50ffc91f 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -107,7 +107,7 @@ static struct dump_file_info dump_files[TDI_end] =
   DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
   DUMP_FILE_INFO (".profile-report", "profile-report", DK_ipa, 0),
 #define FIRST_AUTO_NUMBERED_DUMP 1
-#define FIRST_ME_AUTO_NUMBERED_DUMP 6
+#define FIRST_ME_AUTO_NUMBERED_DUMP 8
 
   DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
   DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),
-- 
2.49.0


From 37793bea62bfc3afdf68c67e1792a155384655ed Mon Sep 17 00:00:00 2001
From: Jason Merrill <ja...@redhat.com>
Date: Thu, 17 Apr 2025 22:14:54 -0400
Subject: [PATCH 3/4] c++: initial -fdump-lang-constexpr
To: gcc-patches@gcc.gnu.org

gcc/cp/ChangeLog:

	* cp-tree.h (constexpr_dump_id): Declare.
	* constexpr.cc (constexpr_dump_id): Define.
	(cxx_eval_outermost_constant_expr): Dump.
	* cp-objcp-common.cc (cp_register_dumps): Add constexpr.
---
 gcc/cp/cp-tree.h          |  1 +
 gcc/cp/constexpr.cc       | 42 +++++++++++++++++++++++++++++++++++++++
 gcc/cp/cp-objcp-common.cc |  4 ++++
 3 files changed, 47 insertions(+)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4107fc971c8..2d8aff2513d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6810,6 +6810,7 @@ extern int class_dump_id;
 extern int module_dump_id;
 extern int raw_dump_id;
 extern int coro_dump_id;
+extern int constexpr_dump_id;
 
 /* Whether the current context is manifestly constant-evaluated.
    Used by the constexpr machinery to control folding of
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index f56c5c42c82..d593eed2d1a 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -188,6 +188,10 @@ struct constexpr_fundef_hasher : ggc_ptr_hash<constexpr_fundef>
 
 static GTY (()) hash_table<constexpr_fundef_hasher> *constexpr_fundef_table;
 
+/* The handle for -fdump-lang-constexpr.  */
+
+int constexpr_dump_id;
+
 /* Utility function used for managing the constexpr function table.
    Return true if the entries pointed to by P and Q are for the
    same constexpr function.  */
@@ -3278,6 +3282,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
 	result = entry->result (ctx->manifestly_const_eval);
     }
 
+  if (cxx_dump_pretty_printer pp {constexpr_dump_id})
+    {
+      for (int i = call_stack.length (); i > 0; --i)
+	pp_space (&pp);
+      pp_printf (&pp, "evaluating call %E\n", t);
+    }
+
   if (!depth_ok)
     {
       if (!ctx->quiet)
@@ -9215,6 +9226,20 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
 	r = TARGET_EXPR_INITIAL (r);
     }
 
+#if 0
+  if (cxx_dump_pretty_printer pp {constexpr_dump_id})
+    {
+      pp_printf (&pp, "evaluating %qE", r);
+      if (object)
+	pp_printf (&pp, " to initialize %qE", object);
+      if (manifestly_const_eval == mce_true)
+	pp_string (&pp, " (mce)");
+      else if (manifestly_const_eval == mce_unknown)
+	pp_string (&pp, " (mce_unknown)");
+      pp_newline (&pp);
+    }
+#endif
+
   auto_vec<tree, 16> cleanups;
   global_ctx.cleanups = &cleanups;
 
@@ -9330,6 +9355,23 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
 		 && TARGET_EXPR_INITIAL (t) == r))
     should_unshare = false;
 
+  if (cxx_dump_pretty_printer pp {constexpr_dump_id})
+    {
+      if (pp.has_flag (TDF_LINENO))
+	{
+	  const expanded_location el
+	    = expand_location (cp_expr_loc_or_input_loc (t));
+	  pp_printf (&pp, "%s:%d:%d\n", el.file, el.line, el.column);
+	}
+      pp_printf (&pp, "evaluated %qE\n", t);
+      if (non_constant_p)
+	pp_string (&pp, "    non-constant");
+      else if (!constexpr_dtor)
+	pp_printf (&pp, "    to value %qE", r);
+      pp_printf (&pp, "\n    in %d operations", global_ctx.constexpr_ops_count);
+      pp_newline (&pp);
+    }
+
   if (non_constant_p && !allow_non_constant)
     return error_mark_node;
   else if (constexpr_dtor)
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 8336d0bb8f7..cf88b352ad6 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -610,6 +610,10 @@ cp_register_dumps (gcc::dump_manager *dumps)
   module_dump_id = dumps->dump_register
     (".module", "lang-module", "lang-module", DK_lang, OPTGROUP_NONE, false);
 
+  constexpr_dump_id = dumps->dump_register
+    (".constexpr", "lang-constexpr", "lang-constexpr",
+     DK_lang, OPTGROUP_NONE, false);
+
   raw_dump_id = dumps->dump_register
     (".raw", "lang-raw", "lang-raw", DK_lang, OPTGROUP_NONE, false);
   coro_dump_id = dumps->dump_register
-- 
2.49.0


From c01cef92b1d79175853214f9121f6d98e5cd5030 Mon Sep 17 00:00:00 2001
From: Jason Merrill <ja...@redhat.com>
Date: Fri, 18 Apr 2025 09:50:04 -0400
Subject: [PATCH 4/4] c++: add -fdump-lang-tinst
To: gcc-patches@gcc.gnu.org

gcc/cp/ChangeLog:

	* cp-tree.h: Declare tinst_dump_id.
	* cp-objcp-common.cc (cp_register_dumps): Set it.
	* pt.cc (push_tinst_level_loc): Use it.
---
 gcc/cp/cp-tree.h          |  1 +
 gcc/cp/cp-objcp-common.cc |  3 +++
 gcc/cp/pt.cc              | 23 +++++++++++++++++------
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2d8aff2513d..616a235c6f5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6811,6 +6811,7 @@ extern int module_dump_id;
 extern int raw_dump_id;
 extern int coro_dump_id;
 extern int constexpr_dump_id;
+extern int tinst_dump_id;
 
 /* Whether the current context is manifestly constant-evaluated.
    Used by the constexpr machinery to control folding of
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index cf88b352ad6..d505867c543 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -614,6 +614,9 @@ cp_register_dumps (gcc::dump_manager *dumps)
     (".constexpr", "lang-constexpr", "lang-constexpr",
      DK_lang, OPTGROUP_NONE, false);
 
+  tinst_dump_id = dumps->dump_register
+    (".tinst", "lang-tinst", "lang-tinst", DK_lang, OPTGROUP_NONE, false);
+
   raw_dump_id = dumps->dump_register
     (".raw", "lang-raw", "lang-raw", DK_lang, OPTGROUP_NONE, false);
   coro_dump_id = dumps->dump_register
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a71705fd085..a60cd592f41 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11373,6 +11373,7 @@ limit_bad_template_recursion (tree decl)
 static int tinst_depth;
 extern int max_tinst_depth;
 int depth_reached;
+int tinst_dump_id;
 
 static GTY(()) struct tinst_level *last_error_tinst_level;
 
@@ -11406,12 +11407,22 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
       return false;
     }
 
-  /* When not -quiet, dump template instantiations other than functions, since
-     announce_function will take care of those.  */
-  if (!quiet_flag && !targs
-      && TREE_CODE (tldcl) != TREE_LIST
-      && TREE_CODE (tldcl) != FUNCTION_DECL)
-    fprintf (stderr, " %s", decl_as_string (tldcl, TFF_DECL_SPECIFIERS));
+  if (!targs && TREE_CODE (tldcl) != TREE_LIST)
+    {
+      /* When not -quiet, dump template instantiations other than functions,
+	 since announce_function will take care of those.  */
+      if (!quiet_flag
+	  && TREE_CODE (tldcl) != FUNCTION_DECL)
+	fprintf (stderr, " %s", decl_as_string (tldcl, TFF_DECL_SPECIFIERS));
+
+      if (cxx_dump_pretty_printer pp {tinst_dump_id})
+	{
+	  for (int i = 0; i < tinst_depth; ++i)
+	    pp_space (&pp);
+	  pp_printf (&pp, "%D", tldcl);
+	  pp_newline (&pp);
+	}
+    }
 
   new_level = tinst_level_freelist ().alloc ();
   new_level->tldcl = tldcl;
-- 
2.49.0

Reply via email to