LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 71.5 % 151 108
Test Date: 2025-06-21 16:26:05 Functions: 72.0 % 25 18
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                 :         705 : GenericArgs::as_string () const
      36                 :             : {
      37                 :         705 :   std::string args;
      38                 :             : 
      39                 :             :   // lifetime args
      40                 :         705 :   if (!lifetime_args.empty ())
      41                 :             :     {
      42                 :             :       auto i = lifetime_args.begin ();
      43                 :             :       auto e = lifetime_args.end ();
      44                 :             : 
      45                 :          42 :       for (; i != e; i++)
      46                 :             :         {
      47                 :          42 :           args += (*i).as_string ();
      48                 :          21 :           if (e != i + 1)
      49                 :           0 :             args += ", ";
      50                 :             :         }
      51                 :             :     }
      52                 :             : 
      53                 :             :   // type args
      54                 :         705 :   if (!generic_args.empty ())
      55                 :             :     {
      56                 :             :       auto i = generic_args.begin ();
      57                 :             :       auto e = generic_args.end ();
      58                 :             : 
      59                 :        1459 :       for (; i != e; i++)
      60                 :             :         {
      61                 :        1550 :           args += (*i).as_string ();
      62                 :         775 :           if (e != i + 1)
      63                 :          91 :             args += ", ";
      64                 :             :         }
      65                 :             :     }
      66                 :             : 
      67                 :             :   // binding args
      68                 :         705 :   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                 :         705 :   return args;
      82                 :             : }
      83                 :             : 
      84                 :             : GenericArg
      85                 :          14 : GenericArg::disambiguate_to_const () const
      86                 :             : {
      87                 :          14 :   rust_assert (get_kind () == Kind::Either);
      88                 :             : 
      89                 :             :   // FIXME: is it fine to have no outer attributes?
      90                 :          14 :   return GenericArg::create_const (
      91                 :          14 :     std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
      92                 :             : }
      93                 :             : 
      94                 :             : GenericArg
      95                 :        2169 : GenericArg::disambiguate_to_type () const
      96                 :             : {
      97                 :        2169 :   rust_assert (get_kind () == Kind::Either);
      98                 :             : 
      99                 :        2169 :   auto segment = std::unique_ptr<TypePathSegment> (
     100                 :        4338 :     new TypePathSegment (path.as_string (), false, locus));
     101                 :        2169 :   auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
     102                 :        2169 :   segments.emplace_back (std::move (segment));
     103                 :             : 
     104                 :        2169 :   return GenericArg::create_type (
     105                 :        2169 :     std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
     106                 :        2169 : }
     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                 :        7059 : PathExprSegment::as_string () const
     129                 :             : {
     130                 :             :   // TODO: rewrite dump to work with non-literalisable types
     131                 :        7059 :   std::string ident_str = segment_name.as_string ();
     132                 :        7059 :   if (has_generic_args ())
     133                 :           0 :     ident_str += "::<" + generic_args.as_string () + ">";
     134                 :             : 
     135                 :        7059 :   return ident_str;
     136                 :             : }
     137                 :             : 
     138                 :             : std::string
     139                 :           2 : Path::as_string () const
     140                 :             : {
     141                 :             :   // FIXME: Impl for lang items
     142                 :           2 :   rust_assert (kind == Kind::Regular);
     143                 :             : 
     144                 :           2 :   std::string str;
     145                 :             : 
     146                 :           4 :   for (const auto &segment : segments)
     147                 :           6 :     str += segment.as_string () + "::";
     148                 :             : 
     149                 :             :   // basically a hack - remove last two characters of string (remove final ::)
     150                 :           2 :   str.erase (str.length () - 2);
     151                 :             : 
     152                 :           2 :   return str;
     153                 :             : }
     154                 :             : 
     155                 :             : SimplePath
     156                 :        3481 : Path::convert_to_simple_path (bool with_opening_scope_resolution) const
     157                 :             : {
     158                 :        3481 :   rust_assert (kind == Kind::Regular);
     159                 :             : 
     160                 :        3481 :   if (!has_segments ())
     161                 :           0 :     return SimplePath::create_empty ();
     162                 :             : 
     163                 :             :   // create vector of reserved size (to minimise reallocations)
     164                 :        3481 :   std::vector<SimplePathSegment> simple_segments;
     165                 :        3481 :   simple_segments.reserve (segments.size ());
     166                 :             : 
     167                 :        7008 :   for (const auto &segment : segments)
     168                 :             :     {
     169                 :             :       // return empty path if doesn't meet simple path segment requirements
     170                 :       10581 :       if (segment.is_error () || segment.has_generic_args ()
     171                 :        7054 :           || segment.as_string () == "Self")
     172                 :           0 :         return SimplePath::create_empty ();
     173                 :             : 
     174                 :             :       // create segment and add to vector
     175                 :        3527 :       std::string segment_str = segment.as_string ();
     176                 :        7054 :       simple_segments.push_back (
     177                 :        7054 :         SimplePathSegment (std::move (segment_str), segment.get_locus ()));
     178                 :        3527 :     }
     179                 :             : 
     180                 :             :   // kind of a HACK to get locus depending on opening scope resolution
     181                 :        3481 :   location_t locus = UNKNOWN_LOCATION;
     182                 :        3481 :   if (with_opening_scope_resolution)
     183                 :           0 :     locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
     184                 :             :   else
     185                 :        3481 :     locus = simple_segments[0].get_locus ();
     186                 :             :   // FIXME: this hack probably doesn't actually work
     187                 :             : 
     188                 :        3481 :   return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
     189                 :        3481 :                      locus);
     190                 :        3481 : }
     191                 :             : 
     192                 :             : void
     193                 :      252668 : PathInExpression::accept_vis (ASTVisitor &vis)
     194                 :             : {
     195                 :      252668 :   vis.visit (*this);
     196                 :      252668 : }
     197                 :             : 
     198                 :             : std::string
     199                 :           2 : PathInExpression::as_string () const
     200                 :             : {
     201                 :           2 :   std::string str;
     202                 :             : 
     203                 :           2 :   if (has_opening_scope_resolution)
     204                 :           0 :     str = "::";
     205                 :             : 
     206                 :           2 :   return str + Path::as_string ();
     207                 :           2 : }
     208                 :             : 
     209                 :             : std::string
     210                 :         705 : TypePathSegmentGeneric::as_string () const
     211                 :             : {
     212                 :             :   // TODO: rewrite to work with non-linearisable types
     213                 :        2115 :   return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
     214                 :             : }
     215                 :             : 
     216                 :             : std::string
     217                 :           0 : TypePathSegmentFunction::as_string () const
     218                 :             : {
     219                 :             :   // TODO: rewrite to work with non-linearisable types
     220                 :           0 :   return TypePathSegment::as_string () + function_path.as_string ();
     221                 :             : }
     222                 :             : 
     223                 :             : std::string
     224                 :       82206 : TypePath::as_string () const
     225                 :             : {
     226                 :             :   /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
     227                 :             :    * literalised */
     228                 :       82206 :   std::string str;
     229                 :             : 
     230                 :       82206 :   if (has_opening_scope_resolution)
     231                 :          31 :     str = "::";
     232                 :             : 
     233                 :      164514 :   for (const auto &segment : segments)
     234                 :      246924 :     str += segment->as_string () + "::";
     235                 :             : 
     236                 :             :   // kinda hack - remove last 2 '::' characters
     237                 :       82206 :   str.erase (str.length () - 2);
     238                 :             : 
     239                 :       82206 :   return str;
     240                 :             : }
     241                 :             : 
     242                 :             : SimplePath
     243                 :          35 : TypePath::as_simple_path () const
     244                 :             : {
     245                 :          35 :   if (segments.empty ())
     246                 :           0 :     return SimplePath::create_empty ();
     247                 :             : 
     248                 :             :   // create vector of reserved size (to minimise reallocations)
     249                 :          35 :   std::vector<SimplePathSegment> simple_segments;
     250                 :          35 :   simple_segments.reserve (segments.size ());
     251                 :             : 
     252                 :          70 :   for (const auto &segment : segments)
     253                 :             :     {
     254                 :             :       // return empty path if doesn't meet simple path segment requirements
     255                 :          35 :       if (segment == nullptr || segment->is_error ()
     256                 :          70 :           || !segment->is_ident_only () || segment->as_string () == "Self")
     257                 :           0 :         return SimplePath::create_empty ();
     258                 :             : 
     259                 :             :       // create segment and add to vector
     260                 :          35 :       std::string segment_str = segment->as_string ();
     261                 :          70 :       simple_segments.push_back (
     262                 :          70 :         SimplePathSegment (std::move (segment_str), segment->get_locus ()));
     263                 :          35 :     }
     264                 :             : 
     265                 :          35 :   return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
     266                 :          35 :                      locus);
     267                 :          35 : }
     268                 :             : 
     269                 :             : // hopefully definition here will prevent circular dependency issue
     270                 :             : TraitBound *
     271                 :           0 : TypePath::to_trait_bound (bool in_parens) const
     272                 :             : {
     273                 :           0 :   return new TraitBound (TypePath (*this), get_locus (), in_parens);
     274                 :             : }
     275                 :             : 
     276                 :             : std::string
     277                 :           0 : TypePathFunction::as_string () const
     278                 :             : {
     279                 :             :   // TODO: rewrite to work with non-linearisable types
     280                 :           0 :   std::string str ("(");
     281                 :             : 
     282                 :           0 :   if (has_inputs ())
     283                 :             :     {
     284                 :             :       auto i = inputs.begin ();
     285                 :             :       auto e = inputs.end ();
     286                 :             : 
     287                 :           0 :       for (; i != e; i++)
     288                 :             :         {
     289                 :           0 :           str += (*i)->as_string ();
     290                 :           0 :           if (e != i + 1)
     291                 :           0 :             str += ", ";
     292                 :             :         }
     293                 :             :     }
     294                 :             : 
     295                 :           0 :   str += ")";
     296                 :             : 
     297                 :           0 :   if (has_return_type ())
     298                 :           0 :     str += " -> " + return_type->as_string ();
     299                 :             : 
     300                 :           0 :   return str;
     301                 :             : }
     302                 :             : 
     303                 :             : std::string
     304                 :           0 : QualifiedPathInExpression::as_string () const
     305                 :             : {
     306                 :           0 :   return path_type.as_string () + "::" + Path::as_string ();
     307                 :             : }
     308                 :             : 
     309                 :             : std::string
     310                 :           0 : QualifiedPathInType::as_string () const
     311                 :             : {
     312                 :             :   /* TODO: this may need adjusting if segments (e.g. with functions) can't be
     313                 :             :    * literalised */
     314                 :           0 :   std::string str = path_type.as_string ();
     315                 :             : 
     316                 :           0 :   str += "::" + associated_segment->as_string ();
     317                 :           0 :   for (const auto &segment : segments)
     318                 :           0 :     str += "::" + segment->as_string ();
     319                 :             : 
     320                 :           0 :   return str;
     321                 :             : }
     322                 :             : 
     323                 :             : void
     324                 :         712 : ConstGenericParam::accept_vis (ASTVisitor &vis)
     325                 :             : {
     326                 :         712 :   vis.visit (*this);
     327                 :         712 : }
     328                 :             : 
     329                 :             : void
     330                 :      574022 : TypePathSegment::accept_vis (ASTVisitor &vis)
     331                 :             : {
     332                 :      574022 :   vis.visit (*this);
     333                 :      574022 : }
     334                 :             : 
     335                 :             : void
     336                 :       32036 : TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
     337                 :             : {
     338                 :       32036 :   vis.visit (*this);
     339                 :       32036 : }
     340                 :             : 
     341                 :             : void
     342                 :         331 : TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
     343                 :             : {
     344                 :         331 :   vis.visit (*this);
     345                 :         331 : }
     346                 :             : 
     347                 :             : void
     348                 :      623917 : TypePath::accept_vis (ASTVisitor &vis)
     349                 :             : {
     350                 :      623917 :   vis.visit (*this);
     351                 :      623915 : }
     352                 :             : 
     353                 :             : void
     354                 :        1756 : QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
     355                 :             : {
     356                 :        1756 :   vis.visit (*this);
     357                 :        1756 : }
     358                 :             : 
     359                 :             : void
     360                 :        5785 : QualifiedPathInType::accept_vis (ASTVisitor &vis)
     361                 :             : {
     362                 :        5785 :   vis.visit (*this);
     363                 :        5785 : }
     364                 :             : 
     365                 :             : } // namespace AST
     366                 :             : } // 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.