https://gcc.gnu.org/g:f59ff19bc3d37f4dd159db541ed4f07efb10fcc8

commit r16-880-gf59ff19bc3d37f4dd159db541ed4f07efb10fcc8
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Apr 18 09:50:04 2025 -0400

    c++: add -fdump-lang-tinst
    
    This patch adds a dump with a trace of template instantiations, indented
    based on the depth of recursive instantiation. -lineno adds the location
    that triggered the instantiation, -details adds non-instantiation
    sbustitutions.
    
    The instantiate_pending_templates change is to avoid a bunch of entries for
    reopening tinst scopes that we then don't instantiate anything with; it also
    seems a bit cleaner this way.
    
    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): Dump it.
            (reopen_tinst_level): Here too.
            (tinst_complete_p): New.
            (instantiate_pending_templates): Don't reopen_tinst_level for
            already-complete instantiations.
    
    gcc/ChangeLog:
    
            * doc/invoke.texi: Move C++ -fdump-lang to C++ section.
            Add -fdump-lang-tinst.

Diff:
---
 gcc/doc/invoke.texi       |  72 ++++++++++++++++++++----------
 gcc/cp/cp-tree.h          |   1 +
 gcc/cp/cp-objcp-common.cc |   2 +
 gcc/cp/pt.cc              | 111 +++++++++++++++++++++++++++++++++++++++-------
 4 files changed, 145 insertions(+), 41 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index fe47ce564873..e3bc833c59bd 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3297,6 +3297,50 @@ Enable support for the C++ coroutines extension 
(experimental).
 Permit the C++ front end to note all candidates during overload resolution
 failure, including when a deleted function is selected.
 
+@item -fdump-lang-
+@itemx -fdump-lang-@var{switch}
+@itemx -fdump-lang-@var{switch}-@var{options}
+@itemx -fdump-lang-@var{switch}-@var{options}=@var{filename}
+Control the dumping of C++-specific information.  The @var{options}
+and @var{filename} portions behave as described in the
+@option{-fdump-tree} option.  The following @var{switch} values are
+accepted:
+
+@table @samp
+@item all
+Enable all of the below.
+
+@opindex fdump-lang-class
+@item class
+Dump class hierarchy information.  Virtual table information is emitted
+unless '@option{slim}' is specified.
+
+@opindex fdump-lang-module
+@item module
+Dump module information.  Options @option{lineno} (locations),
+@option{graph} (reachability), @option{blocks} (clusters),
+@option{uid} (serialization), @option{alias} (mergeable),
+@option{asmname} (Elrond), @option{eh} (mapper) & @option{vops}
+(macros) may provide additional information.
+
+@opindex fdump-lang-raw
+@item raw
+Dump the raw internal tree data.
+
+@opindex fdump-lang-tinst
+@item tinst
+Dump the sequence of template instantiations, indented to show the
+depth of recursion.  The @option{lineno} option adds the source
+location where the instantiation was triggered, and the
+@option{details} option also dumps pre-instantiation substitutions
+such as those performed during template argument deduction.
+
+Lines in the .tinst dump start with @samp{I} for an instantiation,
+@samp{S} for another substitution, and @samp{R[IS]} for the reopened
+context of a deferred instantiation.
+
+@end table
+
 @opindex fno-elide-constructors
 @opindex felide-constructors
 @item -fno-elide-constructors
@@ -20891,30 +20935,10 @@ Dump language-specific information.  The file name is 
made by appending
 @itemx -fdump-lang-@var{switch}-@var{options}=@var{filename}
 Control the dumping of language-specific information.  The @var{options}
 and @var{filename} portions behave as described in the
-@option{-fdump-tree} option.  The following @var{switch} values are
-accepted:
-
-@table @samp
-@item all
-
-Enable all language-specific dumps.
-
-@item class
-Dump class hierarchy information.  Virtual table information is emitted
-unless '@option{slim}' is specified.  This option is applicable to C++ only.
-
-@item module
-Dump module information.  Options @option{lineno} (locations),
-@option{graph} (reachability), @option{blocks} (clusters),
-@option{uid} (serialization), @option{alias} (mergeable),
-@option{asmname} (Elrond), @option{eh} (mapper) & @option{vops}
-(macros) may provide additional information.  This option is
-applicable to C++ only.
-
-@item raw
-Dump the raw internal tree data.  This option is applicable to C++ only.
-
-@end table
+@option{-fdump-tree} option.  @option{-fdump-tree-all} enables all
+language-specific dumps; other options vary with the language.  For
+instance, see @xref{C++ Dialect Options} for the @option{-fdump-lang}
+flags supported by the C++ front-end.
 
 @opindex fdump-passes
 @item -fdump-passes
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7433b8962199..19c0b452d868 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6822,6 +6822,7 @@ extern int class_dump_id;
 extern int module_dump_id;
 extern int raw_dump_id;
 extern int coro_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 8336d0bb8f7c..7665b9454dc5 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -614,6 +614,8 @@ cp_register_dumps (gcc::dump_manager *dumps)
     (".raw", "lang-raw", "lang-raw", DK_lang, OPTGROUP_NONE, false);
   coro_dump_id = dumps->dump_register
     (".coro", "lang-coro", "lang-coro", DK_lang, OPTGROUP_NONE, false);
+  tinst_dump_id = dumps->dump_register
+    (".tinst", "lang-tinst", "lang-tinst", DK_lang, OPTGROUP_NONE, false);
 }
 
 void
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1973d25b61a0..c687fdc71a3c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11378,6 +11378,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;
 
