LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-expand-format-args.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.4 % 66 61
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2024-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-expand-format-args.h"
      20              : #include "rust-ast-fragment.h"
      21              : #include "rust-ast.h"
      22              : #include "rust-builtin-ast-nodes.h"
      23              : #include "rust-ast-builder.h"
      24              : #include "rust-diagnostics.h"
      25              : #include "rust-expr.h"
      26              : #include "rust-fmt.h"
      27              : #include "rust-path.h"
      28              : #include "rust-system.h"
      29              : #include "rust-token.h"
      30              : 
      31              : namespace Rust {
      32              : namespace Fmt {
      33              : 
      34              : static std::unique_ptr<AST::Expr>
      35            4 : format_arg (const AST::Builder &builder, std::unique_ptr<AST::Expr> &&to_format,
      36              :             const std::string &trait)
      37              : {
      38            4 :   auto formatter_fn = std::unique_ptr<AST::Expr> (new AST::PathInExpression (
      39           24 :     builder.path_in_expression ({"core", "fmt", trait, "fmt"})));
      40              : 
      41            4 :   auto path = std::unique_ptr<AST::Expr> (new AST::PathInExpression (
      42            4 :     builder.path_in_expression ({"core", "fmt", "ArgumentV1", "new"})));
      43              : 
      44            4 :   auto args = std::vector<std::unique_ptr<AST::Expr>> ();
      45            4 :   args.emplace_back (std::move (to_format));
      46            4 :   args.emplace_back (std::move (formatter_fn));
      47              : 
      48            4 :   return builder.call (std::move (path), std::move (args));
      49            4 : }
      50              : 
      51              : const std::string &
      52            4 : get_trait_name (ffi::FormatSpec format_specifier)
      53              : {
      54            4 :   static const std::unordered_map<std::string, std::string> spec_map = {
      55              :     {"", "Display"},   {"?", "Debug"},    {"e", "LowerExp"},
      56              :     {"E", "UpperExp"}, {"o", "Octal"},    {"p", "Pointer"},
      57              :     {"b", "Binary"},   {"x", "LowerHex"}, {"X", "UpperHex"},
      58           31 :   };
      59              : 
      60            4 :   auto it = spec_map.find (format_specifier.ty.to_string ());
      61              : 
      62            4 :   if (it == spec_map.end ())
      63            0 :     rust_unreachable ();
      64              : 
      65            4 :   return it->second;
      66              : }
      67              : 
      68              : tl::optional<AST::Fragment>
      69            3 : expand_format_args (AST::FormatArgs &fmt,
      70              :                     std::vector<std::unique_ptr<AST::Token>> &&tokens)
      71              : {
      72            3 :   auto loc = fmt.get_locus ();
      73            3 :   auto builder = AST::Builder (loc);
      74            3 :   auto &arguments = fmt.get_arguments ();
      75              : 
      76            3 :   auto static_pieces = std::vector<std::unique_ptr<AST::Expr>> ();
      77            3 :   auto args
      78            3 :     = std::vector<std::pair<std::unique_ptr<AST::Expr>, ffi::FormatSpec>> ();
      79              : 
      80           11 :   for (const auto &node : fmt.get_template ().get_pieces ())
      81              :     {
      82            8 :       switch (node.tag)
      83              :         {
      84            4 :         case ffi::Piece::Tag::String:
      85            4 :           static_pieces.emplace_back (
      86            8 :             builder.literal_string (node.string._0.to_string ()));
      87            4 :           break;
      88            4 :         case ffi::Piece::Tag::NextArgument:
      89            4 :           {
      90            4 :             auto next_argument = node.next_argument._0;
      91            4 :             switch (node.next_argument._0.position.tag)
      92              :               {
      93            4 :               case ffi::Position::Tag::ArgumentImplicitlyIs:
      94            4 :                 {
      95            4 :                   auto idx = next_argument.position.argument_implicitly_is._0;
      96            4 :                   auto trait = next_argument.format;
      97            4 :                   auto arg = arguments.at (idx);
      98              : 
      99              :                   // FIXME(Arthur): This API sucks
     100            4 :                   rust_assert (arg.get_kind ().kind
     101              :                                == AST::FormatArgumentKind::Kind::Normal);
     102              : 
     103            4 :                   args.push_back ({arg.get_expr ().clone_expr (), trait});
     104            4 :                 }
     105            4 :                 break;
     106            0 :               case ffi::Position::Tag::ArgumentIs:
     107            0 :               case ffi::Position::Tag::ArgumentNamed:
     108            0 :                 rust_sorry_at (loc, "unhandled argument position specifier");
     109            0 :                 break;
     110              :               }
     111            4 :           }
     112            4 :           break;
     113              :         }
     114              :     }
     115              : 
     116            3 :   auto args_array = std::vector<std::unique_ptr<AST::Expr>> ();
     117            7 :   for (auto &&arg : args)
     118           12 :     args_array.emplace_back (format_arg (builder,
     119            8 :                                          builder.ref (std::move (arg.first)),
     120            4 :                                          get_trait_name (arg.second)));
     121              : 
     122            3 :   auto pieces = builder.ref (builder.array (std::move (static_pieces)));
     123            3 :   auto args_slice = builder.ref (builder.array (std::move (args_array)));
     124              : 
     125            3 :   auto final_path = std::make_unique<AST::PathInExpression> (
     126            3 :     builder.path_in_expression ({"core", "fmt", "Arguments", "new_v1"}));
     127            3 :   auto final_args = std::vector<std::unique_ptr<AST::Expr>> ();
     128            3 :   final_args.emplace_back (std::move (pieces));
     129            3 :   final_args.emplace_back (std::move (args_slice));
     130              : 
     131            3 :   auto final_call
     132            3 :     = builder.call (std::move (final_path), std::move (final_args));
     133              : 
     134            3 :   auto node = AST::SingleASTNode (std::move (final_call));
     135              : 
     136            9 :   return AST::Fragment ({node}, std::move (tokens));
     137            3 : }
     138              : 
     139              : } // namespace Fmt
     140              : } // 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.