LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-toplevel-name-resolver-2.0.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.4 % 251 232
Test Date: 2026-03-28 14:25:54 Functions: 100.0 % 57 57
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-toplevel-name-resolver-2.0.h"
      20              : #include "input.h"
      21              : #include "optional.h"
      22              : #include "rust-ast-full.h"
      23              : #include "rust-hir-map.h"
      24              : #include "rust-attribute-values.h"
      25              : 
      26              : namespace Rust {
      27              : namespace Resolver2_0 {
      28              : 
      29        14837 : TopLevel::TopLevel (NameResolutionContext &resolver)
      30        14837 :   : DefaultResolver (resolver), dirty (false)
      31        14837 : {}
      32              : 
      33              : template <typename T>
      34              : void
      35         3332 : TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
      36              :                                             const T &node)
      37              : {
      38         3332 :   insert_enum_variant_or_error_out (identifier, node.get_locus (),
      39         3332 :                                     node.get_node_id ());
      40         3332 : }
      41              : 
      42              : void
      43       153312 : TopLevel::check_multiple_insertion_error (
      44              :   tl::expected<NodeId, DuplicateNameError> result, const Identifier &identifier,
      45              :   const location_t &locus, const NodeId node_id)
      46              : {
      47       153312 :   if (result)
      48        45995 :     dirty = true;
      49       107317 :   else if (result.error ().existing != node_id)
      50              :     {
      51           15 :       rich_location rich_loc (line_table, locus);
      52           15 :       rich_loc.add_range (node_locations[result.error ().existing]);
      53              : 
      54           15 :       rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times",
      55           15 :                      identifier.as_string ().c_str ());
      56           15 :     }
      57       153312 : }
      58              : void
      59         3332 : TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
      60              :                                             const location_t &locus,
      61              :                                             const NodeId node_id)
      62              : {
      63              :   // keep track of each node's location to provide useful errors
      64         3332 :   node_locations.emplace (node_id, locus);
      65              : 
      66         3332 :   auto result = ctx.insert_variant (identifier, node_id);
      67         5675 :   check_multiple_insertion_error (result, identifier, locus, node_id);
      68         3332 : }
      69              : 
      70              : template <typename T>
      71              : void
      72       146879 : TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
      73              :                                Namespace ns)
      74              : {
      75       146879 :   insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
      76       146879 : }
      77              : 
      78              : void
      79       149980 : TopLevel::insert_or_error_out (const Identifier &identifier,
      80              :                                const location_t &locus, const NodeId &node_id,
      81              :                                Namespace ns)
      82              : {
      83              :   // keep track of each node's location to provide useful errors
      84       149980 :   node_locations.emplace (node_id, locus);
      85              : 
      86       149980 :   auto result = ctx.insert (identifier, node_id, ns);
      87       254954 :   check_multiple_insertion_error (result, identifier, locus, node_id);
      88       149980 : }
      89              : 
      90              : void
      91        14837 : TopLevel::go (AST::Crate &crate)
      92              : {
      93              :   // we do not include builtin types in the top-level definition collector, as
      94              :   // they are not used until `Late`. furthermore, we run this visitor multiple
      95              :   // times in a row in a fixed-point fashion, so it would make the code
      96              :   // responsible for this ugly and perfom a lot of error checking.
      97              : 
      98        14837 :   visit (crate);
      99              : 
     100        14837 :   if (Analysis::Mappings::get ().lookup_glob_container (crate.get_node_id ())
     101        14837 :       == tl::nullopt)
     102         4522 :     Analysis::Mappings::get ().insert_glob_container (crate.get_node_id (),
     103              :                                                       &crate);
     104        14837 : }
     105              : 
     106              : void
     107         4477 : TopLevel::visit (AST::Module &module)
     108              : {
     109         4477 :   DefaultResolver::visit (module);
     110              : 
     111         4477 :   if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ())
     112         4477 :       == tl::nullopt)
     113         1308 :     Analysis::Mappings::get ().insert_glob_container (module.get_node_id (),
     114              :                                                       &module);
     115         4477 : }
     116              : 
     117              : void
     118        12473 : TopLevel::visit (AST::Trait &trait)
     119              : {
     120        12473 :   insert_or_error_out (trait.get_identifier (), trait, Namespace::Types);
     121              : 
     122        12473 :   DefaultResolver::visit (trait);
     123        12473 : }
     124              : 
     125              : void
     126        19037 : TopLevel::maybe_insert_big_self (AST::Impl &impl)
     127              : {
     128        38074 :   insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
     129        19037 :                        impl.get_type (), Namespace::Types);
     130        19037 : }
     131              : 
     132              : void
     133         2597 : TopLevel::visit (AST::TraitItemType &trait_item)
     134              : {
     135         7791 :   insert_or_error_out (trait_item.get_identifier ().as_string (), trait_item,
     136              :                        Namespace::Types);
     137              : 
     138         2597 :   DefaultResolver::visit (trait_item);
     139         2597 : }
     140              : 
     141              : template <typename PROC_MACRO>
     142              : static void
     143          216 : insert_macros (std::vector<PROC_MACRO> &macros, NameResolutionContext &ctx)
     144              : {
     145          216 :   for (auto &macro : macros)
     146              :     {
     147            0 :       auto res = ctx.macros.insert (macro.get_name (), macro.get_node_id ());
     148              : 
     149            0 :       if (!res && res.error ().existing != macro.get_node_id ())
     150              :         {
     151            0 :           rust_error_at (UNKNOWN_LOCATION, ErrorCode::E0428,
     152              :                          "macro %qs defined multiple times",
     153            0 :                          macro.get_name ().c_str ());
     154              :         }
     155              :     }
     156          216 : }
     157              : 
     158              : void
     159           72 : TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate,
     160              :                               CrateNum num)
     161              : {
     162           72 :   auto &mappings = Analysis::Mappings::get ();
     163              : 
     164           72 :   auto attribute_macros = mappings.lookup_attribute_proc_macros (num);
     165              : 
     166           72 :   auto bang_macros = mappings.lookup_bang_proc_macros (num);
     167              : 
     168           72 :   auto derive_macros = mappings.lookup_derive_proc_macros (num);
     169              : 
     170              :   // TODO: Find a way to keep this part clean without the double dispatch.
     171           72 :   if (derive_macros.has_value ())
     172              :     {
     173           72 :       insert_macros (derive_macros.value (), ctx);
     174           72 :       for (auto &macro : derive_macros.value ())
     175            0 :         mappings.insert_derive_proc_macro_def (macro);
     176              :     }
     177           72 :   if (attribute_macros.has_value ())
     178              :     {
     179           72 :       insert_macros (attribute_macros.value (), ctx);
     180           72 :       for (auto &macro : attribute_macros.value ())
     181            0 :         mappings.insert_attribute_proc_macro_def (macro);
     182              :     }
     183           72 :   if (bang_macros.has_value ())
     184              :     {
     185           72 :       insert_macros (bang_macros.value (), ctx);
     186           72 :       for (auto &macro : bang_macros.value ())
     187            0 :         mappings.insert_bang_proc_macro_def (macro);
     188              :     }
     189              : 
     190           72 :   visit (crate);
     191           72 : }
     192              : 
     193              : static bool
     194         4702 : is_macro_export (AST::MacroRulesDefinition &def)
     195              : {
     196         5167 :   for (const auto &attr : def.get_outer_attrs ())
     197          476 :     if (attr.get_path ().as_string () == Values::Attributes::MACRO_EXPORT)
     198         4702 :       return true;
     199              : 
     200              :   return false;
     201              : }
     202              : 
     203              : void
     204         4702 : TopLevel::visit (AST::MacroRulesDefinition &macro)
     205              : {
     206              :   // we do not insert macros in the current rib as that needs to be done in the
     207              :   // textual scope of the Early pass. we only insert them in the root of the
     208              :   // crate if they are marked with #[macro_export]. The execption to this is
     209              :   // macros 2.0, which get resolved and inserted like regular items.
     210              : 
     211         4702 :   if (is_macro_export (macro))
     212              :     {
     213           33 :       auto res = ctx.macros.insert_at_root (macro.get_rule_name (),
     214           11 :                                             macro.get_node_id ());
     215           11 :       if (!res && res.error ().existing != macro.get_node_id ())
     216              :         {
     217              :           // TODO: Factor this
     218            0 :           rich_location rich_loc (line_table, macro.get_locus ());
     219            0 :           rich_loc.add_range (node_locations[res.error ().existing]);
     220              : 
     221            0 :           rust_error_at (rich_loc, ErrorCode::E0428,
     222              :                          "macro %qs defined multiple times",
     223            0 :                          macro.get_rule_name ().as_string ().c_str ());
     224            0 :         }
     225           11 :     }
     226              : 
     227         4702 :   if (macro.get_kind () == AST::MacroRulesDefinition::MacroKind::DeclMacro)
     228          153 :     insert_or_error_out (macro.get_rule_name (), macro, Namespace::Macros);
     229              : 
     230         4702 :   auto &mappings = Analysis::Mappings::get ();
     231         4702 :   if (mappings.lookup_macro_def (macro.get_node_id ()))
     232              :     return;
     233              : 
     234          971 :   mappings.insert_macro_def (&macro);
     235              : }
     236              : 
     237              : void
     238        62073 : TopLevel::visit (AST::Function &function)
     239              : {
     240        62073 :   insert_or_error_out (function.get_function_name (), function,
     241              :                        Namespace::Values);
     242              : 
     243        62073 :   DefaultResolver::visit (function);
     244        62073 : }
     245              : 
     246              : void
     247          173 : TopLevel::visit (AST::StaticItem &static_item)
     248              : {
     249          173 :   insert_or_error_out (static_item.get_identifier (), static_item,
     250              :                        Namespace::Values);
     251              : 
     252          173 :   DefaultResolver::visit (static_item);
     253          173 : }
     254              : 
     255              : void
     256            3 : TopLevel::visit (AST::ExternalStaticItem &static_item)
     257              : {
     258            9 :   insert_or_error_out (static_item.get_identifier ().as_string (), static_item,
     259              :                        Namespace::Values);
     260              : 
     261            3 :   DefaultResolver::visit (static_item);
     262            3 : }
     263              : 
     264              : void
     265         5042 : TopLevel::visit (AST::StructStruct &struct_item)
     266              : {
     267         5042 :   DefaultResolver::visit (struct_item);
     268              : 
     269         5042 :   insert_or_error_out (struct_item.get_struct_name (), struct_item,
     270              :                        Namespace::Types);
     271              : 
     272              :   // Do we need to insert the constructor in the value namespace as well?
     273              : 
     274              :   // Do we need to do anything if the struct is a unit struct?
     275         5042 :   if (struct_item.is_unit_struct ())
     276         1917 :     insert_or_error_out (struct_item.get_struct_name (), struct_item,
     277              :                          Namespace::Values);
     278         5042 : }
     279              : 
     280              : void
     281        27700 : TopLevel::visit (AST::TypeParam &type_param)
     282              : {
     283        27700 :   insert_or_error_out (type_param.get_type_representation (), type_param,
     284              :                        Namespace::Types);
     285              : 
     286        27700 :   DefaultResolver::visit (type_param);
     287        27700 : }
     288              : 
     289              : void
     290          291 : TopLevel::visit (AST::ConstGenericParam &const_param)
     291              : {
     292          291 :   insert_or_error_out (const_param.get_name (), const_param, Namespace::Values);
     293              : 
     294          291 :   DefaultResolver::visit (const_param);
     295          291 : }
     296              : 
     297              : void
     298         3047 : TopLevel::visit (AST::TupleStruct &tuple_struct)
     299              : {
     300         3047 :   insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
     301              :                        Namespace::Types);
     302              : 
     303         3047 :   insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
     304              :                        Namespace::Values);
     305              : 
     306         3047 :   DefaultResolver::visit (tuple_struct);
     307         3047 : }
     308              : 
     309              : void
     310         1479 : TopLevel::visit (AST::EnumItem &variant)
     311              : {
     312         1479 :   insert_enum_variant_or_error_out (variant.get_identifier (), variant);
     313              : 
     314         1479 :   DefaultResolver::visit (variant);
     315         1479 : }
     316              : 
     317              : void
     318         1550 : TopLevel::visit (AST::EnumItemTuple &variant)
     319              : {
     320         1550 :   insert_enum_variant_or_error_out (variant.get_identifier (), variant);
     321              : 
     322         1550 :   DefaultResolver::visit (variant);
     323         1550 : }
     324              : 
     325              : void
     326          303 : TopLevel::visit (AST::EnumItemStruct &variant)
     327              : {
     328          303 :   insert_enum_variant_or_error_out (variant.get_identifier (), variant);
     329              : 
     330          303 :   DefaultResolver::visit (variant);
     331          303 : }
     332              : 
     333              : void
     334          953 : TopLevel::visit (AST::EnumItemDiscriminant &variant)
     335              : {
     336          953 :   insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
     337              : 
     338          953 :   DefaultResolver::visit (variant);
     339          953 : }
     340              : 
     341              : void
     342         1836 : TopLevel::visit (AST::Enum &enum_item)
     343              : {
     344         1836 :   insert_or_error_out (enum_item.get_identifier (), enum_item,
     345              :                        Namespace::Types);
     346              : 
     347         1836 :   DefaultResolver::visit (enum_item);
     348              : 
     349              :   // Since enums can be containers for imports, we need to insert them like we
     350              :   // do for modules
     351         3672 :   if (Analysis::Mappings::get ().lookup_glob_container (
     352         1836 :         enum_item.get_node_id ())
     353         1836 :       == tl::nullopt)
     354          544 :     Analysis::Mappings::get ().insert_glob_container (enum_item.get_node_id (),
     355              :                                                       &enum_item);
     356         1836 : }
     357              : 
     358              : void
     359          336 : TopLevel::visit (AST::Union &union_item)
     360              : {
     361          336 :   insert_or_error_out (union_item.get_identifier (), union_item,
     362              :                        Namespace::Types);
     363              : 
     364          336 :   DefaultResolver::visit (union_item);
     365          336 : }
     366              : 
     367              : void
     368         1735 : TopLevel::visit (AST::ConstantItem &const_item)
     369              : {
     370         1735 :   if (const_item.get_identifier ().as_string () != Values::Keywords::UNDERSCORE)
     371         1729 :     insert_or_error_out (const_item.get_identifier (), const_item,
     372              :                          Namespace::Values);
     373              : 
     374         1735 :   DefaultResolver::visit (const_item);
     375         1735 : }
     376              : 
     377              : void
     378         4472 : TopLevel::visit (AST::TypeAlias &type_item)
     379              : {
     380         4472 :   insert_or_error_out (type_item.get_new_type_name (), type_item,
     381              :                        Namespace::Types);
     382              : 
     383         4472 :   DefaultResolver::visit (type_item);
     384         4472 : }
     385              : 
     386              : static void flatten_rebind (
     387              :   const AST::UseTreeRebind &glob,
     388              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths);
     389              : 
     390              : static void flatten_list (
     391              :   const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
     392              :   std::vector<AST::SimplePath> &glob_paths,
     393              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
     394              :   NameResolutionContext &ctx);
     395              : static void flatten_glob (const AST::UseTreeGlob &glob,
     396              :                           std::vector<AST::SimplePath> &glob_paths,
     397              :                           NameResolutionContext &ctx);
     398              : 
     399              : static void
     400         4754 : flatten (
     401              :   const AST::UseTree *tree, std::vector<AST::SimplePath> &paths,
     402              :   std::vector<AST::SimplePath> &glob_paths,
     403              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
     404              :   NameResolutionContext &ctx)
     405              : {
     406         4754 :   switch (tree->get_kind ())
     407              :     {
     408         4122 :     case AST::UseTree::Rebind:
     409         4122 :       {
     410         4122 :         auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
     411         4122 :         flatten_rebind (*rebind, rebind_paths);
     412         4122 :         break;
     413              :       }
     414          605 :     case AST::UseTree::List:
     415          605 :       {
     416          605 :         auto list = static_cast<const AST::UseTreeList *> (tree);
     417          605 :         flatten_list (*list, paths, glob_paths, rebind_paths, ctx);
     418          605 :         break;
     419              :       }
     420           27 :     case AST::UseTree::Glob:
     421           27 :       {
     422           27 :         auto glob = static_cast<const AST::UseTreeGlob *> (tree);
     423           27 :         flatten_glob (*glob, glob_paths, ctx);
     424           27 :         break;
     425              :       }
     426              :       break;
     427              :     }
     428         4754 : }
     429              : 
     430              : static void
     431         4122 : flatten_rebind (
     432              :   const AST::UseTreeRebind &rebind,
     433              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths)
     434              : {
     435         4122 :   rebind_paths.emplace_back (rebind.get_path (), rebind);
     436         4122 : }
     437              : 
     438              : /** Prefix a list of subpath
     439              :  * @param prefix A prefix for all subpath
     440              :  * @param subs List of subpath to prefix
     441              :  * @param size List where results should be stored
     442              :  */
     443              : static void
     444         4508 : prefix_subpaths (AST::SimplePath prefix, std::vector<AST::SimplePath> subs,
     445              :                  std::vector<AST::SimplePath> &results)
     446              : {
     447         4508 :   for (auto &sub : subs)
     448              :     {
     449            0 :       auto new_path = prefix;
     450            0 :       std::copy (sub.get_segments ().begin (), sub.get_segments ().end (),
     451              :                  std::back_inserter (new_path.get_segments ()));
     452            0 :       results.emplace_back (new_path);
     453            0 :     }
     454         4508 : }
     455              : 
     456              : static void
     457         2254 : prefix_rebinds (
     458              :   AST::SimplePath prefix,
     459              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> subs,
     460              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &results)
     461              : {
     462         4508 :   for (auto &sub : subs)
     463              :     {
     464         2254 :       auto new_path = prefix;
     465         2254 :       std::copy (sub.first.get_segments ().begin (),
     466         2254 :                  sub.first.get_segments ().end (),
     467              :                  std::back_inserter (new_path.get_segments ()));
     468         4508 :       results.emplace_back (std::make_pair (new_path, sub.second));
     469         2254 :     }
     470         2254 : }
     471              : 
     472              : static void
     473          605 : flatten_list (
     474              :   const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths,
     475              :   std::vector<AST::SimplePath> &glob_paths,
     476              :   std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
     477              :   NameResolutionContext &ctx)
     478              : {
     479          605 :   auto prefix = AST::SimplePath::create_empty ();
     480          605 :   if (list.has_path ())
     481          601 :     prefix = list.get_path ();
     482              : 
     483         2859 :   for (const auto &tree : list.get_trees ())
     484              :     {
     485         2254 :       auto sub_paths = std::vector<AST::SimplePath> ();
     486         2254 :       auto sub_globs = std::vector<AST::SimplePath> ();
     487         2254 :       auto sub_rebinds
     488         2254 :         = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> ();
     489         2254 :       flatten (tree.get (), sub_paths, sub_globs, sub_rebinds, ctx);
     490              : 
     491         2254 :       prefix_subpaths (prefix, sub_paths, paths);
     492         2254 :       prefix_subpaths (prefix, sub_globs, glob_paths);
     493         2254 :       prefix_rebinds (prefix, sub_rebinds, rebind_paths);
     494         2254 :     }
     495          605 : }
     496              : 
     497              : static void
     498           27 : flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths,
     499              :               NameResolutionContext &ctx)
     500              : {
     501           27 :   if (glob.has_path ())
     502           27 :     paths.emplace_back (glob.get_path ());
     503              :   else
     504            0 :     paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ()));
     505           27 : }
     506              : 
     507              : static bool
     508           27 : has_prelude_import (const std::vector<AST::Attribute> &attributes)
     509              : {
     510           27 :   for (const auto &attr : attributes)
     511            2 :     if (attr.get_path ().as_string () == "prelude_import")
     512           27 :       return true;
     513              : 
     514              :   return false;
     515              : }
     516              : 
     517              : void
     518         2500 : TopLevel::visit (AST::UseDeclaration &use)
     519              : {
     520         2500 :   auto paths = std::vector<AST::SimplePath> ();
     521         2500 :   auto glob_path = std::vector<AST::SimplePath> ();
     522         2500 :   auto rebind_path
     523         2500 :     = std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> ();
     524              : 
     525         2500 :   auto &values_rib = ctx.values.peek ();
     526         2500 :   auto &types_rib = ctx.types.peek ();
     527         2500 :   auto &macros_rib = ctx.macros.peek ();
     528              : 
     529              :   // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup?
     530              :   // How do we handle module imports in general? Should they get added to all
     531              :   // namespaces?
     532              : 
     533         2500 :   const auto &tree = use.get_tree ();
     534         2500 :   flatten (tree.get (), paths, glob_path, rebind_path, this->ctx);
     535              : 
     536         2500 :   auto imports = std::vector<ImportKind> ();
     537              : 
     538         2500 :   for (auto &&path : paths)
     539            0 :     imports.emplace_back (
     540            0 :       ImportKind::Simple (std::move (path), values_rib, types_rib, macros_rib));
     541              : 
     542         2527 :   for (auto &&glob : glob_path)
     543           54 :     imports.emplace_back (
     544           27 :       ImportKind::Glob (std::move (glob), values_rib, types_rib, macros_rib,
     545           27 :                         has_prelude_import (use.get_outer_attrs ())));
     546              : 
     547         6622 :   for (auto &&rebind : rebind_path)
     548         4122 :     imports.emplace_back (
     549         8244 :       ImportKind::Rebind (std::move (rebind.first), std::move (rebind.second),
     550              :                           values_rib, types_rib, macros_rib));
     551              : 
     552         2500 :   imports_to_resolve.insert ({use.get_node_id (), std::move (imports)});
     553         2500 : }
     554              : 
     555              : } // namespace Resolver2_0
     556              : } // namespace Rust
        

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.