@@ -11430,6 +11431,40 @@ push_tinst_level_loc (tree tldcl, tree targs, 
location_t loc)
   set_refcount_ptr (new_level->next, current_tinst_level);
   set_refcount_ptr (current_tinst_level, new_level);
 
+  if (cxx_dump_pretty_printer pp {tinst_dump_id})
+    {
+#if __GNUC__ >= 10
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+      bool list_p = new_level->list_p ();
+      if (list_p && !pp.has_flag (TDF_DETAILS))
+       /* Skip non-instantiations unless -details.  */;
+      else
+       {
+         if (tinst_depth == 0)
+           pp_newline (&pp);
+         if (loc && pp.has_flag (TDF_LINENO))
+           {
+             for (int i = 0; i < tinst_depth; ++i)
+               pp_space (&pp);
+             const expanded_location el = expand_location (loc);
+             pp_printf (&pp, "%s:%d:%d", el.file, el.line, el.column);
+             pp_newline (&pp);
+           }
+         for (int i = 0; i < tinst_depth; ++i)
+           pp_space (&pp);
+         if (list_p)
+           pp_printf (&pp, "S %S", new_level->get_node ());
+         else
+           pp_printf (&pp, "I %D", tldcl);
+         pp_newline (&pp);
+       }
+#if __GNUC__ >= 10
+#pragma GCC diagnostic pop
+#endif
+    }
+
   ++tinst_depth;
   if (GATHER_STATISTICS && (tinst_depth > depth_reached))
     depth_reached = tinst_depth;
@@ -11481,6 +11516,20 @@ pop_tinst_level (void)
   --tinst_depth;
 }
 
+/* True if the instantiation represented by LEVEL is complete.  */
+
+static bool
+tinst_complete_p (struct tinst_level *level)
+{
+  gcc_assert (!level->list_p ());
+  tree node = level->get_node ();
+  if (TYPE_P (node))
+    return COMPLETE_TYPE_P (node);
+  else
+    return (DECL_TEMPLATE_INSTANTIATED (node)
+           || DECL_TEMPLATE_SPECIALIZATION (node));
+}
+
 /* We're instantiating a deferred template; restore the template
    instantiation context in which the instantiation was requested, which
    is one step out from LEVEL.  Return the corresponding DECL or TYPE.  */
@@ -11499,6 +11548,38 @@ reopen_tinst_level (struct tinst_level *level)
   if (current_tinst_level && !current_tinst_level->had_errors)
     current_tinst_level->errors = errorcount+sorrycount;
 
+  if (cxx_dump_pretty_printer pp {tinst_dump_id})
+    {
+#if __GNUC__ >= 10
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+      /* Dump the reopened instantiation context.  */
+      t = current_tinst_level;
+      if (!pp.has_flag (TDF_DETAILS))
+       /* Skip non-instantiations unless -details.  */
+       while (t && t->list_p ())
+         t = t->next;
+      if (t)
+       {
+         static tree last_ctx = NULL_TREE;
+         tree ctx = t->get_node ();
+         if (ctx != last_ctx)
+           {
+             last_ctx = ctx;
+             pp_newline (&pp);
+             if (t->list_p ())
+               pp_printf (&pp, "RS %S", ctx);
+             else
+               pp_printf (&pp, "RI %D", ctx);
+             pp_newline (&pp);
+           }
+       }
+#if __GNUC__ >= 10
+#pragma GCC diagnostic pop
+#endif
+    }
+
   tree decl = level->maybe_get_node ();
   if (decl && modules_p ())
     {
@@ -28068,14 +28149,16 @@ instantiate_pending_templates (int retries)
       reconsider = 0;
       while (*t)
        {
-         tree instantiation = reopen_tinst_level ((*t)->tinst);
-         bool complete = false;
+         struct tinst_level *tinst = (*t)->tinst;
+         bool complete = tinst_complete_p (tinst);
 
-         if (limit_bad_template_recursion (instantiation))
-           /* Do nothing.  */;
-         else if (TYPE_P (instantiation))
+         if (!complete)
            {
-             if (!COMPLETE_TYPE_P (instantiation))
+             tree instantiation = reopen_tinst_level (tinst);
+
+             if (limit_bad_template_recursion (instantiation))
+               /* Do nothing.  */;
+             else if (TYPE_P (instantiation))
                {
                  instantiate_class_template (instantiation);
                  if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
@@ -28092,13 +28175,7 @@ instantiate_pending_templates (int retries)
                  if (COMPLETE_TYPE_P (instantiation))
                    reconsider = 1;
                }
-
-             complete = COMPLETE_TYPE_P (instantiation);
-           }
-         else
-           {
-             if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
-                 && !DECL_TEMPLATE_INSTANTIATED (instantiation))
+             else
                {
                  instantiation
                    = instantiate_decl (instantiation,
@@ -28108,8 +28185,10 @@ instantiate_pending_templates (int retries)
                    reconsider = 1;
                }
 
-             complete = (DECL_TEMPLATE_SPECIALIZATION (instantiation)
-                         || DECL_TEMPLATE_INSTANTIATED (instantiation));
+             complete = tinst_complete_p (tinst);
+
+             tinst_depth = 0;
+             set_refcount_ptr (current_tinst_level);
            }
 
          if (complete)
@@ -28126,8 +28205,6 @@ instantiate_pending_templates (int retries)
              last = *t;
              t = &(*t)->next;
            }
-         tinst_depth = 0;
-         set_refcount_ptr (current_tinst_level);
        }
       last_pending_template = last;
     }

Reply via email to