LCOV - code coverage report
Current view: top level - gcc/rust/resolve - rust-early-name-resolver-2.0.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.6 % 277 240
Test Date: 2026-04-20 14:57:17 Functions: 92.3 % 26 24
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-early-name-resolver-2.0.h"
      20              : #include "optional.h"
      21              : #include "options.h"
      22              : #include "rust-ast.h"
      23              : #include "rust-diagnostics.h"
      24              : #include "rust-hir-map.h"
      25              : #include "rust-item.h"
      26              : #include "rust-toplevel-name-resolver-2.0.h"
      27              : #include "rust-attributes.h"
      28              : #include "rust-finalize-imports-2.0.h"
      29              : #include "rust-attribute-values.h"
      30              : #include "rust-identifier-path.h"
      31              : 
      32              : namespace Rust {
      33              : namespace Resolver2_0 {
      34              : 
      35        10779 : Early::Early (NameResolutionContext &ctx)
      36        10779 :   : DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
      37        10779 : {}
      38              : 
      39              : void
      40         2815 : Early::insert_once (AST::MacroInvocation &invocation, NodeId resolved)
      41              : {
      42              :   // TODO: Should we use `ctx.mark_resolved()`?
      43         2815 :   auto definition = ctx.mappings.lookup_macro_def (resolved);
      44              : 
      45         2815 :   if (!ctx.mappings.lookup_macro_invocation (invocation))
      46         2815 :     ctx.mappings.insert_macro_invocation (invocation, definition.value ());
      47         2815 : }
      48              : 
      49              : void
      50         3800 : Early::insert_once (AST::MacroRulesDefinition &def)
      51              : {
      52              :   // TODO: Should we use `ctx.mark_resolved()`?
      53         3800 :   if (!ctx.mappings.lookup_macro_def (def.get_node_id ()))
      54            1 :     ctx.mappings.insert_macro_def (&def);
      55         3800 : }
      56              : 
      57              : void
      58        10779 : Early::go (AST::Crate &crate)
      59              : {
      60              :   // First we go through TopLevel resolution to get all our declared items
      61        10779 :   toplevel.go (crate);
      62              : 
      63              :   // We start with resolving the list of imports that `TopLevel` has built for
      64              :   // us
      65              : 
      66        10779 :   dirty = toplevel.is_dirty ();
      67              :   // We now proceed with resolving macros, which can be nested in almost any
      68              :   // items
      69        10779 :   textual_scope.push ();
      70              : 
      71        10779 :   visit (crate);
      72              : 
      73        10779 :   textual_scope.pop ();
      74              : 
      75              :   // handle IdentifierPattern vs PathInExpression disambiguation
      76        10779 :   IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
      77        10779 : }
      78              : 
      79              : bool
      80           22 : Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
      81              : {
      82           22 :   auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
      83           22 :   if (!resolved.has_value ())
      84              :     return false;
      85              : 
      86           21 :   auto result = Analysis::Mappings::get ().lookup_glob_container (
      87              :     resolved->get_node_id ());
      88              : 
      89           21 :   if (!result)
      90              :     return false;
      91              : 
      92              :   // here, we insert the module's NodeId into the import_mappings and will look
      93              :   // up the module proper in `FinalizeImports`
      94              :   // The namespace does not matter here since we are dealing with a glob
      95              :   // TODO: Ugly
      96           42 :   import_mappings.insert (use_dec_id,
      97           21 :                           ImportPair (std::move (glob),
      98           63 :                                       ImportData::Glob (*resolved)));
      99              : 
     100           21 :   return true;
     101           22 : }
     102              : 
     103              : bool
     104            0 : Early::resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind &&import)
     105              : {
     106            0 :   auto definitions = resolve_path_in_all_ns (import.to_resolve);
     107              : 
     108              :   // if we've found at least one definition, then we're good
     109            0 :   if (definitions.empty ())
     110              :     return false;
     111              : 
     112            0 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     113              : 
     114            0 :   imports.emplace_back (
     115            0 :     ImportPair (std::move (import),
     116            0 :                 ImportData::Simple (std::move (definitions))));
     117              : 
     118            0 :   return true;
     119            0 : }
     120              : 
     121              : bool
     122         3055 : Early::resolve_rebind_import (NodeId use_dec_id,
     123              :                               TopLevel::ImportKind &&rebind_import)
     124              : {
     125         3055 :   auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
     126              : 
     127              :   // if we've found at least one definition, then we're good
     128         3055 :   if (definitions.empty ())
     129              :     return false;
     130         6601 :   for (const auto &def : definitions)
     131              :     {
     132         3558 :       if (def.first.is_ambiguous ())
     133              :         {
     134            1 :           rich_location rich_locus (line_table,
     135            1 :                                     rebind_import.to_resolve.get_locus ());
     136            1 :           rust_error_at (rich_locus, ErrorCode::E0659, "%qs is ambiguous",
     137            1 :                          rebind_import.to_resolve.as_string ().c_str ());
     138            1 :           return true;
     139            1 :         }
     140              :     }
     141              : 
     142         3043 :   auto &imports = import_mappings.new_or_access (use_dec_id);
     143              : 
     144         3043 :   imports.emplace_back (
     145         3043 :     ImportPair (std::move (rebind_import),
     146         6086 :                 ImportData::Rebind (std::move (definitions))));
     147              : 
     148         3043 :   return true;
     149         3055 : }
     150              : 
     151              : void
     152         1850 : Early::build_import_mapping (
     153              :   std::pair<NodeId, std::vector<TopLevel::ImportKind>> &&use_import)
     154              : {
     155         1850 :   auto found = false;
     156         1850 :   auto use_dec_id = use_import.first;
     157              : 
     158         4927 :   for (auto &&import : use_import.second)
     159              :     {
     160              :       // We create a copy of the path in case of errors, since the `import` will
     161              :       // be moved into the newly created import mappings
     162         3077 :       auto path = import.to_resolve;
     163              : 
     164              :       // used to skip the "unresolved import" error
     165              :       // if we output other errors during resolution
     166         3077 :       size_t old_error_count = macro_resolve_errors.size ();
     167              : 
     168         3077 :       switch (import.kind)
     169              :         {
     170           22 :         case TopLevel::ImportKind::Kind::Glob:
     171           22 :           found = resolve_glob_import (use_dec_id, std::move (import));
     172           22 :           break;
     173            0 :         case TopLevel::ImportKind::Kind::Simple:
     174            0 :           found = resolve_simple_import (use_dec_id, std::move (import));
     175            0 :           break;
     176         3055 :         case TopLevel::ImportKind::Kind::Rebind:
     177         3055 :           found = resolve_rebind_import (use_dec_id, std::move (import));
     178         3055 :           break;
     179              :         }
     180              : 
     181         3077 :       if (!found && old_error_count == macro_resolve_errors.size ())
     182           20 :         collect_error (Error (path.get_final_segment ().get_locus (),
     183              :                               ErrorCode::E0433, "unresolved import %qs",
     184           20 :                               path.as_string ().c_str ()));
     185         3077 :     }
     186         1850 : }
     187              : 
     188              : void
     189        68722 : Early::TextualScope::push ()
     190              : {
     191              :   // push a new empty scope
     192        68722 :   scopes.emplace_back ();
     193        68722 : }
     194              : 
     195              : void
     196        68722 : Early::TextualScope::pop ()
     197              : {
     198        68722 :   rust_assert (!scopes.empty ());
     199              : 
     200        68722 :   scopes.pop_back ();
     201        68722 : }
     202              : 
     203              : void
     204         3800 : Early::TextualScope::insert (std::string name, NodeId id)
     205              : {
     206         3800 :   rust_assert (!scopes.empty ());
     207              : 
     208              :   // we can ignore the return value as we always want the latest defined macro
     209              :   // to shadow a previous one - so if two macros have the same name and get
     210              :   // inserted with the same key, it's not a bug
     211         7600 :   scopes.back ().insert ({name, id});
     212         3800 : }
     213              : 
     214              : tl::optional<NodeId>
     215         2845 : Early::TextualScope::get (const std::string &name)
     216              : {
     217         5587 :   for (auto iterator = scopes.rbegin (); iterator != scopes.rend (); iterator++)
     218              :     {
     219         5543 :       auto scope = *iterator;
     220         5543 :       auto found = scope.find (name);
     221         5543 :       if (found != scope.end ())
     222         2801 :         return found->second;
     223         5543 :     }
     224              : 
     225           44 :   return tl::nullopt;
     226              : }
     227              : 
     228              : void
     229         3800 : Early::visit (AST::MacroRulesDefinition &def)
     230              : {
     231         3800 :   DefaultResolver::visit (def);
     232              : 
     233         7600 :   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
     234         3800 :   insert_once (def);
     235         3800 : }
     236              : 
     237              : void
     238        54712 : Early::visit (AST::BlockExpr &block)
     239              : {
     240        54712 :   textual_scope.push ();
     241              : 
     242        54712 :   DefaultResolver::visit (block);
     243              : 
     244        54712 :   textual_scope.pop ();
     245        54712 : }
     246              : 
     247              : void
     248         3262 : Early::visit (AST::Module &module)
     249              : {
     250         3262 :   bool is_macro_use = false;
     251              : 
     252         3505 :   for (const auto &attr : module.get_outer_attrs ())
     253              :     {
     254          274 :       if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE)
     255              :         {
     256              :           is_macro_use = true;
     257              :           break;
     258              :         }
     259              :     }
     260              : 
     261         3262 :   if (!is_macro_use)
     262         3231 :     textual_scope.push ();
     263              : 
     264         3262 :   DefaultResolver::visit (module);
     265              : 
     266         3262 :   if (!is_macro_use)
     267         3231 :     textual_scope.pop ();
     268         3262 : }
     269              : 
     270              : void
     271         2857 : Early::visit (AST::MacroInvocation &invoc)
     272              : {
     273         2857 :   auto &path = invoc.get_invoc_data ().get_path ();
     274              : 
     275              :   // We special case the `offset_of!()` macro if the flag is here, otherwise
     276              :   // we accept whatever `offset_of!()` definition we resolved to.
     277         2857 :   auto resolve_offset_of
     278         2857 :     = flag_assume_builtin_offset_of && (path.as_string () == "offset_of");
     279              : 
     280         2857 :   if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
     281           95 :     for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
     282           50 :       pending_invoc->accept_vis (*this);
     283              : 
     284              :   // When a macro is invoked by an unqualified identifier (not part of a
     285              :   // multi-part path), it is first looked up in textual scoping. If this does
     286              :   // not yield any results, then it is looked up in path-based scoping. If the
     287              :   // macro's name is qualified with a path, then it is only looked up in
     288              :   // path-based scoping.
     289              : 
     290              :   // https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
     291              : 
     292         2857 :   tl::optional<Rib::Definition> definition = tl::nullopt;
     293         2857 :   if (path.get_segments ().size () == 1)
     294         2845 :     definition
     295         2845 :       = textual_scope.get (path.get_final_segment ().as_string ())
     296         8447 :           .map ([] (NodeId id) { return Rib::Definition::NonShadowable (id); });
     297              : 
     298              :   // we won't have changed `definition` from `nullopt` if there are more
     299              :   // than one segments in our path
     300         2857 :   if (!definition.has_value ())
     301           70 :     definition = ctx.resolve_path (path, Namespace::Macros);
     302              : 
     303              :   // if the definition still does not have a value, then it's an error - unless
     304              :   // we should automatically resolve offset_of!() calls
     305         2857 :   if (!definition.has_value ())
     306              :     {
     307           42 :       if (!resolve_offset_of)
     308           24 :         collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
     309              :                               "could not resolve macro invocation %qs",
     310           48 :                               path.as_string ().c_str ()));
     311           42 :       return;
     312              :     }
     313              : 
     314         2815 :   insert_once (invoc, definition->get_node_id ());
     315              : 
     316              :   // now do we need to keep mappings or something? or insert "uses" into our
     317              :   // ForeverStack? can we do that? are mappings simpler?
     318         2815 :   auto &mappings = Analysis::Mappings::get ();
     319         2815 :   auto rules_def = mappings.lookup_macro_def (definition->get_node_id ());
     320              : 
     321              :   // Macro definition not found, maybe it is not expanded yet.
     322         2815 :   if (!rules_def)
     323              :     return;
     324              : 
     325         2815 :   if (mappings.lookup_macro_invocation (invoc))
     326              :     return;
     327              : 
     328            0 :   mappings.insert_macro_invocation (invoc, rules_def.value ());
     329         2857 : }
     330              : 
     331              : void
     332          170 : Early::visit_derive_attribute (AST::Attribute &attr,
     333              :                                Analysis::Mappings &mappings)
     334              : {
     335          170 :   auto traits = attr.get_traits_to_derive ();
     336          476 :   for (auto &trait : traits)
     337              :     {
     338          306 :       auto definition = ctx.resolve_path (trait.get (), Namespace::Macros);
     339          306 :       if (!definition.has_value ())
     340              :         {
     341              :           // FIXME: Change to proper error message
     342          612 :           collect_error (Error (trait.get ().get_locus (),
     343              :                                 "could not resolve trait %qs",
     344          306 :                                 trait.get ().as_string ().c_str ()));
     345          306 :           continue;
     346              :         }
     347              : 
     348            0 :       auto pm_def
     349            0 :         = mappings.lookup_derive_proc_macro_def (definition->get_node_id ());
     350              : 
     351            0 :       if (pm_def.has_value ())
     352            0 :         mappings.insert_derive_proc_macro_invocation (trait, pm_def.value ());
     353          306 :     }
     354          170 : }
     355              : 
     356              : void
     357            1 : Early::visit_non_builtin_attribute (AST::Attribute &attr,
     358              :                                     Analysis::Mappings &mappings,
     359              :                                     std::string &name)
     360              : {
     361            1 :   auto definition = ctx.resolve_path (attr.get_path (), Namespace::Macros);
     362            1 :   if (!definition.has_value ())
     363              :     {
     364              :       // FIXME: Change to proper error message
     365            0 :       collect_error (Error (attr.get_locus (),
     366              :                             "could not resolve attribute macro invocation %qs",
     367            0 :                             name.c_str ()));
     368            0 :       return;
     369              :     }
     370            1 :   auto pm_def
     371            1 :     = mappings.lookup_attribute_proc_macro_def (definition->get_node_id ());
     372              : 
     373            1 :   if (!pm_def.has_value ())
     374              :     return;
     375              : 
     376            0 :   mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
     377            0 :                                                    pm_def.value ());
     378            1 : }
     379              : 
     380              : void
     381        71061 : Early::visit (AST::Attribute &attr)
     382              : {
     383        71061 :   auto &mappings = Analysis::Mappings::get ();
     384              : 
     385        71061 :   auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
     386       141952 :   auto is_not_builtin = [&name] (AST::Attribute &attr) {
     387        70891 :     return Analysis::BuiltinAttributeMappings::get ()
     388        70891 :       ->lookup_builtin (name)
     389        70891 :       .is_error ();
     390        71061 :   };
     391              : 
     392        71061 :   if (attr.is_derive ())
     393              :     {
     394          170 :       visit_derive_attribute (attr, mappings);
     395              :     }
     396        70891 :   else if (is_not_builtin (attr)) // Do not resolve builtins
     397              :     {
     398            1 :       visit_non_builtin_attribute (attr, mappings, name);
     399              :     }
     400              : 
     401        71061 :   DefaultResolver::visit (attr);
     402        71061 : }
     403              : 
     404              : void
     405            0 : Early::finalize_simple_import (const Early::ImportPair &mapping)
     406              : {
     407              :   // FIXME: We probably need to store namespace information
     408              : 
     409            0 :   auto locus = mapping.import_kind.to_resolve.get_locus ();
     410            0 :   auto data = mapping.data;
     411            0 :   auto identifier
     412            0 :     = mapping.import_kind.to_resolve.get_final_segment ().get_segment_name ();
     413              : 
     414            0 :   for (auto &&definition : data.definitions ())
     415            0 :     toplevel
     416            0 :       .insert_or_error_out (
     417            0 :         identifier, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
     418            0 : }
     419              : 
     420              : void
     421           21 : Early::finalize_glob_import (NameResolutionContext &ctx,
     422              :                              const Early::ImportPair &mapping)
     423              : {
     424           42 :   auto container = Analysis::Mappings::get ().lookup_glob_container (
     425           42 :     mapping.data.container ().get_node_id ());
     426              : 
     427           21 :   rust_assert (container);
     428              : 
     429           21 :   if (mapping.import_kind.is_prelude)
     430              :     {
     431            1 :       rust_assert (container.value ()->get_glob_container_kind ()
     432              :                    == AST::GlobContainer::Kind::Module);
     433              : 
     434            1 :       ctx.prelude = mapping.data.container ().get_node_id ();
     435              :     }
     436              : 
     437           21 :   GlobbingVisitor (ctx).go (container.value ());
     438           21 : }
     439              : 
     440              : void
     441         3043 : Early::finalize_rebind_import (const Early::ImportPair &mapping)
     442              : {
     443              :   // We can fetch the value here as `resolve_rebind` will only be called on
     444              :   // imports of the right kind
     445         3043 :   auto &path = mapping.import_kind.to_resolve;
     446         3043 :   auto &rebind = mapping.import_kind.rebind.value ();
     447         3043 :   auto data = mapping.data;
     448              : 
     449         3043 :   location_t locus = UNKNOWN_LOCATION;
     450         3043 :   std::string declared_name;
     451              : 
     452              :   // FIXME: This needs to be done in `FinalizeImports`
     453         3043 :   switch (rebind.get_new_bind_type ())
     454              :     {
     455            6 :     case AST::UseTreeRebind::NewBindType::IDENTIFIER:
     456            6 :       declared_name = rebind.get_identifier ().as_string ();
     457            6 :       locus = rebind.get_identifier ().get_locus ();
     458            6 :       break;
     459         3033 :     case AST::UseTreeRebind::NewBindType::NONE:
     460         3033 :       {
     461         3033 :         const auto &segments = path.get_segments ();
     462              :         // We don't want to insert `self` with `use module::self`
     463         3033 :         if (path.get_final_segment ().is_lower_self_seg ())
     464              :           {
     465              :             // Erroneous `self` or `{self}` use declaration
     466          209 :             if (segments.size () == 1)
     467              :               break;
     468          204 :             declared_name = segments[segments.size () - 2].as_string ();
     469              :           }
     470              :         else
     471         2824 :           declared_name = path.get_final_segment ().as_string ();
     472         3028 :         locus = path.get_final_segment ().get_locus ();
     473         3028 :         break;
     474              :       }
     475            4 :     case AST::UseTreeRebind::NewBindType::WILDCARD:
     476              :       // We don't want to insert it into the trie
     477            4 :       return;
     478              :     }
     479              : 
     480         6592 :   for (auto &&definition : data.definitions ())
     481         3553 :     toplevel.insert_or_error_out (
     482        17251 :       declared_name, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
     483         6086 : }
     484              : 
     485              : void
     486         1850 : Early::visit (AST::UseDeclaration &decl)
     487              : {
     488              :   // We do not want to visit the use trees, we're only looking for top level
     489              :   // rebind. eg. `use something;` or `use something::other;`
     490         1850 :   if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind)
     491              :     {
     492         1373 :       auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ());
     493         1373 :       if (rebind.get_path ().get_final_segment ().is_lower_self_seg ())
     494              :         {
     495            2 :           collect_error (
     496            1 :             Error (decl.get_locus (), ErrorCode::E0429,
     497            1 :                    "%<self%> imports are only allowed within a { } list"));
     498              :         }
     499              :     }
     500              : 
     501         1850 :   auto &imports = toplevel.get_imports_to_resolve ();
     502         1850 :   auto current_import = imports.find (decl.get_node_id ());
     503         1850 :   if (current_import != imports.end ())
     504              :     {
     505         1850 :       build_import_mapping (*current_import);
     506              :     }
     507              : 
     508              :   // Once this is done, we finalize their resolution
     509         4914 :   for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
     510         3064 :     switch (mapping.import_kind.kind)
     511              :       {
     512           21 :       case TopLevel::ImportKind::Kind::Glob:
     513           21 :         finalize_glob_import (ctx, mapping);
     514           21 :         break;
     515            0 :       case TopLevel::ImportKind::Kind::Simple:
     516            0 :         finalize_simple_import (mapping);
     517            0 :         break;
     518         3043 :       case TopLevel::ImportKind::Kind::Rebind:
     519         3043 :         finalize_rebind_import (mapping);
     520         3043 :         break;
     521              :       }
     522              : 
     523         1850 :   DefaultResolver::visit (decl);
     524         1850 : }
     525              : 
     526              : void
     527          455 : Early::visit (AST::UseTreeList &use_list)
     528              : {
     529          455 :   if (!use_list.has_path ())
     530              :     {
     531           10 :       for (auto &&tree : use_list.get_trees ())
     532              :         {
     533            6 :           if (tree->get_kind () == AST::UseTree::Kind::Rebind)
     534              :             {
     535            6 :               auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
     536            6 :               auto path_size = rebind.get_path ().get_segments ().size ();
     537            6 :               if (path_size == 1
     538            6 :                   && rebind.get_path ()
     539            6 :                        .get_final_segment ()
     540            6 :                        .is_lower_self_seg ())
     541              :                 {
     542            4 :                   collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
     543              :                                         "%<self%> import can only appear in an "
     544            4 :                                         "import list with a non-empty prefix"));
     545              :                 }
     546              :             }
     547              :         }
     548              :     }
     549          455 :   DefaultResolver::visit (use_list);
     550          455 : }
     551              : 
     552              : void
     553        56574 : Early::visit (AST::IdentifierPattern &identifier)
     554              : {
     555              :   // check if this is *really* a path pattern
     556        56574 :   if (!identifier.get_is_ref () && !identifier.get_is_mut ()
     557       110907 :       && !identifier.has_subpattern ())
     558              :     {
     559        54299 :       auto res = ctx.values.get (identifier.get_ident ());
     560        54299 :       if (res)
     561              :         {
     562          122 :           if (res->is_ambiguous ())
     563            0 :             rust_error_at (identifier.get_locus (), ErrorCode::E0659,
     564              :                            "%qs is ambiguous",
     565            0 :                            identifier.get_ident ().as_string ().c_str ());
     566              :           else
     567              :             {
     568              :               // HACK: bail out if the definition is a function
     569          122 :               if (!ctx.mappings.is_function_node (res->get_node_id ()))
     570           22 :                 ident_path_to_convert.insert (identifier.get_node_id ());
     571              :             }
     572              :         }
     573        54299 :     }
     574        56574 : }
     575              : 
     576              : } // namespace Resolver2_0
     577              : } // 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.