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