LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-stmt.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.9 % 84 78
Test Date: 2026-02-28 14:20:25 Functions: 82.4 % 34 28
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              : #ifndef RUST_AST_STATEMENT_H
      20              : #define RUST_AST_STATEMENT_H
      21              : 
      22              : #include "optional.h"
      23              : #include "rust-ast.h"
      24              : #include "rust-path.h"
      25              : #include "rust-expr.h"
      26              : #include "rust-system.h"
      27              : 
      28              : namespace Rust {
      29              : namespace AST {
      30              : // Just a semi-colon, which apparently is a statement.
      31          130 : class EmptyStmt : public Stmt
      32              : {
      33              :   location_t locus;
      34              : 
      35              :   // TODO: find another way to store this to save memory?
      36              :   bool marked_for_strip = false;
      37              : 
      38              : public:
      39            0 :   std::string as_string () const override { return std::string (1, ';'); }
      40              : 
      41           48 :   EmptyStmt (location_t locus) : locus (locus) {}
      42              : 
      43           46 :   location_t get_locus () const override final { return locus; }
      44              : 
      45              :   void accept_vis (ASTVisitor &vis) override;
      46              : 
      47              :   // Can't think of any invalid invariants, so store boolean.
      48            0 :   void mark_for_strip () override { marked_for_strip = true; }
      49          162 :   bool is_marked_for_strip () const override { return marked_for_strip; }
      50              : 
      51            0 :   bool is_item () const override final { return false; }
      52              : 
      53          226 :   Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Empty; }
      54              : 
      55              : protected:
      56              :   /* Use covariance to implement clone function as returning this object rather
      57              :    * than base */
      58          130 :   EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); }
      59              : };
      60              : 
      61              : /* Variable assignment let statement - type of "declaration statement" as it
      62              :  * introduces new name into scope */
      63              : class LetStmt : public Stmt
      64              : {
      65              :   // bool has_outer_attrs;
      66              :   std::vector<Attribute> outer_attrs;
      67              : 
      68              :   std::unique_ptr<Pattern> variables_pattern;
      69              : 
      70              :   // bool has_type;
      71              :   std::unique_ptr<Type> type;
      72              : 
      73              :   // bool has_init_expr;
      74              :   std::unique_ptr<Expr> init_expr;
      75              : 
      76              :   tl::optional<std::unique_ptr<Expr>> else_expr;
      77              : 
      78              :   location_t locus;
      79              : 
      80              : public:
      81              :   Type *inferedType;
      82              : 
      83              :   // Returns whether let statement has outer attributes.
      84              :   bool has_outer_attrs () const { return !outer_attrs.empty (); }
      85              : 
      86              :   // Returns whether let statement has a given return type.
      87       320389 :   bool has_type () const { return type != nullptr; }
      88              : 
      89              :   // Returns whether let statement has an initialisation expression.
      90       320120 :   bool has_init_expr () const { return init_expr != nullptr; }
      91        26819 :   bool has_else_expr () const { return else_expr.has_value (); }
      92              : 
      93              :   std::string as_string () const override;
      94              : 
      95        13119 :   LetStmt (std::unique_ptr<Pattern> variables_pattern,
      96              :            std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
      97              :            tl::optional<std::unique_ptr<Expr>> else_expr,
      98              :            std::vector<Attribute> outer_attrs, location_t locus)
      99        26238 :     : outer_attrs (std::move (outer_attrs)),
     100        13119 :       variables_pattern (std::move (variables_pattern)),
     101        13119 :       type (std::move (type)), init_expr (std::move (init_expr)),
     102        13119 :       else_expr (std::move (else_expr)), locus (locus)
     103        13119 :   {}
     104              : 
     105              :   // Copy constructor with clone
     106        13748 :   LetStmt (LetStmt const &other)
     107        13748 :     : outer_attrs (other.outer_attrs), locus (other.locus)
     108              :   {
     109              :     // guard to prevent null dereference (only required if error state)
     110        13748 :     if (other.variables_pattern != nullptr)
     111        13748 :       variables_pattern = other.variables_pattern->clone_pattern ();
     112              : 
     113              :     // guard to prevent null dereference (always required)
     114        13748 :     if (other.init_expr != nullptr)
     115        12676 :       init_expr = other.init_expr->clone_expr ();
     116        13748 :     if (other.else_expr.has_value ())
     117            5 :       else_expr = other.else_expr.value ()->clone_expr ();
     118              : 
     119        13748 :     if (other.type != nullptr)
     120         2069 :       type = other.type->clone_type ();
     121        13748 :   }
     122              : 
     123              :   // Overloaded assignment operator to clone
     124              :   LetStmt &operator= (LetStmt const &other)
     125              :   {
     126              :     outer_attrs = other.outer_attrs;
     127              :     locus = other.locus;
     128              : 
     129              :     // guard to prevent null dereference (only required if error state)
     130              :     if (other.variables_pattern != nullptr)
     131              :       variables_pattern = other.variables_pattern->clone_pattern ();
     132              :     else
     133              :       variables_pattern = nullptr;
     134              : 
     135              :     // guard to prevent null dereference (always required)
     136              :     if (other.init_expr != nullptr)
     137              :       init_expr = other.init_expr->clone_expr ();
     138              :     else
     139              :       init_expr = nullptr;
     140              : 
     141              :     if (other.else_expr != nullptr)
     142              :       else_expr = other.else_expr.value ()->clone_expr ();
     143              :     else
     144              :       else_expr = tl::nullopt;
     145              : 
     146              :     if (other.type != nullptr)
     147              :       type = other.type->clone_type ();
     148              :     else
     149              :       type = nullptr;
     150              : 
     151              :     return *this;
     152              :   }
     153              : 
     154              :   // move constructors
     155              :   LetStmt (LetStmt &&other) = default;
     156              :   LetStmt &operator= (LetStmt &&other) = default;
     157              : 
     158        14113 :   location_t get_locus () const override final { return locus; }
     159              : 
     160              :   void accept_vis (ASTVisitor &vis) override;
     161              : 
     162              :   // Invalid if pattern is null, so base stripping on that.
     163            0 :   void mark_for_strip () override { variables_pattern = nullptr; }
     164        36940 :   bool is_marked_for_strip () const override
     165              :   {
     166        36940 :     return variables_pattern == nullptr;
     167              :   }
     168              : 
     169              :   // TODO: this mutable getter seems really dodgy. Think up better way.
     170       291220 :   std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     171              :   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     172              : 
     173              :   // TODO: is this better? Or is a "vis_block" better?
     174       258070 :   Expr &get_init_expr ()
     175              :   {
     176       258070 :     rust_assert (has_init_expr ());
     177       258070 :     return *init_expr;
     178              :   }
     179              : 
     180           10 :   Expr &get_else_expr ()
     181              :   {
     182           10 :     rust_assert (has_else_expr ());
     183           10 :     return *else_expr.value ();
     184              :   }
     185              : 
     186        36562 :   std::unique_ptr<Expr> &get_init_expr_ptr ()
     187              :   {
     188        36562 :     rust_assert (has_init_expr ());
     189        36562 :     return init_expr;
     190              :   }
     191              : 
     192              :   std::unique_ptr<Expr> &get_else_expr_ptr ()
     193              :   {
     194              :     rust_assert (has_else_expr ());
     195              :     return else_expr.value ();
     196              :   }
     197              : 
     198       279989 :   Pattern &get_pattern ()
     199              :   {
     200       279989 :     rust_assert (variables_pattern != nullptr);
     201       279989 :     return *variables_pattern;
     202              :   }
     203              : 
     204        40131 :   std::unique_ptr<Pattern> &get_pattern_ptr ()
     205              :   {
     206        40131 :     rust_assert (variables_pattern != nullptr);
     207        40131 :     return variables_pattern;
     208              :   }
     209              : 
     210        41987 :   Type &get_type ()
     211              :   {
     212        41987 :     rust_assert (has_type ());
     213        41987 :     return *type;
     214              :   }
     215              : 
     216         6599 :   std::unique_ptr<Type> &get_type_ptr ()
     217              :   {
     218         6599 :     rust_assert (has_type ());
     219         6599 :     return type;
     220              :   }
     221              : 
     222            0 :   bool is_item () const override final { return false; }
     223        49666 :   Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Let; }
     224              : 
     225              : protected:
     226              :   /* Use covariance to implement clone function as returning this object rather
     227              :    * than base */
     228        13748 :   LetStmt *clone_stmt_impl () const override { return new LetStmt (*this); }
     229              : };
     230              : 
     231              : // Expression statements (statements containing an expression)
     232              : class ExprStmt : public Stmt
     233              : {
     234              :   std::unique_ptr<Expr> expr;
     235              :   location_t locus;
     236              :   bool semicolon_followed;
     237              : 
     238              : public:
     239         9270 :   location_t get_locus () const override final { return locus; }
     240              : 
     241            0 :   bool is_item () const override final { return false; }
     242              : 
     243        12051 :   bool is_expr () const override final { return true; }
     244              : 
     245              :   // Used for the last statement for statement macros with a trailing
     246              :   // semicolon.
     247          238 :   void add_semicolon () override final { semicolon_followed = true; }
     248              : 
     249              :   std::string as_string () const override;
     250              : 
     251        33896 :   Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Expr; }
     252              : 
     253              :   std::vector<LetStmt *> locals;
     254              : 
     255         9446 :   ExprStmt (std::unique_ptr<Expr> &&expr, location_t locus,
     256              :             bool semicolon_followed)
     257        18892 :     : expr (std::move (expr)), locus (locus),
     258         9446 :       semicolon_followed (semicolon_followed)
     259              :   {}
     260              : 
     261              :   // Copy constructor with clone
     262        15936 :   ExprStmt (ExprStmt const &other)
     263        15936 :     : locus (other.locus), semicolon_followed (other.semicolon_followed)
     264              :   {
     265              :     // guard to prevent null dereference (only required if error state)
     266        15936 :     if (other.expr != nullptr)
     267        15936 :       expr = other.expr->clone_expr ();
     268        15936 :   }
     269              : 
     270              :   // Overloaded assignment operator to clone
     271              :   ExprStmt &operator= (ExprStmt const &other)
     272              :   {
     273              :     Stmt::operator= (other);
     274              : 
     275              :     // guard to prevent null dereference (only required if error state)
     276              :     if (other.expr != nullptr)
     277              :       expr = other.expr->clone_expr ();
     278              :     else
     279              :       expr = nullptr;
     280              : 
     281              :     locus = other.locus;
     282              :     semicolon_followed = other.semicolon_followed;
     283              : 
     284              :     return *this;
     285              :   }
     286              : 
     287              :   // move constructors
     288              :   ExprStmt (ExprStmt &&other) = default;
     289              :   ExprStmt &operator= (ExprStmt &&other) = default;
     290              : 
     291              :   void accept_vis (ASTVisitor &vis) override;
     292              : 
     293              :   // Invalid if expr is null, so base stripping on that.
     294           18 :   void mark_for_strip () override { expr = nullptr; }
     295        92787 :   bool is_marked_for_strip () const override { return expr == nullptr; }
     296              : 
     297              :   // TODO: is this better? Or is a "vis_block" better?
     298       218974 :   Expr &get_expr ()
     299              :   {
     300       218974 :     rust_assert (expr != nullptr);
     301       218974 :     return *expr;
     302              :   }
     303              : 
     304        28529 :   std::unique_ptr<Expr> &get_expr_ptr ()
     305              :   {
     306        28529 :     rust_assert (expr != nullptr);
     307        28529 :     return expr;
     308              :   }
     309              : 
     310           59 :   std::unique_ptr<Expr> take_expr ()
     311              :   {
     312           59 :     rust_assert (expr != nullptr);
     313           59 :     return std::move (expr);
     314              :   }
     315              : 
     316        22176 :   bool is_semicolon_followed () const { return semicolon_followed; }
     317              : 
     318              : protected:
     319              :   /* Use covariance to implement clone function as returning this object rather
     320              :    * than base */
     321        15936 :   ExprStmt *clone_stmt_impl () const override { return new ExprStmt (*this); }
     322              : };
     323              : 
     324              : } // namespace AST
     325              : } // namespace Rust
     326              : 
     327              : #endif
        

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.