LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 59.4 % 160 95
Test Date: 2025-11-22 14:42:49 Functions: 65.4 % 26 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* General AST-related method implementations for Rust frontend.
       2                 :             :    Copyright (C) 2009-2025 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : #include "rust-path.h"
      21                 :             : #include "rust-system.h"
      22                 :             : #include "rust-ast-full.h"
      23                 :             : #include "rust-diagnostics.h"
      24                 :             : #include "rust-ast-visitor.h"
      25                 :             : #include "rust-macro.h"
      26                 :             : #include "rust-session-manager.h"
      27                 :             : #include "rust-lex.h"
      28                 :             : #include "rust-parse.h"
      29                 :             : #include "rust-operators.h"
      30                 :             : 
      31                 :             : namespace Rust {
      32                 :             : namespace AST {
      33                 :             : 
      34                 :             : std::string
      35                 :           0 : GenericArgs::as_string () const
      36                 :             : {
      37                 :           0 :   std::string args;
      38                 :             : 
      39                 :             :   // lifetime args
      40                 :           0 :   if (!lifetime_args.empty ())
      41                 :             :     {
      42                 :             :       auto i = lifetime_args.begin ();
      43                 :             :       auto e = lifetime_args.end ();
      44                 :             : 
      45                 :           0 :       for (; i != e; i++)
      46                 :             :         {
      47                 :           0 :           args += (*i).as_string ();
      48                 :           0 :           if (e != i + 1)
      49                 :           0 :             args += ", ";
      50                 :             :         }
      51                 :             :     }
      52                 :             : 
      53                 :             :   // type args
      54                 :           0 :   if (!generic_args.empty ())
      55                 :             :     {
      56                 :             :       auto i = generic_args.begin ();
      57                 :             :       auto e = generic_args.end ();
      58                 :             : 
      59                 :           0 :       for (; i != e; i++)
      60                 :             :         {
      61                 :           0 :           args += (*i).as_string ();
      62                 :           0 :           if (e != i + 1)
      63                 :           0 :             args += ", ";
      64                 :             :         }
      65                 :             :     }
      66                 :             : 
      67                 :             :   // binding args
      68                 :           0 :   if (!binding_args.empty ())
      69                 :             :     {
      70                 :             :       auto i = binding_args.begin ();
      71                 :             :       auto e = binding_args.end ();
      72                 :             : 
      73                 :           0 :       for (; i != e; i++)
      74                 :             :         {
      75                 :           0 :           args += (*i).as_string ();
      76                 :           0 :           if (e != i + 1)
      77                 :           0 :             args += ", ";
      78                 :             :         }
      79                 :             :     }
      80                 :             : 
      81                 :           0 :   return args;
      82                 :             : }
      83                 :             : 
      84                 :             : GenericArg
      85                 :          31 : GenericArg::disambiguate_to_const () const
      86                 :             : {
      87                 :          31 :   rust_assert (get_kind () == Kind::Either);
      88                 :             : 
      89                 :             :   // FIXME: is it fine to have no outer attributes?
      90                 :          31 :   return GenericArg::create_const (
      91                 :          31 :     std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
      92                 :             : }
      93                 :             : 
      94                 :             : GenericArg
      95                 :        2309 : GenericArg::disambiguate_to_type () const
      96                 :             : {
      97                 :        2309 :   rust_assert (get_kind () == Kind::Either);
      98                 :             : 
      99                 :        2309 :   auto segment = std::unique_ptr<TypePathSegment> (
     100                 :        4618 :     new TypePathSegment (path.as_string (), false, locus));
     101                 :        2309 :   auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
     102                 :        2309 :   segments.emplace_back (std::move (segment));
     103                 :             : 
     104                 :        2309 :   return GenericArg::create_type (
     105                 :        2309 :     std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
     106                 :        2309 : }
     107                 :             : 
     108                 :             : std::string
     109                 :           0 : GenericArgsBinding::as_string () const
     110                 :             : {
     111                 :             :   // TODO: rewrite to work with non-literalisable types
     112                 :           0 :   return identifier.as_string () + " = " + type->as_string ();
     113                 :             : }
     114                 :             : 
     115                 :             : std::string
     116                 :           0 : ConstGenericParam::as_string () const
     117                 :             : {
     118                 :           0 :   std::string str ("ConstGenericParam: ");
     119                 :           0 :   str += "const " + name.as_string () + ": " + type->as_string ();
     120                 :             : 
     121                 :           0 :   if (has_default_value ())
     122                 :           0 :     str += " = " + get_default_value_unchecked ().as_string ();
     123                 :             : 
     124                 :           0 :   return str;
     125                 :             : }
     126                 :             : 
     127                 :             : std::string
     128                 :       52797 : PathExprSegment::as_string () const
     129                 :             : {
     130                 :             :   // TODO: rewrite dump to work with non-literalisable types
     131                 :       52797 :   std::string ident_str = segment_name.as_string ();
     132                 :       52797 :   if (has_generic_args ())
     133                 :           0 :     ident_str += "::<" + generic_args.as_string () + ">";
     134                 :             : 
     135                 :       52797 :   return ident_str;
     136                 :             : }
     137                 :             : 
     138                 :             : std::string
     139                 :           1 : Path::as_string () const
     140                 :             : {
     141                 :             :   // FIXME: Impl for lang items
     142                 :           1 :   rust_assert (kind == Kind::Regular);
     143                 :             : 
     144                 :           1 :   std::string str;
     145                 :             : 
     146                 :           2 :   for (const auto &segment : segments)
     147                 :           3 :     str += segment.as_string () + "::";
     148                 :             : 
     149                 :             :   // basically a hack - remove last two characters of string (remove final ::)
     150                 :           1 :   str.erase (str.length () - 2);
     151                 :             : 
     152                 :           1 :   return str;
     153                 :             : }
     154                 :             : 
     155                 :             : SimplePath
     156                 :       52545 : Path::convert_to_simple_path (bool with_opening_scope_resolution) const
     157                 :             : {
     158                 :       52545 :   rust_assert (kind == Kind::Regular);
     159                 :             : 
     160                 :       52545 :   if (!has_segments ())
     161                 :           0 :     return SimplePath::create_empty ();
     162                 :             : 
     163                 :             :   // create vector of reserved size (to minimise reallocations)
     164                 :       52545 :   std::vector<SimplePathSegment> simple_segments;
     165                 :       52545 :   simple_segments.reserve (segments.size ());
     166                 :             : 
     167                 :      105341 :   for (const auto &segment : segments)
     168                 :             :     {
     169                 :             :       // return empty path if doesn't meet simple path segment requirements
     170                 :       52796 :       if (segment.is_error () || segment.has_generic_args ())
     171                 :           0 :         return SimplePath::create_empty ();
     172                 :             : 
     173                 :             :       // create segment and add to vector
     174                 :       52796 :       std::string segment_str = segment.as_string ();
     175                 :       52796 :       simple_segments.emplace_back (std::move (segment_str),
     176                 :       52796 :                                     segment.get_locus ());
     177                 :       52796 :     }
     178                 :             : 
     179                 :             :   // kind of a HACK to get locus depending on opening scope resolution
     180                 :       52545 :   location_t locus = UNKNOWN_LOCATION;
     181                 :       52545 :   if (with_opening_scope_resolution)
     182                 :           0 :     locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
     183                 :             :   else
     184                 :       52545 :     locus = simple_segments[0].get_locus ();
     185                 :             :   // FIXME: this hack probably doesn't actually work
     186                 :             : 
     187                 :       52545 :   return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
     188                 :       52545 :                      locus);
     189                 :       52545 : }
     190                 :             : 
     191                 :             : void
     192                 :    13518040 : PathInExpression::accept_vis (ASTVisitor &vis)
     193                 :             : {
     194                 :    13518040 :   vis.visit (*this);
     195                 :    13518040 : }
     196                 :             : 
     197                 :             : std::string
     198                 :           1 : PathInExpression::as_string () const
     199                 :             : {
     200                 :           1 :   std::string str;
     201                 :             : 
     202                 :           1 :   if (has_opening_scope_resolution)
     203                 :           0 :     str = "::";
     204                 :             : 
     205                 :           1 :   return str + Path::as_string ();
     206                 :           1 : }
     207                 :             : 
     208                 :             : std::string
     209                 :           0 : TypePathSegmentGeneric::as_string () const
     210                 :             : {
     211                 :             :   // TODO: rewrite to work with non-linearisable types
     212                 :           0 :   return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
     213                 :             : }
     214                 :             : 
     215                 :             : std::string
     216                 :           0 : TypePathSegmentFunction::as_string () const
     217                 :             : {
     218                 :             :   // TODO: rewrite to work with non-linearisable types
     219                 :           0 :   return TypePathSegment::as_string () + function_path.as_string ();
     220                 :             : }
     221                 :             : 
     222                 :             : std::string
     223                 :           0 : TypePath::as_string () const
     224                 :             : {
     225                 :             :   /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
     226                 :             :    * literalised */
     227                 :           0 :   std::string str;
     228                 :             : 
     229                 :           0 :   if (has_opening_scope_resolution)
     230                 :           0 :     str = "::";
     231                 :             : 
     232                 :           0 :   for (const auto &segment : segments)
     233                 :           0 :     str += segment->as_string () + "::";
     234                 :             : 
     235                 :             :   // kinda hack - remove last 2 '::' characters
     236                 :           0 :   str.erase (str.length () - 2);
     237                 :             : 
     238                 :           0 :   return str;
     239                 :             : }
     240                 :             : 
     241                 :             : SimplePath
     242                 :         497 : TypePath::as_simple_path () const
     243                 :             : {
     244                 :         497 :   if (segments.empty ())
     245                 :           0 :     return SimplePath::create_empty ();
     246                 :             : 
     247                 :             :   // create vector of reserved size (to minimise reallocations)
     248                 :         497 :   std::vector<SimplePathSegment> simple_segments;
     249                 :         497 :   simple_segments.reserve (segments.size ());
     250                 :             : 
     251                 :         994 :   for (const auto &segment : segments)
     252                 :             :     {
     253                 :             :       // return empty path if doesn't meet simple path segment requirements
     254                 :         497 :       if (segment == nullptr || segment->is_error ()
     255                 :         994 :           || !segment->is_ident_only () || segment->as_string () == "Self")
     256                 :           0 :         return SimplePath::create_empty ();
     257                 :             : 
     258                 :             :       // create segment and add to vector
     259                 :         497 :       std::string segment_str = segment->as_string ();
     260                 :         497 :       simple_segments.emplace_back (std::move (segment_str),
     261                 :         497 :                                     segment->get_locus ());
     262                 :         497 :     }
     263                 :             : 
     264                 :         497 :   return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
     265                 :         497 :                      locus);
     266                 :         497 : }
     267                 :             : 
     268                 :             : std::string
     269                 :          23 : TypePath::make_debug_string () const
     270                 :             : {
     271                 :          23 :   rust_assert (!segments.empty ());
     272                 :             : 
     273                 :          23 :   std::string output;
     274                 :             : 
     275                 :          46 :   for (const auto &segment : segments)
     276                 :             :     {
     277                 :          23 :       if (segment != nullptr && !segment->is_lang_item ()
     278                 :          46 :           && !segment->is_error ())
     279                 :             :         {
     280                 :          23 :           if (!output.empty () || has_opening_scope_resolution_op ())
     281                 :           0 :             output.append ("::");
     282                 :          69 :           output.append (segment->get_ident_segment ().as_string ());
     283                 :             :         }
     284                 :             :     }
     285                 :             : 
     286                 :          23 :   return output;
     287                 :             : }
     288                 :             : 
     289                 :             : // hopefully definition here will prevent circular dependency issue
     290                 :             : TraitBound *
     291                 :           3 : TypePath::to_trait_bound (bool in_parens) const
     292                 :             : {
     293                 :           3 :   return new TraitBound (TypePath (*this), get_locus (), in_parens);
     294                 :             : }
     295                 :             : 
     296                 :             : std::string
     297                 :           0 : TypePathFunction::as_string () const
     298                 :             : {
     299                 :             :   // TODO: rewrite to work with non-linearisable types
     300                 :           0 :   std::string str ("(");
     301                 :             : 
     302                 :           0 :   if (has_inputs ())
     303                 :             :     {
     304                 :             :       auto i = inputs.begin ();
     305                 :             :       auto e = inputs.end ();
     306                 :             : 
     307                 :           0 :       for (; i != e; i++)
     308                 :             :         {
     309                 :           0 :           str += (*i)->as_string ();
     310                 :           0 :           if (e != i + 1)
     311                 :           0 :             str += ", ";
     312                 :             :         }
     313                 :             :     }
     314                 :             : 
     315                 :           0 :   str += ")";
     316                 :             : 
     317                 :           0 :   if (has_return_type ())
     318                 :           0 :     str += " -> " + return_type->as_string ();
     319                 :             : 
     320                 :           0 :   return str;
     321                 :             : }
     322                 :             : 
     323                 :             : std::string
     324                 :           0 : QualifiedPathInExpression::as_string () const
     325                 :             : {
     326                 :           0 :   return path_type.as_string () + "::" + Path::as_string ();
     327                 :             : }
     328                 :             : 
     329                 :             : std::string
     330                 :           0 : QualifiedPathInType::as_string () const
     331                 :             : {
     332                 :             :   /* TODO: this may need adjusting if segments (e.g. with functions) can't be
     333                 :             :    * literalised */
     334                 :           0 :   std::string str = path_type.as_string ();
     335                 :             : 
     336                 :           0 :   str += "::" + associated_segment->as_string ();
     337                 :           0 :   for (const auto &segment : segments)
     338                 :           0 :     str += "::" + segment->as_string ();
     339                 :             : 
     340                 :           0 :   return str;
     341                 :             : }
     342                 :             : 
     343                 :             : void
     344                 :       12744 : ConstGenericParam::accept_vis (ASTVisitor &vis)
     345                 :             : {
     346                 :       12744 :   vis.visit (*this);
     347                 :       12744 : }
     348                 :             : 
     349                 :             : void
     350                 :    12069555 : TypePathSegment::accept_vis (ASTVisitor &vis)
     351                 :             : {
     352                 :    12069555 :   vis.visit (*this);
     353                 :    12069555 : }
     354                 :             : 
     355                 :             : void
     356                 :     2775586 : TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
     357                 :             : {
     358                 :     2775586 :   vis.visit (*this);
     359                 :     2775586 : }
     360                 :             : 
     361                 :             : void
     362                 :       96509 : TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
     363                 :             : {
     364                 :       96509 :   vis.visit (*this);
     365                 :       96509 : }
     366                 :             : 
     367                 :             : void
     368                 :    10989945 : TypePath::accept_vis (ASTVisitor &vis)
     369                 :             : {
     370                 :    10989945 :   vis.visit (*this);
     371                 :    10989945 : }
     372                 :             : 
     373                 :             : void
     374                 :       24114 : QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
     375                 :             : {
     376                 :       24114 :   vis.visit (*this);
     377                 :       24114 : }
     378                 :             : 
     379                 :             : void
     380                 :      528771 : QualifiedPathInType::accept_vis (ASTVisitor &vis)
     381                 :             : {
     382                 :      528771 :   vis.visit (*this);
     383                 :      528771 : }
     384                 :             : 
     385                 :             : } // namespace AST
     386                 :             : } // namespace Rust
        

Generated by: LCOV version 2.1-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.