LCOV - code coverage report
Current view: top level - gcc/analyzer - analyzer.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.9 % 213 183
Test Date: 2026-08-22 16:33:35 Functions: 96.2 % 26 25
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Utility functions for the analyzer.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it
       8              : under the terms of the GNU General Public License as published by
       9              : the Free Software Foundation; either version 3, or (at your option)
      10              : any later version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but
      13              : WITHOUT ANY WARRANTY; without even the implied warranty of
      14              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              : General Public License for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "analyzer/common.h"
      22              : 
      23              : #include "tree-pretty-print.h"
      24              : #include "diagnostics/event-id.h"
      25              : #include "tree-dfa.h"
      26              : #include "intl.h"
      27              : 
      28              : #if ENABLE_ANALYZER
      29              : 
      30              : namespace ana {
      31              : 
      32              : bool
      33           65 : printable_expr_p (const_tree expr)
      34              : {
      35           65 :   if (TREE_CODE (expr) == SSA_NAME
      36           65 :       && !SSA_NAME_VAR (expr))
      37           33 :     return false;
      38              : 
      39              :   return true;
      40              : }
      41              : 
      42              : /* Workaround for missing location information for some stmts,
      43              :    which ultimately should be solved by fixing the frontends
      44              :    to provide the locations (TODO).  */
      45              : 
      46              : location_t
      47       137854 : get_stmt_location (const gimple *stmt, function *fun)
      48              : {
      49       137854 :   if (!stmt)
      50              :     return UNKNOWN_LOCATION;
      51       137854 :   if (get_pure_location (stmt->location) == UNKNOWN_LOCATION)
      52              :     {
      53              :       /* Workaround for missing location information for clobber
      54              :          stmts, which seem to lack location information in the C frontend
      55              :          at least.  Created by gimplify_bind_expr, which uses the
      56              :            BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr))
      57              :          but this is never set up when the block is created in
      58              :          c_end_compound_stmt's pop_scope.
      59              :          TODO: fix this missing location information.
      60              : 
      61              :          For now, as a hackish workaround, use the location of the end of
      62              :          the function.  */
      63        12318 :       if (gimple_clobber_p (stmt) && fun)
      64         3439 :         return fun->function_end_locus;
      65              :     }
      66              : 
      67       134415 :   return stmt->location;
      68              : }
      69              : 
      70              : static tree
      71              : fixup_tree_for_diagnostic_1 (tree expr, hash_set<tree> *visited);
      72              : 
      73              : /* Attempt to generate a tree for the LHS of ASSIGN_STMT.
      74              :    VISITED must be non-NULL; it is used to ensure termination.  */
      75              : 
      76              : static tree
      77       436038 : get_diagnostic_tree_for_gassign_1 (const gassign *assign_stmt,
      78              :                                    hash_set<tree> *visited)
      79              : {
      80       436038 :   enum tree_code code = gimple_assign_rhs_code (assign_stmt);
      81              : 
      82              :   /* Reverse the effect of extract_ops_from_tree during
      83              :      gimplification.  */
      84       436038 :   switch (get_gimple_rhs_class (code))
      85              :     {
      86            0 :     default:
      87            0 :     case GIMPLE_INVALID_RHS:
      88            0 :       gcc_unreachable ();
      89       224925 :     case GIMPLE_TERNARY_RHS:
      90       224925 :     case GIMPLE_BINARY_RHS:
      91       224925 :     case GIMPLE_UNARY_RHS:
      92       224925 :       {
      93       224925 :         tree t = make_node (code);
      94       224925 :         TREE_TYPE (t) = TREE_TYPE (gimple_assign_lhs (assign_stmt));
      95       224925 :         unsigned num_rhs_args = gimple_num_ops (assign_stmt) - 1;
      96       586379 :         for (unsigned i = 0; i < num_rhs_args; i++)
      97              :           {
      98       361454 :             tree op = gimple_op (assign_stmt, i + 1);
      99       361454 :             if (op)
     100              :               {
     101       361454 :                 op = fixup_tree_for_diagnostic_1 (op, visited);
     102       361454 :                 if (op == NULL_TREE)
     103              :                   return NULL_TREE;
     104              :               }
     105       361454 :             TREE_OPERAND (t, i) = op;
     106              :           }
     107              :         return t;
     108              :       }
     109       211113 :     case GIMPLE_SINGLE_RHS:
     110       211113 :       {
     111       211113 :         tree op = gimple_op (assign_stmt, 1);
     112       211113 :         op = fixup_tree_for_diagnostic_1 (op, visited);
     113       211113 :         return op;
     114              :       }
     115              :     }
     116              : }
     117              : 
     118              : /*  Subroutine of fixup_tree_for_diagnostic_1, called on SSA names.
     119              :     Attempt to reconstruct a tree expression for SSA_NAME
     120              :     based on its def-stmt.
     121              :     SSA_NAME must be non-NULL.
     122              :     VISITED must be non-NULL; it is used to ensure termination.
     123              : 
     124              :     Return NULL_TREE if there is a problem.  */
     125              : 
     126              : static tree
     127       199330 : maybe_reconstruct_from_def_stmt (tree ssa_name,
     128              :                                  hash_set<tree> *visited)
     129              : {
     130              :   /* Ensure termination.  */
     131       199330 :   if (visited->contains (ssa_name))
     132              :     return NULL_TREE;
     133       199256 :   visited->add (ssa_name);
     134              : 
     135       199256 :   gimple *def_stmt = SSA_NAME_DEF_STMT (ssa_name);
     136              : 
     137       199256 :   switch (gimple_code (def_stmt))
     138              :     {
     139            0 :     default:
     140            0 :       gcc_unreachable ();
     141              :     case GIMPLE_ASM:
     142              :     case GIMPLE_NOP:
     143              :     case GIMPLE_PHI:
     144              :       /* Can't handle these.  */
     145              :       return NULL_TREE;
     146       178718 :     case GIMPLE_ASSIGN:
     147       178718 :       return get_diagnostic_tree_for_gassign_1
     148       178718 :         (as_a <const gassign *> (def_stmt), visited);
     149        18077 :     case GIMPLE_CALL:
     150        18077 :       {
     151        18077 :         gcall *call_stmt = as_a <gcall *> (def_stmt);
     152        18077 :         tree return_type = gimple_call_return_type (call_stmt);
     153        18077 :         tree fn = fixup_tree_for_diagnostic_1 (gimple_call_fn (call_stmt),
     154              :                                                visited);
     155        18077 :         if (fn == NULL_TREE)
     156              :           return NULL_TREE;
     157        17710 :         unsigned num_args = gimple_call_num_args (call_stmt);
     158        17710 :         auto_vec<tree> args (num_args);
     159        58872 :         for (unsigned i = 0; i < num_args; i++)
     160              :           {
     161        23452 :             tree arg = gimple_call_arg (call_stmt, i);
     162        23452 :             arg = fixup_tree_for_diagnostic_1 (arg, visited);
     163        23452 :             if (arg == NULL_TREE)
     164            0 :               return NULL_TREE;
     165        23452 :             args.quick_push (arg);
     166              :           }
     167        17710 :         gcc_assert (fn);
     168        17710 :         return build_call_array_loc (gimple_location (call_stmt),
     169              :                                      return_type, fn,
     170        17710 :                                      num_args, args.address ());
     171        17710 :       }
     172              :       break;
     173              :     }
     174              : }
     175              : 
     176              : /* Subroutine of fixup_tree_for_diagnostic: attempt to fixup EXPR,
     177              :    which can be NULL.
     178              :    VISITED must be non-NULL; it is used to ensure termination.  */
     179              : 
     180              : static tree
     181       642347 : fixup_tree_for_diagnostic_1 (tree expr, hash_set<tree> *visited)
     182              : {
     183       642347 :   if (expr
     184       629509 :       && TREE_CODE (expr) == SSA_NAME
     185       959859 :       && (SSA_NAME_VAR (expr) == NULL_TREE
     186       119354 :           || DECL_ARTIFICIAL (SSA_NAME_VAR (expr))))
     187              :     {
     188       199467 :       if (tree var = SSA_NAME_VAR (expr))
     189         1309 :         if (VAR_P (var) && DECL_HAS_DEBUG_EXPR_P (var))
     190          137 :           return DECL_DEBUG_EXPR (var);
     191       199330 :       if (tree expr2 = maybe_reconstruct_from_def_stmt (expr, visited))
     192       196428 :         return expr2;
     193              :     }
     194              :   return expr;
     195              : }
     196              : 
     197              : /* We don't want to print '<unknown>' in our diagnostics (PR analyzer/99771),
     198              :    but sometimes we generate diagnostics involving an ssa name for a
     199              :    temporary.
     200              : 
     201              :    Work around this by attempting to reconstruct a tree expression for
     202              :    such temporaries based on their def-stmts.
     203              : 
     204              :    Otherwise return EXPR.
     205              : 
     206              :    EXPR can be NULL.  */
     207              : 
     208              : tree
     209        28251 : fixup_tree_for_diagnostic (tree expr)
     210              : {
     211        28251 :   hash_set<tree> visited;
     212        28251 :   return fixup_tree_for_diagnostic_1 (expr, &visited);
     213        28251 : }
     214              : 
     215              : /* Attempt to generate a tree for the LHS of ASSIGN_STMT.  */
     216              : 
     217              : tree
     218       257320 : get_diagnostic_tree_for_gassign (const gassign *assign_stmt)
     219              : {
     220       257320 :   hash_set<tree> visited;
     221       257320 :   return get_diagnostic_tree_for_gassign_1 (assign_stmt, &visited);
     222       257320 : }
     223              : 
     224              : /* Generate a JSON value for NODE, which can be NULL_TREE.
     225              :    This is intended for debugging the analyzer rather than serialization and
     226              :    thus is a string (or null, for NULL_TREE).  */
     227              : 
     228              : std::unique_ptr<json::value>
     229           44 : tree_to_json (tree node)
     230              : {
     231           44 :   if (!node)
     232            0 :     return std::make_unique<json::literal> (json::JSON_NULL);
     233              : 
     234           44 :   pretty_printer pp;
     235           44 :   dump_generic_node (&pp, node, 0, TDF_VOPS|TDF_MEMSYMS, false);
     236           44 :   return std::make_unique<json::string> (pp_formatted_text (&pp));
     237           44 : }
     238              : 
     239              : /* Generate a JSON value for EVENT_ID.
     240              :    This is intended for debugging the analyzer rather than serialization and
     241              :    thus is a string matching those seen in event messages (or null,
     242              :    for unknown).  */
     243              : 
     244              : std::unique_ptr<json::value>
     245          159 : diagnostic_event_id_to_json (const diagnostics::paths::event_id_t &event_id)
     246              : {
     247          159 :   if (event_id.known_p ())
     248              :     {
     249          159 :       pretty_printer pp;
     250          159 :       pp_printf (&pp, "%@", &event_id);
     251          159 :       return std::make_unique<json::string> (pp_formatted_text (&pp));
     252          159 :     }
     253              :   else
     254            0 :     return std::make_unique<json::literal> (json::JSON_NULL);
     255              : }
     256              : 
     257              : /* Generate a JSON value for OFFSET.
     258              :    This is intended for debugging the analyzer rather than serialization and
     259              :    thus is a string.  */
     260              : 
     261              : std::unique_ptr<json::value>
     262            8 : bit_offset_to_json (const bit_offset_t &offset)
     263              : {
     264            8 :   pretty_printer pp;
     265            8 :   pp_wide_int_large (&pp, offset, SIGNED);
     266            8 :   return std::make_unique<json::string> (pp_formatted_text (&pp));
     267            8 : }
     268              : 
     269              : /* Generate a JSON value for OFFSET.
     270              :    This is intended for debugging the analyzer rather than serialization and
     271              :    thus is a string.  */
     272              : 
     273              : std::unique_ptr<json::value>
     274            8 : byte_offset_to_json (const byte_offset_t &offset)
     275              : {
     276            8 :   pretty_printer pp;
     277            8 :   pp_wide_int_large (&pp, offset, SIGNED);
     278            8 :   return std::make_unique<json::string> (pp_formatted_text (&pp));
     279            8 : }
     280              : 
     281              : /* Workaround for lack of const-correctness of ssa_default_def.  */
     282              : 
     283              : tree
     284        42409 : get_ssa_default_def (const function &fun, tree var)
     285              : {
     286        42409 :   return ssa_default_def (const_cast <function *> (&fun), var);
     287              : }
     288              : 
     289              : } // namespace ana
     290              : 
     291              : /* Helper function for checkers.  Is the CALL to the given function name,
     292              :    and with the given number of arguments?
     293              : 
     294              :    This doesn't resolve function pointers via the region model;
     295              :    is_named_call_p should be used instead, using a fndecl from
     296              :    get_fndecl_for_call; this function should only be used for special cases
     297              :    where it's not practical to get at the region model, or for special
     298              :    analyzer functions such as __analyzer_dump.
     299              : 
     300              :    If LOOK_IN_STD is true, then also look for within std:: for the name.  */
     301              : 
     302              : bool
     303       424003 : is_special_named_call_p (const gcall &call, const char *funcname,
     304              :                          unsigned int num_args, bool look_in_std)
     305              : {
     306       424003 :   gcc_assert (funcname);
     307              : 
     308       424003 :   tree fndecl = gimple_call_fndecl (&call);
     309       424003 :   if (!fndecl)
     310              :     return false;
     311              : 
     312       395895 :   if (is_named_call_p (fndecl, funcname, call, num_args))
     313              :     return true;
     314       394319 :   if (look_in_std)
     315            0 :     if (is_std_named_call_p (fndecl, funcname, call, num_args))
     316              :       return true;
     317              :   return false;
     318              : }
     319              : 
     320              : /* Helper function for checkers.  Is FNDECL an extern fndecl at file scope
     321              :    that has the given FUNCNAME?
     322              : 
     323              :    Compare with special_function_p in calls.cc.  */
     324              : 
     325              : bool
     326      1928047 : is_named_call_p (const_tree fndecl, const char *funcname)
     327              : {
     328      1928047 :   gcc_assert (fndecl);
     329      1928047 :   gcc_assert (funcname);
     330              : 
     331      1928047 :   if (!maybe_special_function_p (fndecl))
     332              :     return false;
     333              : 
     334      1876058 :   tree identifier = DECL_NAME (fndecl);
     335      1876058 :   const char *name = IDENTIFIER_POINTER (identifier);
     336      1876058 :   const char *tname = name;
     337              : 
     338              :   /* Potentially disregard prefix _ or __ in FNDECL's name, but not if
     339              :      FUNCNAME itself has leading underscores (e.g. when looking for
     340              :      "__analyzer_eval").  */
     341      1876058 :   if (funcname[0] != '_' && name[0] == '_')
     342              :     {
     343       768661 :       if (name[1] == '_')
     344       764297 :         tname += 2;
     345              :       else
     346         4364 :         tname += 1;
     347              :     }
     348              : 
     349      1876058 :   return 0 == strcmp (tname, funcname);
     350              : }
     351              : 
     352              : /* Return true if FNDECL is declared directly within a top-level
     353              :    namespace named NS_NAME (e.g. "std" or "__cxxabiv1").
     354              :    Compare with cp/typeck.cc: decl_in_std_namespace_p, but this doesn't
     355              :    rely on being the C++ FE (or handle inline namespaces inside of std).  */
     356              : 
     357              : bool
     358       899078 : is_fndecl_in_toplevel_namespace_p (const_tree fndecl, const char *ns_name)
     359              : {
     360       899078 :   tree name_decl = DECL_NAME (fndecl);
     361       899078 :   if (!name_decl)
     362              :     return false;
     363              : 
     364       899078 :   if (!DECL_CONTEXT (fndecl))
     365              :     return false;
     366       891559 :   if (TREE_CODE (DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
     367              :     return false;
     368         3716 :   tree ns = DECL_CONTEXT (fndecl);
     369              :   /* Require the namespace itself to be at top level.  */
     370         3716 :   if (!(DECL_CONTEXT (ns) == NULL_TREE
     371         3706 :         || TREE_CODE (DECL_CONTEXT (ns)) == TRANSLATION_UNIT_DECL))
     372              :     return false;
     373         3620 :   if (!DECL_NAME (ns))
     374              :     return false;
     375              : 
     376         3620 :   return id_equal (ns_name, DECL_NAME (ns));
     377              : }
     378              : 
     379              : /* Return true if FNDECL is within the namespace "std".  */
     380              : 
     381              : bool
     382       553405 : is_std_function_p (const_tree fndecl)
     383              : {
     384       553405 :   return is_fndecl_in_toplevel_namespace_p (fndecl, "std");
     385              : }
     386              : 
     387              : /* Return true if FNDECL is within the namespace "__cxxabiv1".  */
     388              : 
     389              : bool
     390       345673 : is_cxxabi_function_p (const_tree fndecl)
     391              : {
     392       345673 :   return is_fndecl_in_toplevel_namespace_p (fndecl, "__cxxabiv1");
     393              : }
     394              : 
     395              : /* Like is_named_call_p, but look for std::FUNCNAME.  */
     396              : 
     397              : bool
     398       206533 : is_std_named_call_p (const_tree fndecl, const char *funcname)
     399              : {
     400       206533 :   gcc_assert (fndecl);
     401       206533 :   gcc_assert (funcname);
     402              : 
     403       206533 :   if (!is_std_function_p (fndecl))
     404              :     return false;
     405              : 
     406          564 :   tree identifier = DECL_NAME (fndecl);
     407          564 :   const char *name = IDENTIFIER_POINTER (identifier);
     408          564 :   const char *tname = name;
     409              : 
     410              :   /* Don't disregard prefix _ or __ in FNDECL's name.  */
     411              : 
     412          564 :   return 0 == strcmp (tname, funcname);
     413              : }
     414              : 
     415              : /* Helper function for checkers.  Is FNDECL an extern fndecl at file scope
     416              :    that has the given FUNCNAME, and does CALL have the given number of
     417              :    arguments?  */
     418              : 
     419              : bool
     420      1668276 : is_named_call_p (const_tree fndecl, const char *funcname,
     421              :                  const gcall &call, unsigned int num_args)
     422              : {
     423      1668276 :   gcc_assert (fndecl);
     424      1668276 :   gcc_assert (funcname);
     425              : 
     426      1668276 :   if (!is_named_call_p (fndecl, funcname))
     427              :     return false;
     428              : 
     429        20350 :   if (gimple_call_num_args (&call) != num_args)
     430         1228 :     return false;
     431              : 
     432              :   return true;
     433              : }
     434              : 
     435              : /* Like is_named_call_p, but check for std::FUNCNAME.  */
     436              : 
     437              : bool
     438       206462 : is_std_named_call_p (const_tree fndecl, const char *funcname,
     439              :                      const gcall &call, unsigned int num_args)
     440              : {
     441       206462 :   gcc_assert (fndecl);
     442       206462 :   gcc_assert (funcname);
     443              : 
     444       206462 :   if (!is_std_named_call_p (fndecl, funcname))
     445              :     return false;
     446              : 
     447           12 :   if (gimple_call_num_args (&call) != num_args)
     448            0 :     return false;
     449              : 
     450              :   return true;
     451              : }
     452              : 
     453              : bool
     454        44298 : is_cxa_throw_p (const gcall &call)
     455              : {
     456        44298 :   tree fndecl = gimple_call_fndecl (&call);
     457        44298 :   if (!fndecl)
     458              :     return false;
     459              : 
     460        41288 :   return is_named_call_p (fndecl, "__cxa_throw");
     461              : }
     462              : 
     463              : bool
     464        44188 : is_cxa_rethrow_p (const gcall &call)
     465              : {
     466        44188 :   tree fndecl = gimple_call_fndecl (&call);
     467        44188 :   if (!fndecl)
     468              :     return false;
     469              : 
     470        41178 :   return is_named_call_p (fndecl, "__cxa_rethrow");
     471              : }
     472              : 
     473              : bool
     474          526 : is_cxa_end_catch_p (const gcall &call)
     475              : {
     476          526 :   tree fndecl = gimple_call_fndecl (&call);
     477          526 :   if (!fndecl)
     478              :     return false;
     479              : 
     480          514 :   return is_named_call_p (fndecl, "__cxa_end_catch");
     481              : }
     482              : 
     483              : /* For a CALL that matched is_special_named_call_p or is_named_call_p for
     484              :    some name, return a name for the called function suitable for use in
     485              :    diagnostics (stripping the leading underscores).  */
     486              : 
     487              : const char *
     488          133 : get_user_facing_name (const gcall &call)
     489              : {
     490          133 :   tree fndecl = gimple_call_fndecl (&call);
     491          133 :   gcc_assert (fndecl);
     492              : 
     493          133 :   tree identifier = DECL_NAME (fndecl);
     494          133 :   gcc_assert (identifier);
     495              : 
     496          133 :   const char *name = IDENTIFIER_POINTER (identifier);
     497              : 
     498              :   /* Strip prefix _ or __ in FNDECL's name.  */
     499          133 :   if (name[0] == '_')
     500              :     {
     501            0 :       if (name[1] == '_')
     502            0 :         return name + 2;
     503              :       else
     504            0 :         return name + 1;
     505              :     }
     506              : 
     507              :   return name;
     508              : }
     509              : 
     510              : /* Generate a label_text instance by formatting FMT, using a
     511              :    temporary clone of the global_dc's printer (thus using its
     512              :    formatting callbacks).
     513              : 
     514              :    Colorize if the global_dc supports colorization and CAN_COLORIZE is
     515              :    true.  */
     516              : 
     517              : label_text
     518         4126 : make_label_text (bool can_colorize, const char *fmt, ...)
     519              : {
     520         4126 :   std::unique_ptr<pretty_printer> pp (global_dc->clone_printer ());
     521         4126 :   pp_clear_output_area (pp.get ());
     522              : 
     523         4126 :   if (!can_colorize)
     524         4123 :     pp_show_color (pp.get ()) = false;
     525              : 
     526         4126 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     527              : 
     528         4126 :   va_list ap;
     529              : 
     530         4126 :   va_start (ap, fmt);
     531              : 
     532         4126 :   text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
     533         4126 :   pp_format (pp.get (), &ti);
     534         4126 :   pp_output_formatted_text (pp.get ());
     535              : 
     536         4126 :   va_end (ap);
     537              : 
     538         4126 :   label_text result = label_text::take (xstrdup (pp_formatted_text (pp.get ())));
     539         8252 :   return result;
     540         4126 : }
     541              : 
     542              : /* As above, but with singular vs plural.  */
     543              : 
     544              : label_text
     545            0 : make_label_text_n (bool can_colorize, unsigned HOST_WIDE_INT n,
     546              :                    const char *singular_fmt,
     547              :                    const char *plural_fmt, ...)
     548              : {
     549            0 :   std::unique_ptr<pretty_printer> pp (global_dc->clone_printer ());
     550            0 :   pp_clear_output_area (pp.get ());
     551              : 
     552            0 :   if (!can_colorize)
     553            0 :     pp_show_color (pp.get ()) = false;
     554              : 
     555            0 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     556              : 
     557            0 :   va_list ap;
     558              : 
     559            0 :   va_start (ap, plural_fmt);
     560              : 
     561            0 :   const char *fmt = ngettext (singular_fmt, plural_fmt, n);
     562              : 
     563            0 :   text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
     564              : 
     565            0 :   pp_format (pp.get (), &ti);
     566            0 :   pp_output_formatted_text (pp.get ());
     567              : 
     568            0 :   va_end (ap);
     569              : 
     570            0 :   label_text result
     571            0 :     = label_text::take (xstrdup (pp_formatted_text (pp.get ())));
     572            0 :   return result;
     573            0 : }
     574              : 
     575              : #endif /* #if ENABLE_ANALYZER */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.