aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/ast
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/ast')
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.cc166
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.h57
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc61
-rw-r--r--gcc/rust/ast/rust-ast-builder.h39
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc75
-rw-r--r--gcc/rust/ast/rust-ast-collector.h6
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h5
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc58
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h12
-rw-r--r--gcc/rust/ast/rust-ast.cc319
-rw-r--r--gcc/rust/ast/rust-ast.h67
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h53
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.cc69
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.h17
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.cc54
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.h16
-rw-r--r--gcc/rust/ast/rust-desugar-try-block.cc62
-rw-r--r--gcc/rust/ast/rust-desugar-try-block.h42
-rw-r--r--gcc/rust/ast/rust-desugar-while-let.cc104
-rw-r--r--gcc/rust/ast/rust-desugar-while-let.h71
-rw-r--r--gcc/rust/ast/rust-expr.h261
-rw-r--r--gcc/rust/ast/rust-expression-yeast.cc118
-rw-r--r--gcc/rust/ast/rust-expression-yeast.h52
-rw-r--r--gcc/rust/ast/rust-macro.h49
-rw-r--r--gcc/rust/ast/rust-path.h37
-rw-r--r--gcc/rust/ast/rust-pattern.cc54
-rw-r--r--gcc/rust/ast/rust-pattern.h209
-rw-r--r--gcc/rust/ast/rust-type.h124
28 files changed, 1542 insertions, 715 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
deleted file mode 100644
index 7f8571a..0000000
--- a/gcc/rust/ast/rust-ast-builder-type.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-builder-type.h"
-#include "rust-ast-builder.h"
-#include "rust-ast-full.h"
-#include "rust-common.h"
-
-namespace Rust {
-namespace AST {
-
-ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {}
-
-Type *
-ASTTypeBuilder::build (Type &type)
-{
- ASTTypeBuilder builder;
- type.accept_vis (builder);
- rust_assert (builder.translated != nullptr);
- return builder.translated;
-}
-
-void
-ASTTypeBuilder::visit (BareFunctionType &fntype)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TupleType &tuple)
-{
- std::vector<std::unique_ptr<Type> > elems;
- for (auto &elem : tuple.get_elems ())
- {
- Type *t = ASTTypeBuilder::build (*elem.get ());
- std::unique_ptr<Type> ty (t);
- elems.push_back (std::move (ty));
- }
- translated = new TupleType (std::move (elems), tuple.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TypePath &path)
-{
- std::vector<std::unique_ptr<TypePathSegment> > segments;
- for (auto &seg : path.get_segments ())
- {
- switch (seg->get_type ())
- {
- case TypePathSegment::REG:
- {
- const TypePathSegment &segment
- = (const TypePathSegment &) (*seg.get ());
- TypePathSegment *s
- = new TypePathSegment (segment.get_ident_segment (),
- segment.get_separating_scope_resolution (),
- segment.get_locus ());
- std::unique_ptr<TypePathSegment> sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::GENERIC:
- {
- TypePathSegmentGeneric &generic
- = (TypePathSegmentGeneric &) (*seg.get ());
-
- GenericArgs args
- = Builder::new_generic_args (generic.get_generic_args ());
- TypePathSegmentGeneric *s
- = new TypePathSegmentGeneric (generic.get_ident_segment (), false,
- std::move (args),
- generic.get_locus ());
- std::unique_ptr<TypePathSegment> sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::FUNCTION:
- {
- rust_unreachable ();
- // TODO
- // const TypePathSegmentFunction &fn
- // = (const TypePathSegmentFunction &) (*seg.get ());
- }
- break;
- }
- }
-
- translated = new TypePath (std::move (segments), path.get_locus (),
- path.has_opening_scope_resolution_op ());
-}
-
-void
-ASTTypeBuilder::visit (QualifiedPathInType &path)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ArrayType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ReferenceType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (RawPointerType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (SliceType &type)
-{
- Type *t = ASTTypeBuilder::build (type.get_elem_type ());
- std::unique_ptr<Type> ty (t);
- translated = new SliceType (std::move (ty), type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (InferredType &type)
-{
- translated = new InferredType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (NeverType &type)
-{
- translated = new NeverType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectTypeOneBound &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectType &type)
-{
- /* TODO */
-}
-
-} // namespace AST
-} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h
deleted file mode 100644
index b67ae3b..0000000
--- a/gcc/rust/ast/rust-ast-builder-type.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_BUILDER_TYPE
-#define RUST_AST_BUILDER_TYPE
-
-#include "rust-ast-visitor.h"
-
-namespace Rust {
-namespace AST {
-
-class ASTTypeBuilder : public DefaultASTVisitor
-{
-protected:
- using DefaultASTVisitor::visit;
-
-public:
- static Type *build (Type &type);
-
- void visit (BareFunctionType &fntype) override;
- void visit (TupleType &tuple) override;
- void visit (TypePath &path) override;
- void visit (QualifiedPathInType &path) override;
- void visit (ArrayType &type) override;
- void visit (ReferenceType &type) override;
- void visit (RawPointerType &type) override;
- void visit (SliceType &type) override;
- void visit (InferredType &type) override;
- void visit (NeverType &type) override;
- void visit (TraitObjectTypeOneBound &type) override;
- void visit (TraitObjectType &type) override;
-
-private:
- ASTTypeBuilder ();
-
- Type *translated;
-};
-
-} // namespace AST
-} // namespace Rust
-
-#endif // RUST_AST_BUILDER_TYPE
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index fbc8f27..ed10ce7 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -18,7 +18,6 @@
#include "rust-ast-builder.h"
#include "optional.h"
-#include "rust-ast-builder-type.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
@@ -29,7 +28,6 @@
#include "rust-pattern.h"
#include "rust-system.h"
#include "rust-token.h"
-#include <memory>
namespace Rust {
namespace AST {
@@ -332,6 +330,12 @@ Builder::block () const
}
std::unique_ptr<BlockExpr>
+Builder::block (std::unique_ptr<Expr> &&tail_expr) const
+{
+ return block (tl::nullopt, std::move (tail_expr));
+}
+
+std::unique_ptr<BlockExpr>
Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts,
std::unique_ptr<Expr> &&tail_expr) const
{
@@ -490,9 +494,14 @@ MatchCase
Builder::match_case (std::unique_ptr<Pattern> &&pattern,
std::unique_ptr<Expr> &&expr)
{
- return MatchCase (match_arm (std::move (pattern)), std::move (expr));
+ return match_case (match_arm (std::move (pattern)), std::move (expr));
}
+MatchCase
+Builder::match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr)
+{
+ return MatchCase (std::move (arm), std::move (expr));
+}
std::unique_ptr<Expr>
Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts)
{
@@ -531,11 +540,14 @@ Builder::generic_type_param (
std::vector<Attribute> ());
}
-std::unique_ptr<Type>
-Builder::new_type (Type &type)
+std::unique_ptr<Stmt>
+Builder::discriminant_value (std::string binding_name, std::string instance)
{
- Type *t = ASTTypeBuilder::build (type);
- return std::unique_ptr<Type> (t);
+ auto intrinsic = ptrify (
+ path_in_expression ({"core", "intrinsics", "discriminant_value"}, true));
+
+ return let (identifier_pattern (binding_name), nullptr,
+ call (std::move (intrinsic), identifier (instance)));
}
std::unique_ptr<GenericParam>
@@ -555,6 +567,16 @@ Builder::new_lifetime_param (LifetimeParam &param)
}
std::unique_ptr<GenericParam>
+Builder::new_const_param (ConstGenericParam &param) const
+{
+ return std::make_unique<ConstGenericParam> (param.get_name (),
+ param.get_type ().clone_type (),
+ param.get_default_value (),
+ param.get_outer_attrs (),
+ param.get_locus ());
+}
+
+std::unique_ptr<GenericParam>
Builder::new_type_param (
TypeParam &param, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds)
{
@@ -565,7 +587,7 @@ Builder::new_type_param (
std::unique_ptr<Type> type = nullptr;
if (param.has_type ())
- type = new_type (param.get_type ());
+ type = param.get_type ().reconstruct ();
for (auto &&extra_bound : extra_bounds)
type_param_bounds.emplace_back (std::move (extra_bound));
@@ -695,7 +717,7 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &binding : args.get_binding_args ())
{
Type &t = *binding.get_type_ptr ().get ();
- std::unique_ptr<Type> ty = new_type (t);
+ std::unique_ptr<Type> ty = t.reconstruct ();
GenericArgsBinding b (binding.get_identifier (), std::move (ty),
binding.get_locus ());
binding_args.push_back (std::move (b));
@@ -703,20 +725,25 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &arg : args.get_generic_args ())
{
+ tl::optional<GenericArg> new_arg = tl::nullopt;
+
switch (arg.get_kind ())
{
case GenericArg::Kind::Type:
- {
- std::unique_ptr<Type> ty = new_type (arg.get_type ());
- GenericArg arg = GenericArg::create_type (std::move (ty));
- }
+ new_arg = GenericArg::create_type (arg.get_type ().reconstruct ());
break;
-
- default:
- // FIXME
- rust_unreachable ();
+ case GenericArg::Kind::Either:
+ new_arg
+ = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ());
+ break;
+ case GenericArg::Kind::Const:
+ new_arg
+ = GenericArg::create_const (arg.get_expression ().clone_expr ());
+ // FIXME: Use `reconstruct()` here, not `clone_expr()`
break;
}
+
+ generic_args.emplace_back (*new_arg);
}
return GenericArgs (std::move (lifetime_args), std::move (generic_args),
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index a5115b68..843bab8 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -24,6 +24,7 @@
#include "rust-ast.h"
#include "rust-item.h"
#include "rust-operators.h"
+#include <initializer_list>
namespace Rust {
namespace AST {
@@ -51,6 +52,19 @@ vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2)
return v;
}
+template <typename T>
+std::vector<std::unique_ptr<T>>
+vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2, std::unique_ptr<T> &&t3)
+{
+ auto v = std::vector<std::unique_ptr<T>> ();
+
+ v.emplace_back (std::move (t1));
+ v.emplace_back (std::move (t2));
+ v.emplace_back (std::move (t3));
+
+ return v;
+}
+
/* Pointer-ify something */
template <typename T>
static std::unique_ptr<T>
@@ -117,6 +131,9 @@ public:
/* Create an empty block */
std::unique_ptr<BlockExpr> block () const;
+ /* Create a block with just a tail expression */
+ std::unique_ptr<BlockExpr> block (std::unique_ptr<Expr> &&tail_expr) const;
+
/* Create an early return expression with an optional expression */
std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return
= nullptr);
@@ -272,6 +289,7 @@ public:
MatchArm match_arm (std::unique_ptr<Pattern> &&pattern);
MatchCase match_case (std::unique_ptr<Pattern> &&pattern,
std::unique_ptr<Expr> &&expr);
+ MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr);
/* Create a loop expression */
std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts);
@@ -289,11 +307,20 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
std::unique_ptr<Type> &&type = nullptr);
- static std::unique_ptr<Type> new_type (Type &type);
+ /**
+ * Create a let statement with the discriminant value of a given enum
+ * instance. This helper exists since it is a common operation in a lot of the
+ * derive implementations, and it sucks to repeat all the steps every time.
+ */
+ std::unique_ptr<Stmt> discriminant_value (std::string binding_name,
+ std::string instance = "self");
static std::unique_ptr<GenericParam>
new_lifetime_param (LifetimeParam &param);
+ std::unique_ptr<GenericParam>
+ new_const_param (ConstGenericParam &param) const;
+
static std::unique_ptr<GenericParam> new_type_param (
TypeParam &param,
std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {});
@@ -302,11 +329,13 @@ public:
static GenericArgs new_generic_args (GenericArgs &args);
-private:
- /**
- * Location of the generated AST nodes
- */
+ /* Location of the generated AST nodes */
location_t loc;
+
+private:
+ /* Some constexpr helpers for some of the builders */
+ static constexpr std::initializer_list<const char *> discriminant_value_path
+ = {"core", "intrinsics", "discriminant_value"};
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index b0e06ab..3d9ea78 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -18,6 +18,7 @@
#include "rust-ast-collector.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-diagnostics.h"
#include "rust-expr.h"
#include "rust-item.h"
@@ -839,13 +840,13 @@ TokenCollector::visit (MetaItemLitExpr &item)
}
void
-TokenCollector::visit (MetaItemPathLit &item)
+TokenCollector::visit (MetaItemPathExpr &item)
{
- auto path = item.get_path ();
- auto lit = item.get_literal ();
+ auto &path = item.get_path ();
+ auto &expr = item.get_expr ();
visit (path);
- push (Rust::Token::make (COLON, item.get_locus ()));
- visit (lit);
+ push (Rust::Token::make (EQUAL, item.get_locus ()));
+ visit (expr);
}
void
@@ -870,7 +871,8 @@ TokenCollector::visit (BorrowExpr &expr)
push (Rust::Token::make (MUT, UNDEF_LOCATION));
}
- visit (expr.get_borrowed_expr ());
+ if (expr.has_borrow_expr ())
+ visit (expr.get_borrowed_expr ());
}
void
@@ -1272,7 +1274,13 @@ TokenCollector::visit (BlockExpr &expr)
void
TokenCollector::visit (AnonConst &expr)
{
- visit (expr.get_inner_expr ());
+ if (!expr.is_deferred ())
+ {
+ visit (expr.get_inner_expr ());
+ return;
+ }
+
+ push (Rust::Token::make_string (expr.get_locus (), "_"));
}
void
@@ -1371,6 +1379,13 @@ TokenCollector::visit (ReturnExpr &expr)
}
void
+TokenCollector::visit (TryExpr &expr)
+{
+ push (Rust::Token::make (TRY, expr.get_locus ()));
+ visit (expr.get_block_expr ());
+}
+
+void
TokenCollector::visit (UnsafeBlockExpr &expr)
{
push (Rust::Token::make (UNSAFE, expr.get_locus ()));
@@ -2485,7 +2500,7 @@ TokenCollector::visit (IdentifierPattern &pattern)
if (pattern.has_subpattern ())
{
push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION));
- visit (pattern.get_pattern_to_bind ());
+ visit (pattern.get_subpattern ());
}
}
@@ -2703,10 +2718,34 @@ TokenCollector::visit (GroupedPattern &pattern)
}
void
+TokenCollector::visit (SlicePatternItemsNoRest &items)
+{
+ visit_items_joined_by_separator (items.get_patterns (), COMMA);
+}
+
+void
+TokenCollector::visit (SlicePatternItemsHasRest &items)
+{
+ if (!items.get_lower_patterns ().empty ())
+ {
+ visit_items_joined_by_separator (items.get_lower_patterns (), COMMA);
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ }
+
+ push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
+
+ if (!items.get_upper_patterns ().empty ())
+ {
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ visit_items_joined_by_separator (items.get_upper_patterns (), COMMA);
+ }
+}
+
+void
TokenCollector::visit (SlicePattern &pattern)
{
push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ()));
- visit_items_joined_by_separator (pattern.get_items (), COMMA);
+ visit (pattern.get_items ());
push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
}
@@ -2974,5 +3013,23 @@ TokenCollector::visit (AST::FormatArgs &fmt)
__FILE__, __LINE__);
}
+void
+TokenCollector::visit (AST::OffsetOf &offset_of)
+{
+ auto loc = offset_of.get_locus ();
+
+ push (Rust::Token::make_identifier (loc, "offset_of"));
+ push (Rust::Token::make (EXCLAM, loc));
+ push (Rust::Token::make (LEFT_PAREN, loc));
+
+ visit (offset_of.get_type ());
+
+ push (Rust::Token::make (COMMA, loc));
+
+ push (Rust::Token::make_identifier (offset_of.get_field ()));
+
+ push (Rust::Token::make (RIGHT_PAREN, loc));
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index cec2365..d3ab18a 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -246,7 +246,7 @@ public:
void visit (AttrInputLiteral &attr_input);
void visit (AttrInputMacro &attr_input);
void visit (MetaItemLitExpr &meta_item);
- void visit (MetaItemPathLit &meta_item);
+ void visit (MetaItemPathExpr &meta_item);
void visit (BorrowExpr &expr);
void visit (DereferenceExpr &expr);
void visit (ErrorPropagationExpr &expr);
@@ -289,6 +289,7 @@ public:
void visit (RangeFromToInclExpr &expr);
void visit (RangeToInclExpr &expr);
void visit (ReturnExpr &expr);
+ void visit (TryExpr &expr);
void visit (BoxExpr &expr);
void visit (UnsafeBlockExpr &expr);
void visit (LoopExpr &expr);
@@ -377,6 +378,8 @@ public:
void visit (TuplePatternItemsRanged &tuple_items);
void visit (TuplePattern &pattern);
void visit (GroupedPattern &pattern);
+ void visit (SlicePatternItemsNoRest &items);
+ void visit (SlicePatternItemsHasRest &items);
void visit (SlicePattern &pattern);
void visit (AltPattern &pattern);
@@ -402,6 +405,7 @@ public:
void visit (BareFunctionType &type);
void visit (FormatArgs &fmt);
+ void visit (OffsetOf &offset_of);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index b410f3a..09706ce 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -78,7 +78,7 @@ class LiteralExpr;
class AttrInputLiteral;
class AttrInputMacro;
class MetaItemLitExpr;
-class MetaItemPathLit;
+class MetaItemPathExpr;
class OperatorExpr;
class BorrowExpr;
class DereferenceExpr;
@@ -128,6 +128,7 @@ class RangeFullExpr;
class RangeFromToInclExpr;
class RangeToInclExpr;
class ReturnExpr;
+class TryExpr;
class UnsafeBlockExpr;
class LoopLabel;
class BaseLoopExpr;
@@ -247,6 +248,8 @@ class TuplePatternItemsMultiple;
class TuplePatternItemsRanged;
class TuplePattern;
class GroupedPattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
class SlicePattern;
class AltPattern;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 02f4f16..ab8cdbe 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -19,6 +19,7 @@
#include "rust-ast-visitor.h"
#include "rust-ast-full-decls.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-path.h"
#include "rust-token.h"
#include "rust-expr.h"
@@ -223,10 +224,10 @@ DefaultASTVisitor::visit (AST::SimplePath &path)
}
void
-DefaultASTVisitor::visit (AST::MetaItemPathLit &meta_item)
+DefaultASTVisitor::visit (AST::MetaItemPathExpr &meta_item)
{
visit (meta_item.get_path ());
- visit (meta_item.get_literal ());
+ visit (meta_item.get_expr ());
}
void
@@ -449,8 +450,13 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr)
{
visit_outer_attrs (expr);
visit_inner_attrs (expr);
+
+ if (expr.has_label ())
+ visit (expr.get_label ());
+
for (auto &stmt : expr.get_statements ())
visit (stmt);
+
if (expr.has_tail_expr ())
visit (expr.get_tail_expr ());
}
@@ -464,7 +470,8 @@ DefaultASTVisitor::visit (AST::ConstBlock &expr)
void
DefaultASTVisitor::visit (AST::AnonConst &expr)
{
- visit (expr.get_inner_expr ());
+ if (!expr.is_deferred ())
+ visit (expr.get_inner_expr ());
}
void
@@ -550,6 +557,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr)
}
void
+DefaultASTVisitor::visit (AST::TryExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit (expr.get_block_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::BoxExpr &expr)
{
visit_outer_attrs (expr);
@@ -594,7 +608,10 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- visit (expr.get_loop_label ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_block ());
}
@@ -942,7 +959,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item)
void
DefaultASTVisitor::visit (AST::EnumItemTuple &item)
{
- DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
for (auto &field : item.get_tuple_fields ())
visit (field);
}
@@ -950,7 +967,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item)
void
DefaultASTVisitor::visit (AST::EnumItemStruct &item)
{
- DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
for (auto &field : item.get_struct_fields ())
visit (field);
}
@@ -958,7 +975,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item)
void
DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item)
{
- DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
visit (item.get_expr ());
}
@@ -1200,7 +1217,7 @@ void
DefaultASTVisitor::visit (AST::IdentifierPattern &pattern)
{
if (pattern.has_subpattern ())
- visit (pattern.get_pattern_to_bind ());
+ visit (pattern.get_subpattern ());
}
void
@@ -1330,13 +1347,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items)
{
- for (auto &item : pattern.get_items ())
+ for (auto &item : items.get_patterns ())
visit (item);
}
void
+DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items)
+{
+ for (auto &item : items.get_lower_patterns ())
+ visit (item);
+ for (auto &item : items.get_upper_patterns ())
+ visit (item);
+}
+
+void
+DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+{
+ visit (pattern.get_items ());
+}
+
+void
DefaultASTVisitor::visit (AST::AltPattern &pattern)
{
for (auto &alt : pattern.get_alts ())
@@ -1474,6 +1506,12 @@ DefaultASTVisitor::visit (AST::FormatArgs &)
}
void
+DefaultASTVisitor::visit (AST::OffsetOf &offset_of)
+{
+ visit (offset_of.get_type ());
+}
+
+void
DefaultASTVisitor::visit (AST::VariadicParam &param)
{
if (param.has_pattern ())
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 22fd98b..2d81aa1 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -73,7 +73,7 @@ public:
virtual void visit (AttrInputLiteral &attr_input) = 0;
virtual void visit (AttrInputMacro &attr_input) = 0;
virtual void visit (MetaItemLitExpr &meta_item) = 0;
- virtual void visit (MetaItemPathLit &meta_item) = 0;
+ virtual void visit (MetaItemPathExpr &meta_item) = 0;
virtual void visit (BorrowExpr &expr) = 0;
virtual void visit (DereferenceExpr &expr) = 0;
virtual void visit (ErrorPropagationExpr &expr) = 0;
@@ -116,6 +116,7 @@ public:
virtual void visit (RangeFromToInclExpr &expr) = 0;
virtual void visit (RangeToInclExpr &expr) = 0;
virtual void visit (ReturnExpr &expr) = 0;
+ virtual void visit (TryExpr &expr) = 0;
virtual void visit (BoxExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
@@ -211,6 +212,8 @@ public:
virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
virtual void visit (TuplePattern &pattern) = 0;
virtual void visit (GroupedPattern &pattern) = 0;
+ virtual void visit (SlicePatternItemsNoRest &items) = 0;
+ virtual void visit (SlicePatternItemsHasRest &items) = 0;
virtual void visit (SlicePattern &pattern) = 0;
virtual void visit (AltPattern &pattern) = 0;
@@ -237,6 +240,7 @@ public:
// special AST nodes for certain builtin macros such as `asm!()`
virtual void visit (FormatArgs &fmt) = 0;
+ virtual void visit (OffsetOf &fmt) = 0;
// TODO: rust-cond-compilation.h visiting? not currently used
};
@@ -266,7 +270,7 @@ public:
virtual void visit (AST::AttrInputLiteral &attr_input) override;
virtual void visit (AST::AttrInputMacro &attr_input) override;
virtual void visit (AST::MetaItemLitExpr &meta_item) override;
- virtual void visit (AST::MetaItemPathLit &meta_item) override;
+ virtual void visit (AST::MetaItemPathExpr &meta_item) override;
virtual void visit (AST::BorrowExpr &expr) override;
virtual void visit (AST::DereferenceExpr &expr) override;
virtual void visit (AST::ErrorPropagationExpr &expr) override;
@@ -307,6 +311,7 @@ public:
virtual void visit (AST::RangeFromToInclExpr &expr) override;
virtual void visit (AST::RangeToInclExpr &expr) override;
virtual void visit (AST::ReturnExpr &expr) override;
+ virtual void visit (AST::TryExpr &expr) override;
virtual void visit (AST::BoxExpr &expr) override;
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
@@ -383,6 +388,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
virtual void visit (AST::EmptyStmt &stmt) override;
@@ -406,6 +413,7 @@ public:
virtual void visit (AST::FunctionParam &param) override;
virtual void visit (AST::VariadicParam &param) override;
virtual void visit (AST::FormatArgs &fmt) override;
+ virtual void visit (AST::OffsetOf &fmt) override;
template <typename T> void visit (T &node) { node.accept_vis (*this); }
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 916829f..8e856fb 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "rust-operators.h"
#include "rust-dir-owner.h"
#include "rust-attribute-values.h"
+#include "rust-macro-invoc-lexer.h"
/* Compilation unit used for various AST-related functions that would make
* the headers too long if they were defined inline and don't receive any
@@ -287,7 +288,7 @@ Attribute::get_traits_to_derive ()
break;
case AST::MetaItem::ItemKind::ListPaths:
case AST::MetaItem::ItemKind::NameValueStr:
- case AST::MetaItem::ItemKind::PathLit:
+ case AST::MetaItem::ItemKind::PathExpr:
case AST::MetaItem::ItemKind::Seq:
case AST::MetaItem::ItemKind::ListNameValueStr:
default:
@@ -1280,7 +1281,14 @@ BlockExpr::as_string () const
std::string
AnonConst::as_string () const
{
- return "AnonConst: " + expr->as_string ();
+ std::string str = "AnonConst: ";
+
+ if (kind == AnonConst::Kind::DeferredInference)
+ str += "_";
+ else
+ str += expr.value ()->as_string ();
+
+ return str;
}
std::string
@@ -1637,6 +1645,19 @@ ReturnExpr::as_string () const
}
std::string
+TryExpr::as_string () const
+{
+ /* TODO: find way to incorporate outer attrs - may have to represent in
+ * different style (i.e. something more like BorrowExpr: \n outer attrs) */
+
+ std::string str ("try ");
+
+ str += block_expr->as_string ();
+
+ return str;
+}
+
+std::string
RangeToExpr::as_string () const
{
return ".." + to->as_string ();
@@ -2754,7 +2775,7 @@ std::string
ArrayType::as_string () const
{
// TODO: rewrite to work with non-linearisable types and exprs
- return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+ return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
}
std::string
@@ -3495,13 +3516,24 @@ DelimTokenTree::parse_to_meta_item () const
return new AttrInputMetaItemContainer (std::move (meta_items));
}
+AttributeParser::AttributeParser (
+ std::vector<std::unique_ptr<Token>> token_stream, int stream_start_pos)
+ : lexer (new MacroInvocLexer (std::move (token_stream))),
+ parser (new Parser<MacroInvocLexer> (*lexer))
+{
+ if (stream_start_pos)
+ lexer->skip_token (stream_start_pos - 1);
+}
+
+AttributeParser::~AttributeParser () {}
+
std::unique_ptr<MetaItemInner>
AttributeParser::parse_meta_item_inner ()
{
// if first tok not identifier, not a "special" case one
- if (peek_token ()->get_id () != IDENTIFIER)
+ if (lexer->peek_token ()->get_id () != IDENTIFIER)
{
- switch (peek_token ()->get_id ())
+ switch (lexer->peek_token ()->get_id ())
{
case CHAR_LITERAL:
case STRING_LITERAL:
@@ -3522,48 +3554,46 @@ AttributeParser::parse_meta_item_inner ()
return parse_path_meta_item ();
default:
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
- get_token_description (peek_token ()->get_id ()));
+ get_token_description (
+ lexer->peek_token ()->get_id ()));
return nullptr;
}
}
// else, check for path
- if (peek_token (1)->get_id () == SCOPE_RESOLUTION)
+ if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION)
{
// path
return parse_path_meta_item ();
}
- auto ident = peek_token ()->as_string ();
- auto ident_locus = peek_token ()->get_locus ();
+ auto ident = lexer->peek_token ()->get_str ();
+ auto ident_locus = lexer->peek_token ()->get_locus ();
- if (is_end_meta_item_tok (peek_token (1)->get_id ()))
+ if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ()))
{
// meta word syntax
- skip_token ();
+ lexer->skip_token ();
return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus));
}
- if (peek_token (1)->get_id () == EQUAL)
+ if (lexer->peek_token (1)->get_id () == EQUAL)
{
// maybe meta name value str syntax - check next 2 tokens
- if (peek_token (2)->get_id () == STRING_LITERAL
- && is_end_meta_item_tok (peek_token (3)->get_id ()))
+ if (lexer->peek_token (2)->get_id () == STRING_LITERAL
+ && is_end_meta_item_tok (lexer->peek_token (3)->get_id ()))
{
// meta name value str syntax
- auto &value_tok = peek_token (2);
- auto value = value_tok->as_string ();
+ const_TokenPtr value_tok = lexer->peek_token (2);
+ auto value = value_tok->get_str ();
auto locus = value_tok->get_locus ();
- skip_token (2);
-
- // remove the quotes from the string value
- std::string raw_value = unquote_string (std::move (value));
+ lexer->skip_token (2);
return std::unique_ptr<MetaNameValueStr> (
- new MetaNameValueStr (ident, ident_locus, std::move (raw_value),
+ new MetaNameValueStr (ident, ident_locus, std::move (value),
locus));
}
else
@@ -3573,16 +3603,16 @@ AttributeParser::parse_meta_item_inner ()
}
}
- if (peek_token (1)->get_id () != LEFT_PAREN)
+ if (lexer->peek_token (1)->get_id () != LEFT_PAREN)
{
- rust_error_at (peek_token (1)->get_locus (),
+ rust_error_at (lexer->peek_token (1)->get_locus (),
"unexpected token '%s' after identifier in attribute",
- get_token_description (peek_token (1)->get_id ()));
+ get_token_description (lexer->peek_token (1)->get_id ()));
return nullptr;
}
// is it one of those special cases like not?
- if (peek_token ()->get_id () == IDENTIFIER)
+ if (lexer->peek_token ()->get_id () == IDENTIFIER)
{
return parse_path_meta_item ();
}
@@ -3661,15 +3691,15 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const
std::unique_ptr<MetaItem>
AttributeParser::parse_path_meta_item ()
{
- SimplePath path = parse_simple_path ();
+ SimplePath path = parser->parse_simple_path ();
if (path.is_empty ())
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"failed to parse simple path in attribute");
return nullptr;
}
- switch (peek_token ()->get_id ())
+ switch (lexer->peek_token ()->get_id ())
{
case LEFT_PAREN:
{
@@ -3681,31 +3711,26 @@ AttributeParser::parse_path_meta_item ()
}
case EQUAL:
{
- skip_token ();
+ lexer->skip_token ();
- location_t locus = peek_token ()->get_locus ();
- Literal lit = parse_literal ();
- if (lit.is_error ())
- {
- rust_error_at (peek_token ()->get_locus (),
- "failed to parse literal in attribute");
- return nullptr;
- }
- LiteralExpr expr (std::move (lit), {}, locus);
- // stream_pos++;
- /* shouldn't be required anymore due to parsing literal actually
- * skipping the token */
- return std::unique_ptr<MetaItemPathLit> (
- new MetaItemPathLit (std::move (path), std::move (expr)));
+ std::unique_ptr<Expr> expr = parser->parse_expr ();
+
+ // handle error
+ // parse_expr should already emit an error and return nullptr
+ if (!expr)
+ return nullptr;
+
+ return std::unique_ptr<MetaItemPathExpr> (
+ new MetaItemPathExpr (std::move (path), std::move (expr)));
}
case COMMA:
// just simple path
return std::unique_ptr<MetaItemPath> (
new MetaItemPath (std::move (path)));
default:
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
- get_token_description (peek_token ()->get_id ()));
+ get_token_description (lexer->peek_token ()->get_id ()));
return nullptr;
}
}
@@ -3715,41 +3740,41 @@ AttributeParser::parse_path_meta_item ()
std::vector<std::unique_ptr<MetaItemInner>>
AttributeParser::parse_meta_item_seq ()
{
- int vec_length = token_stream.size ();
std::vector<std::unique_ptr<MetaItemInner>> meta_items;
- if (peek_token ()->get_id () != LEFT_PAREN)
+ if (lexer->peek_token ()->get_id () != LEFT_PAREN)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"missing left paren in delim token tree");
return {};
}
- skip_token ();
+ lexer->skip_token ();
- while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN)
+ while (lexer->peek_token ()->get_id () != END_OF_FILE
+ && lexer->peek_token ()->get_id () != RIGHT_PAREN)
{
std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner ();
if (inner == nullptr)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"failed to parse inner meta item in attribute");
return {};
}
meta_items.push_back (std::move (inner));
- if (peek_token ()->get_id () != COMMA)
+ if (lexer->peek_token ()->get_id () != COMMA)
break;
- skip_token ();
+ lexer->skip_token ();
}
- if (peek_token ()->get_id () != RIGHT_PAREN)
+ if (lexer->peek_token ()->get_id () != RIGHT_PAREN)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"missing right paren in delim token tree");
return {};
}
- skip_token ();
+ lexer->skip_token ();
return meta_items;
}
@@ -3772,130 +3797,19 @@ DelimTokenTree::to_token_stream () const
return tokens;
}
-Literal
-AttributeParser::parse_literal ()
-{
- const std::unique_ptr<Token> &tok = peek_token ();
- switch (tok->get_id ())
- {
- case CHAR_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ());
- case STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::STRING,
- tok->get_type_hint ());
- case BYTE_CHAR_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ());
- case BYTE_STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::BYTE_STRING,
- tok->get_type_hint ());
- case RAW_STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::RAW_STRING,
- tok->get_type_hint ());
- case INT_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ());
- case FLOAT_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ());
- case TRUE_LITERAL:
- skip_token ();
- return Literal ("true", Literal::BOOL, tok->get_type_hint ());
- case FALSE_LITERAL:
- skip_token ();
- return Literal ("false", Literal::BOOL, tok->get_type_hint ());
- default:
- rust_error_at (tok->get_locus (), "expected literal - found '%s'",
- get_token_description (tok->get_id ()));
- return Literal::create_error ();
- }
-}
-
-SimplePath
-AttributeParser::parse_simple_path ()
-{
- bool has_opening_scope_res = false;
- if (peek_token ()->get_id () == SCOPE_RESOLUTION)
- {
- has_opening_scope_res = true;
- skip_token ();
- }
-
- std::vector<SimplePathSegment> segments;
-
- SimplePathSegment segment = parse_simple_path_segment ();
- if (segment.is_error ())
- {
- rust_error_at (
- peek_token ()->get_locus (),
- "failed to parse simple path segment in attribute simple path");
- return SimplePath::create_empty ();
- }
- segments.push_back (std::move (segment));
-
- while (peek_token ()->get_id () == SCOPE_RESOLUTION)
- {
- skip_token ();
-
- SimplePathSegment segment = parse_simple_path_segment ();
- if (segment.is_error ())
- {
- rust_error_at (
- peek_token ()->get_locus (),
- "failed to parse simple path segment in attribute simple path");
- return SimplePath::create_empty ();
- }
- segments.push_back (std::move (segment));
- }
- segments.shrink_to_fit ();
-
- return SimplePath (std::move (segments), has_opening_scope_res);
-}
-
-SimplePathSegment
-AttributeParser::parse_simple_path_segment ()
-{
- const std::unique_ptr<Token> &tok = peek_token ();
- switch (tok->get_id ())
- {
- case IDENTIFIER:
- skip_token ();
- return SimplePathSegment (tok->as_string (), tok->get_locus ());
- case SUPER:
- skip_token ();
- return SimplePathSegment ("super", tok->get_locus ());
- case SELF:
- skip_token ();
- return SimplePathSegment ("self", tok->get_locus ());
- case CRATE:
- skip_token ();
- return SimplePathSegment ("crate", tok->get_locus ());
- case DOLLAR_SIGN:
- if (peek_token (1)->get_id () == CRATE)
- {
- skip_token (1);
- return SimplePathSegment ("$crate", tok->get_locus ());
- }
- gcc_fallthrough ();
- default:
- rust_error_at (tok->get_locus (),
- "unexpected token '%s' in simple path segment",
- get_token_description (tok->get_id ()));
- return SimplePathSegment::create_error ();
- }
-}
-
std::unique_ptr<MetaItemLitExpr>
AttributeParser::parse_meta_item_lit ()
{
- location_t locus = peek_token ()->get_locus ();
- LiteralExpr lit_expr (parse_literal (), {}, locus);
+ std::unique_ptr<LiteralExpr> lit_expr = parser->parse_literal_expr ({});
+
+ // TODO: return nullptr instead?
+ if (!lit_expr)
+ lit_expr = std::unique_ptr<LiteralExpr> (
+ new LiteralExpr (Literal::create_error (), {},
+ lexer->peek_token ()->get_locus ()));
+
return std::unique_ptr<MetaItemLitExpr> (
- new MetaItemLitExpr (std::move (lit_expr)));
+ new MetaItemLitExpr (std::move (*lit_expr)));
}
bool
@@ -4104,10 +4018,12 @@ MetaNameValueStr::check_cfg_predicate (const Session &session) const
}
bool
-MetaItemPathLit::check_cfg_predicate (const Session &session) const
+MetaItemPathExpr::check_cfg_predicate (const Session &session) const
{
+ // FIXME: Accept path expressions
+ rust_assert (expr->is_literal ());
return session.options.target_data.has_key_value_pair (path.as_string (),
- lit.as_string ());
+ expr->as_string ());
}
std::vector<std::unique_ptr<Token>>
@@ -4195,8 +4111,10 @@ MetaListNameValueStr::to_attribute () const
}
Attribute
-MetaItemPathLit::to_attribute () const
+MetaItemPathExpr::to_attribute () const
{
+ rust_assert (expr->is_literal ());
+ auto &lit = static_cast<LiteralExpr &> (*expr);
return Attribute (path, std::unique_ptr<AttrInputLiteral> (
new AttrInputLiteral (lit)));
}
@@ -4299,11 +4217,12 @@ AttrInputMacro::AttrInputMacro (const AttrInputMacro &oth)
: macro (oth.macro->clone_macro_invocation_impl ())
{}
-void
+AttrInputMacro &
AttrInputMacro::operator= (const AttrInputMacro &oth)
{
macro = std::unique_ptr<MacroInvocation> (
oth.macro->clone_macro_invocation_impl ());
+ return *this;
}
/* Visitor implementations - these are short but inlining can't happen anyway
@@ -4365,7 +4284,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis)
}
void
-MetaItemPathLit::accept_vis (ASTVisitor &vis)
+MetaItemPathExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
@@ -4605,6 +4524,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis)
}
void
+TryExpr::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -5042,6 +4967,12 @@ FormatArgs::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
+void
+OffsetOf::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
std::string
FormatArgs::as_string () const
{
@@ -5049,6 +4980,12 @@ FormatArgs::as_string () const
return "FormatArgs";
}
+std::string
+OffsetOf::as_string () const
+{
+ return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
+}
+
location_t
FormatArgs::get_locus () const
{
@@ -5093,6 +5030,24 @@ FormatArgs::clone_expr_impl () const
return new FormatArgs (*this);
}
+std::vector<Attribute> &
+OffsetOf::get_outer_attrs ()
+{
+ rust_unreachable ();
+}
+
+void
+OffsetOf::set_outer_attrs (std::vector<Attribute>)
+{
+ rust_unreachable ();
+}
+
+Expr *
+OffsetOf::clone_expr_impl () const
+{
+ return new OffsetOf (*this);
+}
+
} // namespace AST
std::ostream &
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index cd586c6..2d2c5d0 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -83,6 +83,38 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
};
+/**
+ * Base function for reconstructing and asserting that the new NodeId is
+ * different from the old NodeId. It then wraps the given pointer into a unique
+ * pointer and returns it.
+ */
+template <typename T>
+std::unique_ptr<T>
+reconstruct_base (const T *instance)
+{
+ auto *reconstructed = instance->reconstruct_impl ();
+
+ rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
+
+ return std::unique_ptr<T> (reconstructed);
+}
+
+/**
+ * Reconstruct multiple items in a vector
+ */
+template <typename T>
+std::vector<std::unique_ptr<T>>
+reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
+{
+ std::vector<std::unique_ptr<T>> reconstructed;
+ reconstructed.reserve (to_reconstruct.size ());
+
+ for (const auto &elt : to_reconstruct)
+ reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
+
+ return reconstructed;
+}
+
// Delimiter types - used in macros and whatever.
enum DelimType
{
@@ -251,6 +283,7 @@ public:
std::vector<std::unique_ptr<Token>> to_token_stream () const override;
TokenId get_id () const { return tok_ref->get_id (); }
+ bool has_str () const { return tok_ref->has_str (); }
const std::string &get_str () const { return tok_ref->get_str (); }
location_t get_locus () const { return tok_ref->get_locus (); }
@@ -1040,7 +1073,7 @@ public:
Path,
Word,
NameValueStr,
- PathLit,
+ PathExpr,
Seq,
ListPaths,
ListNameValueStr,
@@ -1058,7 +1091,7 @@ public:
class MetaItemLitExpr;
// Forward decl - defined in rust-expr.h
-class MetaItemPathLit;
+class MetaItemPathExpr;
// Forward decl - defined in rust-macro.h
class MetaItemPath;
@@ -1275,6 +1308,7 @@ public:
LlvmInlineAsm,
Identifier,
FormatArgs,
+ OffsetOf,
MacroInvocation,
Borrow,
Dereference,
@@ -1286,6 +1320,7 @@ public:
TypeCast,
Assignment,
CompoundAssignment,
+ Try,
};
virtual Kind get_expr_kind () const = 0;
@@ -1480,6 +1515,10 @@ public:
return std::unique_ptr<Type> (clone_type_impl ());
}
+ // Similar to `clone_type`, but generates a new instance of the node with a
+ // different NodeId
+ std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); }
+
// virtual destructor
virtual ~Type () {}
@@ -1498,11 +1537,13 @@ public:
virtual location_t get_locus () const = 0;
NodeId get_node_id () const { return node_id; }
+ virtual Type *reconstruct_impl () const = 0;
protected:
Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
+ Type (NodeId node_id) : node_id (node_id) {}
- // Clone function implementation as pure virtual method
+ // Clone and reconstruct function implementations as pure virtual methods
virtual Type *clone_type_impl () const = 0;
NodeId node_id;
@@ -1518,6 +1559,13 @@ public:
return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
}
+ std::unique_ptr<TypeNoBounds> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
+ virtual TypeNoBounds *reconstruct_impl () const override = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
@@ -1552,6 +1600,11 @@ public:
return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
}
+ std::unique_ptr<TypeParamBound> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
virtual std::string as_string () const = 0;
NodeId get_node_id () const { return node_id; }
@@ -1560,10 +1613,14 @@ public:
virtual TypeParamBoundType get_bound_type () const = 0;
+ virtual TypeParamBound *reconstruct_impl () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
+ TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
TypeParamBound (NodeId node_id) : node_id (node_id) {}
NodeId node_id;
@@ -1625,6 +1682,10 @@ protected:
{
return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
}
+ Lifetime *reconstruct_impl () const override
+ {
+ return new Lifetime (lifetime_type, lifetime_name, locus);
+ }
};
/* Base generic parameter in AST. Abstract - can be represented by a Lifetime
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
index 3684092..2893e7b 100644
--- a/gcc/rust/ast/rust-builtin-ast-nodes.h
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -225,6 +225,59 @@ protected:
virtual Expr *clone_expr_impl () const override;
};
+/**
+ * The node associated with the builtin offset_of!() macro
+ */
+class OffsetOf : public Expr
+{
+public:
+ OffsetOf (std::unique_ptr<Type> &&type, Identifier field, location_t loc)
+ : type (std::move (type)), field (field), loc (loc)
+ {}
+
+ OffsetOf (const OffsetOf &other)
+ : type (other.type->clone_type ()), field (other.field), loc (other.loc),
+ marked_for_strip (other.marked_for_strip)
+ {}
+
+ OffsetOf &operator= (const OffsetOf &other)
+ {
+ type = other.type->clone_type ();
+ field = other.field;
+ loc = other.loc;
+ marked_for_strip = other.marked_for_strip;
+
+ return *this;
+ }
+
+ void accept_vis (AST::ASTVisitor &vis) override;
+
+ virtual location_t get_locus () const override { return loc; }
+ const Type &get_type () const { return *type; }
+ Type &get_type () { return *type; }
+ const Identifier &get_field () const { return field; }
+
+ bool is_expr_without_block () const override { return false; }
+
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ std::string as_string () const override;
+
+ std::vector<Attribute> &get_outer_attrs () override;
+ void set_outer_attrs (std::vector<Attribute>) override;
+ Expr *clone_expr_impl () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::OffsetOf; }
+
+private:
+ std::unique_ptr<Type> type;
+ Identifier field;
+
+ location_t loc;
+ bool marked_for_strip = false;
+};
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc
index ffc3470..5cc1c19 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.cc
+++ b/gcc/rust/ast/rust-desugar-for-loops.cc
@@ -17,7 +17,6 @@
// <http://www.gnu.org/licenses/>.
#include "rust-desugar-for-loops.h"
-#include "rust-ast-visitor.h"
#include "rust-ast.h"
#include "rust-hir-map.h"
#include "rust-path.h"
@@ -31,32 +30,10 @@ namespace AST {
DesugarForLoops::DesugarForLoops () {}
-void
-DesugarForLoops::go (AST::Crate &crate)
-{
- DefaultASTVisitor::visit (crate);
-}
-
-static void
-replace_for_loop (std::unique_ptr<Expr> &for_loop,
- std::unique_ptr<Expr> &&expanded)
-{
- for_loop = std::move (expanded);
-}
-
-MatchArm
-DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path)
-{
- auto patterns = std::vector<std::unique_ptr<Pattern>> ();
- patterns.emplace_back (std::move (path));
-
- return MatchArm (std::move (patterns), loc);
-}
-
MatchCase
DesugarForLoops::DesugarCtx::make_break_arm ()
{
- auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression (
+ auto arm = builder.match_arm (std::unique_ptr<Pattern> (new PathInExpression (
builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
auto break_expr
@@ -79,7 +56,7 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
builder.path_in_expression (LangItem::Kind::OPTION_SOME),
std::move (pattern_item)));
- auto val_arm = make_match_arm (std::move (pattern));
+ auto val_arm = builder.match_arm (std::move (pattern));
auto next = builder.identifier (DesugarCtx::next_value_id);
@@ -91,14 +68,8 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
return MatchCase (std::move (val_arm), std::move (assignment));
}
-std::unique_ptr<Stmt>
-DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr)
-{
- return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true));
-}
-
std::unique_ptr<Expr>
-DesugarForLoops::desugar (AST::ForLoopExpr &expr)
+DesugarForLoops::desugar (ForLoopExpr &expr)
{
auto ctx = DesugarCtx (expr.get_locus ());
@@ -140,10 +111,10 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr)
auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
loop_stmts.emplace_back (std::move (let_next));
- loop_stmts.emplace_back (ctx.statementify (std::move (match_next)));
+ loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_next)));
loop_stmts.emplace_back (std::move (let_pat));
loop_stmts.emplace_back (
- ctx.statementify (expr.get_loop_block ().clone_expr ()));
+ ctx.builder.statementify (expr.get_loop_block ().clone_expr ()));
// loop {
// <let_next>;
@@ -170,34 +141,18 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr)
}
void
-DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr)
+DesugarForLoops::go (std::unique_ptr<Expr> &ptr)
{
- if (expr->get_expr_kind () == AST::Expr::Kind::Loop)
- {
- auto &loop = static_cast<AST::BaseLoopExpr &> (*expr);
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
- if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For)
- {
- auto &for_loop = static_cast<AST::ForLoopExpr &> (loop);
+ auto &loop = static_cast<BaseLoopExpr &> (*ptr);
- auto desugared = desugar (for_loop);
-
- replace_for_loop (expr, std::move (desugared));
- }
- }
-}
-
-void
-DesugarForLoops::visit (AST::BlockExpr &block)
-{
- for (auto &stmt : block.get_statements ())
- if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr)
- maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ());
+ rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::For);
- if (block.has_tail_expr ())
- maybe_desugar_expr (block.get_tail_expr_ptr ());
+ auto &for_loop = static_cast<ForLoopExpr &> (loop);
+ auto desugared = DesugarForLoops ().desugar (for_loop);
- DefaultASTVisitor::visit (block);
+ ptr = std::move (desugared);
}
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h
index 7beb692..96b63ff 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.h
+++ b/gcc/rust/ast/rust-desugar-for-loops.h
@@ -20,7 +20,6 @@
#define RUST_DESUGAR_FOR_LOOPS_H
#include "rust-ast-builder.h"
-#include "rust-ast-visitor.h"
#include "rust-expr.h"
namespace Rust {
@@ -69,15 +68,14 @@ namespace AST {
// of the way the typechecker is currently structured, where it will fetch name
// resolution information in order to typecheck paths - which technically isn't
// necessary.
-class DesugarForLoops : public DefaultASTVisitor
+class DesugarForLoops
{
- using DefaultASTVisitor::visit;
-
public:
- DesugarForLoops ();
- void go (AST::Crate &);
+ static void go (std::unique_ptr<Expr> &ptr);
private:
+ DesugarForLoops ();
+
struct DesugarCtx
{
DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
@@ -85,10 +83,8 @@ private:
Builder builder;
location_t loc;
- MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern);
MatchCase make_break_arm ();
MatchCase make_continue_arm ();
- std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr);
constexpr static const char *continue_pattern_id = "#val";
constexpr static const char *next_value_id = "#__next";
@@ -96,10 +92,7 @@ private:
constexpr static const char *result_id = "#result";
};
- std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr);
- void maybe_desugar_expr (std::unique_ptr<Expr> &expr);
-
- void visit (AST::BlockExpr &) override;
+ std::unique_ptr<Expr> desugar (ForLoopExpr &expr);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc
index 4d2933b..01400d8 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.cc
+++ b/gcc/rust/ast/rust-desugar-question-mark.cc
@@ -18,7 +18,6 @@
#include "rust-desugar-question-mark.h"
#include "rust-ast-builder.h"
-#include "rust-ast-visitor.h"
namespace Rust {
namespace AST {
@@ -26,42 +25,14 @@ namespace AST {
DesugarQuestionMark::DesugarQuestionMark () {}
void
-DesugarQuestionMark::go (AST::Crate &crate)
+DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr)
{
- DesugarQuestionMark::visit (crate);
-}
-
-void
-DesugarQuestionMark::visit (ExprStmt &stmt)
-{
- if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (stmt.get_expr_ptr ());
-
- DefaultASTVisitor::visit (stmt);
-}
-
-void
-DesugarQuestionMark::visit (CallExpr &call)
-{
- if (call.get_function_expr ().get_expr_kind ()
- == Expr::Kind::ErrorPropagation)
- desugar_and_replace (call.get_function_expr_ptr ());
-
- for (auto &arg : call.get_params ())
- if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (arg);
-
- DefaultASTVisitor::visit (call);
-}
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::ErrorPropagation);
-void
-DesugarQuestionMark::visit (LetStmt &stmt)
-{
- if (stmt.has_init_expr ()
- && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (stmt.get_init_expr_ptr ());
+ auto original = static_cast<ErrorPropagationExpr &> (*ptr);
+ auto desugared = DesugarQuestionMark ().desugar (original);
- DefaultASTVisitor::visit (stmt);
+ ptr = std::move (desugared);
}
MatchArm
@@ -99,6 +70,12 @@ ok_case (Builder &builder)
MatchCase
err_case (Builder &builder)
{
+ // TODO: We need to handle the case where there is an enclosing `try {}`
+ // block, as that will create an additional block label that we can break to.
+ // This allows try blocks to use the question mark operator without having the
+ // offending statement early return from the enclosing function
+ // FIXME: How to mark that there is an enclosing block label?
+
auto val = builder.identifier_pattern ("err");
auto patterns = std::vector<std::unique_ptr<Pattern>> ();
@@ -154,14 +131,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
expr.get_locus ()));
}
-void
-DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr)
-{
- auto original = static_cast<ErrorPropagationExpr &> (*ptr);
- auto desugared = desugar (original);
-
- ptr = std::move (desugared);
-}
-
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-question-mark.h b/gcc/rust/ast/rust-desugar-question-mark.h
index e4c513f..542c52b 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.h
+++ b/gcc/rust/ast/rust-desugar-question-mark.h
@@ -19,9 +19,7 @@
#ifndef RUST_DESUGAR_QUESTION_MARK
#define RUST_DESUGAR_QUESTION_MARK
-#include "rust-ast-visitor.h"
#include "rust-expr.h"
-#include "rust-stmt.h"
namespace Rust {
namespace AST {
@@ -56,21 +54,15 @@ namespace AST {
// }
// }
// ```
-class DesugarQuestionMark : public DefaultASTVisitor
+class DesugarQuestionMark
{
- using DefaultASTVisitor::visit;
-
public:
- DesugarQuestionMark ();
- void go (AST::Crate &);
+ static void go (std::unique_ptr<Expr> &ptr);
private:
- void desugar_and_replace (std::unique_ptr<Expr> &ptr);
- std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
+ DesugarQuestionMark ();
- void visit (AST::ExprStmt &) override;
- void visit (AST::CallExpr &) override;
- void visit (AST::LetStmt &) override;
+ std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-try-block.cc b/gcc/rust/ast/rust-desugar-try-block.cc
new file mode 100644
index 0000000..07f06aa
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-try-block.cc
@@ -0,0 +1,62 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-desugar-try-block.h"
+#include "rust-ast-builder.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarTryBlock::DesugarTryBlock () {}
+
+void
+DesugarTryBlock::go (std::unique_ptr<Expr> &ptr)
+{
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Try);
+
+ auto original = static_cast<TryExpr &> (*ptr);
+ auto desugared = DesugarTryBlock ().desugar (original);
+
+ ptr = std::move (desugared);
+}
+
+std::unique_ptr<Expr>
+DesugarTryBlock::desugar (TryExpr &expr)
+{
+ auto builder = Builder (expr.get_locus ());
+ auto &block = expr.get_block_expr ();
+
+ if (block.has_statements ())
+ rust_sorry_at (expr.get_locus (),
+ "cannot desugar try-blocks with statements");
+
+ auto tail_expr = builder.tuple ();
+
+ if (block.has_tail_expr ())
+ tail_expr = block.get_tail_expr ().clone_expr ();
+
+ // Wrap in Try::from_ok call
+ auto from_ok = builder.path_in_expression (LangItem::Kind::TRY_FROM_OK);
+ auto call = builder.call (ptrify (from_ok), std::move (tail_expr));
+
+ return builder.block (std::move (call));
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-try-block.h b/gcc/rust/ast/rust-desugar-try-block.h
new file mode 100644
index 0000000..bfd0463
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-try-block.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DESUGAR_TRY_BLOCK
+#define RUST_DESUGAR_TRY_BLOCK
+
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// FIXME: Add documentation
+class DesugarTryBlock
+{
+public:
+ static void go (std::unique_ptr<Expr> &ptr);
+
+private:
+ DesugarTryBlock ();
+
+ std::unique_ptr<Expr> desugar (TryExpr &);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_TRY_BLOCK
diff --git a/gcc/rust/ast/rust-desugar-while-let.cc b/gcc/rust/ast/rust-desugar-while-let.cc
new file mode 100644
index 0000000..5eadc59
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-while-let.cc
@@ -0,0 +1,104 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-desugar-while-let.h"
+#include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-path.h"
+#include "rust-pattern.h"
+#include "rust-stmt.h"
+#include "rust-expr.h"
+#include "rust-ast-builder.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarWhileLet::DesugarWhileLet () {}
+
+MatchCase
+DesugarWhileLet::DesugarCtx::make_break_arm ()
+{
+ auto arm = builder.match_arm (builder.wildcard ());
+
+ auto break_expr
+ = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
+
+ return MatchCase (std::move (arm), std::move (break_expr));
+}
+
+MatchCase
+DesugarWhileLet::DesugarCtx::make_continue_arm (
+ std::unique_ptr<Pattern> &&pattern, std::unique_ptr<BlockExpr> &&body)
+{
+ auto arm = builder.match_arm (std::move (pattern));
+
+ return MatchCase (std::move (arm), std::move (body));
+}
+
+std::unique_ptr<Expr>
+DesugarWhileLet::desugar (WhileLetLoopExpr &expr)
+{
+ rust_assert (expr.get_patterns ().size () == 1);
+
+ auto pattern = expr.get_patterns ()[0]->clone_pattern ();
+ auto body = expr.get_loop_block ().clone_block_expr ();
+ auto scrutinee = expr.get_scrutinee_expr ().clone_expr ();
+
+ auto ctx = DesugarCtx (expr.get_locus ());
+
+ // _ => break,
+ auto break_arm = ctx.make_break_arm ();
+
+ // <pattern> => <body>,
+ auto continue_arm
+ = ctx.make_continue_arm (std::move (pattern), std::move (body));
+
+ // match <scrutinee> {
+ // <continue_arm>
+ // <break_arm>
+ // }
+ auto match_expr
+ = ctx.builder.match (std::move (scrutinee),
+ {std::move (continue_arm), std::move (break_arm)});
+
+ auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
+ loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_expr)));
+
+ // loop {
+ // <match_expr>
+ // }
+ return ctx.builder.loop (std::move (loop_stmts));
+}
+
+void
+DesugarWhileLet::go (std::unique_ptr<Expr> &ptr)
+{
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
+
+ auto &loop = static_cast<BaseLoopExpr &> (*ptr);
+
+ rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::WhileLet);
+
+ auto &while_let = static_cast<WhileLetLoopExpr &> (loop);
+ auto desugared = DesugarWhileLet ().desugar (while_let);
+
+ ptr = std::move (desugared);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-while-let.h b/gcc/rust/ast/rust-desugar-while-let.h
new file mode 100644
index 0000000..60e0693
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-while-let.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_DESUGAR_WHILE_LET_H
+#define RUST_DESUGAR_WHILE_LET_H
+
+#include "rust-ast-builder.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// Desugar while-let into a set of other AST nodes. The desugar is of the
+// following form:
+//
+// ```
+// whilet let <pat> = <expr> <body>
+// ```
+//
+// becomes:
+//
+// ```
+// loop {
+// match <expr> {
+// <pat> => <body>,
+// _ => break
+// }
+// }
+// ```
+class DesugarWhileLet
+{
+public:
+ static void go (std::unique_ptr<Expr> &ptr);
+
+private:
+ DesugarWhileLet ();
+
+ struct DesugarCtx
+ {
+ DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
+
+ Builder builder;
+ location_t loc;
+
+ MatchCase make_break_arm ();
+ MatchCase make_continue_arm (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<BlockExpr> &&body);
+ };
+
+ std::unique_ptr<Expr> desugar (WhileLetLoopExpr &expr);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_WHILE_LET_H
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 8f44d58..7b0df25 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1,6 +1,7 @@
#ifndef RUST_AST_EXPR_H
#define RUST_AST_EXPR_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-path.h"
@@ -182,9 +183,13 @@ public:
AttrInputMacro (AttrInputMacro &&oth) : macro (std::move (oth.macro)) {}
- void operator= (const AttrInputMacro &oth);
+ AttrInputMacro &operator= (const AttrInputMacro &oth);
- void operator= (AttrInputMacro &&oth) { macro = std::move (oth.macro); }
+ AttrInputMacro &operator= (AttrInputMacro &&oth)
+ {
+ macro = std::move (oth.macro);
+ return *this;
+ }
std::string as_string () const override;
@@ -244,36 +249,50 @@ protected:
}
};
-// more generic meta item "path = lit" form
-class MetaItemPathLit : public MetaItem
+// more generic meta item "path = expr" form
+class MetaItemPathExpr : public MetaItem
{
SimplePath path;
- LiteralExpr lit;
+ std::unique_ptr<Expr> expr;
public:
- MetaItemPathLit (SimplePath path, LiteralExpr lit_expr)
- : path (std::move (path)), lit (std::move (lit_expr))
+ MetaItemPathExpr (SimplePath path, std::unique_ptr<Expr> expr)
+ : path (std::move (path)), expr (std::move (expr))
{}
+ MetaItemPathExpr (const MetaItemPathExpr &other)
+ : MetaItem (other), path (other.path), expr (other.expr->clone_expr ())
+ {}
+
+ MetaItemPathExpr (MetaItemPathExpr &&) = default;
+
+ MetaItemPathExpr &operator= (MetaItemPathExpr &&) = default;
+
+ MetaItemPathExpr operator= (const MetaItemPathExpr &other)
+ {
+ MetaItem::operator= (other);
+ path = other.path;
+ expr = other.expr->clone_expr ();
+ return *this;
+ }
+
SimplePath get_path () const { return path; }
SimplePath &get_path () { return path; }
- LiteralExpr get_literal () const { return lit; }
-
- LiteralExpr &get_literal () { return lit; }
+ Expr &get_expr () { return *expr; }
std::string as_string () const override
{
- return path.as_string () + " = " + lit.as_string ();
+ return path.as_string () + " = " + expr->as_string ();
}
MetaItem::ItemKind get_item_kind () const override
{
- return MetaItem::ItemKind::PathLit;
+ return MetaItem::ItemKind::PathExpr;
}
- // There are two Locations in MetaItemPathLit (path and lit_expr),
+ // There are two Locations in MetaItemPathExpr (path and expr),
// we have no idea use which of them, just simply return UNKNOWN_LOCATION
// now.
// Maybe we will figure out when we really need the location in the future.
@@ -289,9 +308,9 @@ public:
protected:
// Use covariance to implement clone function as returning this type
- MetaItemPathLit *clone_meta_item_inner_impl () const override
+ MetaItemPathExpr *clone_meta_item_inner_impl () const override
{
- return new MetaItemPathLit (*this);
+ return new MetaItemPathExpr (*this);
}
};
@@ -395,6 +414,8 @@ public:
return *main_or_left_expr;
}
+ bool has_borrow_expr () const { return main_or_left_expr != nullptr; }
+
bool get_is_mut () const { return mutability == Mutability::Mut; }
Mutability get_mutability () const { return mutability; }
@@ -1160,11 +1181,11 @@ protected:
// Value array elements
class ArrayElemsValues : public ArrayElems
{
- std::vector<std::unique_ptr<Expr> > values;
+ std::vector<std::unique_ptr<Expr>> values;
location_t locus;
public:
- ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems, location_t locus)
+ ArrayElemsValues (std::vector<std::unique_ptr<Expr>> elems, location_t locus)
: ArrayElems (), values (std::move (elems)), locus (locus)
{}
@@ -1192,14 +1213,16 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_values () const
+ const std::vector<std::unique_ptr<Expr>> &get_values () const
{
return values;
}
- std::vector<std::unique_ptr<Expr> > &get_values () { return values; }
+ std::vector<std::unique_ptr<Expr>> &get_values () { return values; }
size_t get_num_values () const { return values.size (); }
@@ -1248,6 +1271,8 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_block" better?
@@ -1474,7 +1499,7 @@ class TupleExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
std::vector<Attribute> inner_attrs;
- std::vector<std::unique_ptr<Expr> > tuple_elems;
+ std::vector<std::unique_ptr<Expr>> tuple_elems;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -1494,7 +1519,7 @@ public:
outer_attrs = std::move (new_attrs);
}
- TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements,
+ TupleExpr (std::vector<std::unique_ptr<Expr>> tuple_elements,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
@@ -1545,14 +1570,11 @@ public:
bool is_marked_for_strip () const override { return marked_for_strip; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const
- {
- return tuple_elems;
- }
- std::vector<std::unique_ptr<Expr> > &get_tuple_elems ()
+ const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const
{
return tuple_elems;
}
+ std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; }
bool is_unit () const { return tuple_elems.size () == 0; }
@@ -1777,6 +1799,8 @@ public:
std::string as_string () const;
+ location_t get_locus () const { return locus; }
+
// TODO: is this better? Or is a "vis_block" better?
Expr &get_base_struct ()
{
@@ -1974,7 +1998,7 @@ protected:
class StructExprStructFields : public StructExprStruct
{
// std::vector<StructExprField> fields;
- std::vector<std::unique_ptr<StructExprField> > fields;
+ std::vector<std::unique_ptr<StructExprField>> fields;
// bool has_struct_base;
StructBase struct_base;
@@ -1987,8 +2011,8 @@ public:
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
PathInExpression struct_path,
- std::vector<std::unique_ptr<StructExprField> > expr_fields,
- location_t locus, StructBase base_struct = StructBase::error (),
+ std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
+ StructBase base_struct = StructBase::error (),
std::vector<Attribute> inner_attribs = std::vector<Attribute> (),
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: StructExprStruct (std::move (struct_path), std::move (inner_attribs),
@@ -2025,11 +2049,11 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<std::unique_ptr<StructExprField> > &get_fields ()
+ std::vector<std::unique_ptr<StructExprField>> &get_fields ()
{
return fields;
}
- const std::vector<std::unique_ptr<StructExprField> > &get_fields () const
+ const std::vector<std::unique_ptr<StructExprField>> &get_fields () const
{
return fields;
}
@@ -2086,7 +2110,7 @@ class CallExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
std::unique_ptr<Expr> function;
- std::vector<std::unique_ptr<Expr> > params;
+ std::vector<std::unique_ptr<Expr>> params;
location_t locus;
public:
@@ -2095,7 +2119,7 @@ public:
std::string as_string () const override;
CallExpr (std::unique_ptr<Expr> function_expr,
- std::vector<std::unique_ptr<Expr> > function_params,
+ std::vector<std::unique_ptr<Expr>> function_params,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
function (std::move (function_expr)),
@@ -2152,11 +2176,11 @@ public:
bool is_marked_for_strip () const override { return function == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_params () const
+ const std::vector<std::unique_ptr<Expr>> &get_params () const
{
return params;
}
- std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+ std::vector<std::unique_ptr<Expr>> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_function_expr ()
@@ -2192,7 +2216,7 @@ class MethodCallExpr : public ExprWithoutBlock
std::vector<Attribute> outer_attrs;
std::unique_ptr<Expr> receiver;
PathExprSegment method_name;
- std::vector<std::unique_ptr<Expr> > params;
+ std::vector<std::unique_ptr<Expr>> params;
location_t locus;
public:
@@ -2200,7 +2224,7 @@ public:
MethodCallExpr (std::unique_ptr<Expr> call_receiver,
PathExprSegment method_path,
- std::vector<std::unique_ptr<Expr> > method_params,
+ std::vector<std::unique_ptr<Expr>> method_params,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
receiver (std::move (call_receiver)),
@@ -2256,11 +2280,11 @@ public:
bool is_marked_for_strip () const override { return receiver == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_params () const
+ const std::vector<std::unique_ptr<Expr>> &get_params () const
{
return params;
}
- std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+ std::vector<std::unique_ptr<Expr>> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_receiver_expr ()
@@ -2587,7 +2611,7 @@ class BlockExpr : public ExprWithBlock
{
std::vector<Attribute> outer_attrs;
std::vector<Attribute> inner_attrs;
- std::vector<std::unique_ptr<Stmt> > statements;
+ std::vector<std::unique_ptr<Stmt>> statements;
std::unique_ptr<Expr> expr;
tl::optional<LoopLabel> label;
location_t start_locus;
@@ -2603,7 +2627,7 @@ public:
// Returns whether the block contains a final expression.
bool has_tail_expr () const { return expr != nullptr; }
- BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
+ BlockExpr (std::vector<std::unique_ptr<Stmt>> block_statements,
std::unique_ptr<Expr> block_expr,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs,
@@ -2682,11 +2706,11 @@ public:
const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
- const std::vector<std::unique_ptr<Stmt> > &get_statements () const
+ const std::vector<std::unique_ptr<Stmt>> &get_statements () const
{
return statements;
}
- std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
+ std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_tail_expr ()
@@ -2751,24 +2775,42 @@ protected:
class AnonConst : public ExprWithBlock
{
public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference,
+ };
+
AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION)
- : ExprWithBlock (), locus (locus), expr (std::move (expr))
+ : ExprWithBlock (), locus (locus), kind (Kind::Explicit),
+ expr (std::move (expr))
{
- rust_assert (this->expr);
+ rust_assert (this->expr.value ());
}
+ AnonConst (location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference),
+ expr (tl::nullopt)
+ {}
+
AnonConst (const AnonConst &other)
{
node_id = other.node_id;
locus = other.locus;
- expr = other.expr->clone_expr ();
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
}
AnonConst operator= (const AnonConst &other)
{
node_id = other.node_id;
locus = other.locus;
- expr = other.expr->clone_expr ();
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
return *this;
}
@@ -2778,7 +2820,13 @@ public:
Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; }
location_t get_locus () const override { return locus; }
- Expr &get_inner_expr () { return *expr; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (expr.has_value ());
+ return *expr.value ();
+ }
+
NodeId get_node_id () const override { return node_id; }
/* FIXME: AnonConst are always "internal" and should not have outer attributes
@@ -2799,9 +2847,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
private:
location_t locus;
- std::unique_ptr<Expr> expr;
+ Kind kind;
+ tl::optional<std::unique_ptr<Expr>> expr;
AnonConst *clone_expr_with_block_impl () const override
{
@@ -3694,6 +3745,82 @@ protected:
}
};
+// Try expression AST node representation
+class TryExpr : public ExprWithBlock
+{
+ std::vector<Attribute> outer_attrs;
+ std::unique_ptr<BlockExpr> block_expr;
+ location_t locus;
+
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor for ReturnExpr.
+ TryExpr (std::unique_ptr<BlockExpr> block_expr,
+ std::vector<Attribute> outer_attribs, location_t locus)
+ : outer_attrs (std::move (outer_attribs)),
+ block_expr (std::move (block_expr)), locus (locus)
+ {
+ rust_assert (this->block_expr);
+ }
+
+ // Copy constructor with clone
+ TryExpr (TryExpr const &other)
+ : ExprWithBlock (other), outer_attrs (other.outer_attrs),
+ block_expr (other.block_expr->clone_block_expr ()), locus (other.locus),
+ marked_for_strip (other.marked_for_strip)
+ {}
+
+ // Overloaded assignment operator to clone return_expr pointer
+ TryExpr &operator= (TryExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
+ outer_attrs = other.outer_attrs;
+
+ block_expr = other.block_expr->clone_block_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ TryExpr (TryExpr &&other) = default;
+ TryExpr &operator= (TryExpr &&other) = default;
+
+ location_t get_locus () const override final { return locus; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ BlockExpr &get_block_expr () { return *block_expr; }
+
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector<Attribute> new_attrs) override
+ {
+ outer_attrs = std::move (new_attrs);
+ }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Try; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TryExpr *clone_expr_with_block_impl () const override
+ {
+ return new TryExpr (*this);
+ }
+};
+
// Forward decl - defined in rust-macro.h
class MacroInvocation;
@@ -3969,14 +4096,14 @@ protected:
class WhileLetLoopExpr : public BaseLoopExpr
{
// MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
std::unique_ptr<Expr> scrutinee;
public:
std::string as_string () const override;
// Constructor with a loop label
- WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
tl::optional<LoopLabel> loop_label = tl::nullopt,
@@ -4030,11 +4157,11 @@ public:
}
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4317,7 +4444,7 @@ protected:
class IfLetExpr : public ExprWithBlock
{
std::vector<Attribute> outer_attrs;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
std::unique_ptr<Expr> value;
std::unique_ptr<BlockExpr> if_block;
location_t locus;
@@ -4325,7 +4452,7 @@ class IfLetExpr : public ExprWithBlock
public:
std::string as_string () const override;
- IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ IfLetExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
std::vector<Attribute> outer_attrs, location_t locus)
: outer_attrs (std::move (outer_attrs)),
@@ -4419,11 +4546,11 @@ public:
}
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4463,11 +4590,11 @@ class IfLetExprConseqElse : public IfLetExpr
public:
std::string as_string () const override;
- IfLetExprConseqElse (
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
- std::unique_ptr<ExprWithBlock> else_block,
- std::vector<Attribute> outer_attrs, location_t locus)
+ IfLetExprConseqElse (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
+ std::unique_ptr<Expr> value,
+ std::unique_ptr<BlockExpr> if_block,
+ std::unique_ptr<ExprWithBlock> else_block,
+ std::vector<Attribute> outer_attrs, location_t locus)
: IfLetExpr (std::move (match_arm_patterns), std::move (value),
std::move (if_block), std::move (outer_attrs), locus),
else_block (std::move (else_block))
@@ -4520,7 +4647,7 @@ struct MatchArm
private:
std::vector<Attribute> outer_attrs;
// MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
// bool has_match_arm_guard;
// inlined from MatchArmGuard
@@ -4533,7 +4660,7 @@ public:
bool has_match_arm_guard () const { return guard_expr != nullptr; }
// Constructor for match arm with a guard expression
- MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
location_t locus, std::unique_ptr<Expr> guard_expr = nullptr,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)),
@@ -4585,7 +4712,7 @@ public:
static MatchArm create_error ()
{
location_t locus = UNDEF_LOCATION;
- return MatchArm (std::vector<std::unique_ptr<Pattern> > (), locus);
+ return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus);
}
std::string as_string () const;
@@ -4607,11 +4734,11 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc
new file mode 100644
index 0000000..9f6a62f
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.cc
@@ -0,0 +1,118 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-expression-yeast.h"
+#include "rust-ast-visitor.h"
+#include "rust-desugar-question-mark.h"
+#include "rust-desugar-try-block.h"
+#include "rust-desugar-for-loops.h"
+#include "rust-ast-full.h"
+#include "rust-desugar-while-let.h"
+#include "rust-expr.h"
+#include "rust-stmt.h"
+
+namespace Rust {
+namespace AST {
+
+void
+ExpressionYeast::go (AST::Crate &crate)
+{
+ DefaultASTVisitor::visit (crate);
+}
+
+void
+ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr)
+{
+ auto &loop = static_cast<BaseLoopExpr &> (*loop_expr.get ());
+
+ switch (loop.get_loop_kind ())
+ {
+ case BaseLoopExpr::Kind::For:
+ DesugarForLoops::go (loop_expr);
+ break;
+ case BaseLoopExpr::Kind::WhileLet:
+ DesugarWhileLet::go (loop_expr);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr)
+{
+ switch (expr->get_expr_kind ())
+ {
+ case Expr::Kind::ErrorPropagation:
+ DesugarQuestionMark::go (expr);
+ break;
+ case Expr::Kind::Try:
+ DesugarTryBlock::go (expr);
+ break;
+ case Expr::Kind::Loop:
+ dispatch_loops (expr);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+ExpressionYeast::visit (ExprStmt &stmt)
+{
+ dispatch (stmt.get_expr_ptr ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+void
+ExpressionYeast::visit (CallExpr &call)
+{
+ dispatch (call.get_function_expr_ptr ());
+
+ for (auto &arg : call.get_params ())
+ dispatch (arg);
+
+ DefaultASTVisitor::visit (call);
+}
+
+void
+ExpressionYeast::visit (BlockExpr &block)
+{
+ for (auto &stmt : block.get_statements ())
+ if (stmt->get_stmt_kind () == Stmt::Kind::Expr)
+ dispatch (static_cast<ExprStmt &> (*stmt).get_expr_ptr ());
+
+ if (block.has_tail_expr ())
+ dispatch (block.get_tail_expr_ptr ());
+
+ DefaultASTVisitor::visit (block);
+}
+
+void
+ExpressionYeast::visit (LetStmt &stmt)
+{
+ if (stmt.has_init_expr ())
+ dispatch (stmt.get_init_expr_ptr ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h
new file mode 100644
index 0000000..855918f
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_EXPRESSION_YEAST
+#define RUST_EXPRESSION_YEAST
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-desugar-question-mark.h"
+
+namespace Rust {
+namespace AST {
+
+// This visitor takes care of all the expression desugars: try-blocks,
+// error-propagation, etc.
+class ExpressionYeast : public AST::DefaultASTVisitor
+{
+ using AST::DefaultASTVisitor::visit;
+
+public:
+ void go (AST::Crate &);
+
+private:
+ // Dispatch to the proper desugar
+ void dispatch (std::unique_ptr<Expr> &expr);
+ void dispatch_loops (std::unique_ptr<Expr> &loop_expr);
+
+ void visit (AST::ExprStmt &) override;
+ void visit (AST::CallExpr &) override;
+ void visit (AST::LetStmt &) override;
+ void visit (AST::BlockExpr &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_EXPRESSION_YEAST
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc01e57..4165075 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -27,6 +27,11 @@
#include "rust-macro-builtins.h"
namespace Rust {
+
+// forward declarations for AttributeParser
+class MacroInvocLexer;
+template <typename ManagedTokenSource> class Parser;
+
namespace AST {
class MacroFragSpec
@@ -756,22 +761,16 @@ private:
std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_pattern_impl () const final override
{
return clone_macro_invocation_impl ();
}
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_expr_without_block_impl () const final override
{
return clone_macro_invocation_impl ();
}
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_type_no_bounds_impl () const final override
{
return clone_macro_invocation_impl ();
@@ -788,6 +787,20 @@ public:
return new MacroInvocation (*this);
}
+ std::unique_ptr<MacroInvocation> reconstruct_macro_invocation () const
+ {
+ return nullptr;
+ // return reconstruct (this,
+ // &MacroInvocation::reconstruct_macro_invocation_impl);
+ }
+
+ MacroInvocation *reconstruct_impl () const override
+ {
+ return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs,
+ locus, is_semi_coloned,
+ reconstruct_vec (pending_eager_invocs));
+ }
+
void add_semicolon () override { is_semi_coloned = true; }
Pattern::Kind get_pattern_kind () override
@@ -1108,16 +1121,14 @@ struct AttributeParser
{
private:
// TODO: might as well rewrite to use lexer tokens
- std::vector<std::unique_ptr<Token>> token_stream;
- int stream_pos;
+ std::unique_ptr<MacroInvocLexer> lexer;
+ std::unique_ptr<Parser<MacroInvocLexer>> parser;
public:
AttributeParser (std::vector<std::unique_ptr<Token>> token_stream,
- int stream_start_pos = 0)
- : token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
- {}
+ int stream_start_pos = 0);
- ~AttributeParser () = default;
+ ~AttributeParser ();
std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
@@ -1126,24 +1137,10 @@ private:
std::unique_ptr<MetaItemInner> parse_meta_item_inner ();
// Returns whether token can end a meta item.
bool is_end_meta_item_tok (TokenId id) const;
- // Parses a simple path.
- SimplePath parse_simple_path ();
- // Parses a segment of a simple path (but not scope resolution operator).
- SimplePathSegment parse_simple_path_segment ();
// Parses a MetaItemLitExpr.
std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit ();
- // Parses a literal.
- Literal parse_literal ();
// Parses a meta item that begins with a simple path.
std::unique_ptr<MetaItem> parse_path_meta_item ();
-
- // TODO: should this be const?
- std::unique_ptr<Token> &peek_token (int i = 0)
- {
- return token_stream[stream_pos + i];
- }
-
- void skip_token (int i = 0) { stream_pos += 1 + i; }
};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 11f7248..a1b19d5 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -391,6 +391,13 @@ public:
return default_value.value ();
}
+ tl::optional<GenericArg> &get_default_value () { return default_value; }
+
+ const tl::optional<GenericArg> &get_default_value () const
+ {
+ return default_value;
+ }
+
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -779,6 +786,11 @@ public:
{
return new TypePathSegment (*this);
}
+ virtual TypePathSegment *reconstruct_impl () const
+ {
+ return new TypePathSegment (lang_item, ident_segment,
+ has_separating_scope_resolution, locus);
+ }
public:
virtual ~TypePathSegment () {}
@@ -790,6 +802,11 @@ public:
{
return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
}
+ // Unique pointer custom reconstruct function
+ std::unique_ptr<TypePathSegment> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
TypePathSegment (PathIdentSegment ident_segment,
bool has_separating_scope_resolution, location_t locus)
@@ -814,6 +831,15 @@ public:
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
+ // General constructor
+ TypePathSegment (tl::optional<LangItem::Kind> lang_item,
+ tl::optional<PathIdentSegment> ident_segment,
+ bool has_separating_scope_resolution, location_t locus)
+ : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
+ has_separating_scope_resolution (has_separating_scope_resolution),
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
+
TypePathSegment (TypePathSegment const &other)
: lang_item (other.lang_item), ident_segment (other.ident_segment),
locus (other.locus),
@@ -1145,6 +1171,11 @@ protected:
{
return new TypePath (*this);
}
+ TypePath *reconstruct_impl () const override
+ {
+ return new TypePath (reconstruct_vec (segments), locus,
+ has_opening_scope_resolution);
+ }
public:
/* Returns whether the TypePath has an opening scope resolution operator
@@ -1436,6 +1467,12 @@ protected:
{
return new QualifiedPathInType (*this);
}
+ QualifiedPathInType *reconstruct_impl () const override
+ {
+ return new QualifiedPathInType (path_type,
+ associated_segment->reconstruct (),
+ reconstruct_vec (segments), locus);
+ }
public:
QualifiedPathInType (
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index 62bf6f2..15ab0b7 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -327,17 +327,53 @@ GroupedExpr::as_string () const
}
std::string
-SlicePattern::as_string () const
+SlicePatternItemsNoRest::as_string () const
{
- std::string str ("SlicePattern: ");
+ std::string str;
- for (const auto &pattern : items)
+ for (const auto &pattern : patterns)
str += "\n " + pattern->as_string ();
return str;
}
std::string
+SlicePatternItemsHasRest::as_string () const
+{
+ std::string str;
+
+ str += "\n Lower patterns: ";
+ if (lower_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &lower : lower_patterns)
+ str += "\n " + lower->as_string ();
+ }
+
+ str += "\n Upper patterns: ";
+ if (upper_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &upper : upper_patterns)
+ str += "\n " + upper->as_string ();
+ }
+
+ return str;
+}
+
+std::string
+SlicePattern::as_string () const
+{
+ return "SlicePattern: " + items->as_string ();
+}
+
+std::string
AltPattern::as_string () const
{
std::string str ("AltPattern: ");
@@ -367,6 +403,18 @@ GroupedExpr::accept_vis (ASTVisitor &vis)
}
void
+SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
SlicePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 195a08f..4945ec4 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -137,8 +137,7 @@ public:
void accept_vis (ASTVisitor &vis) override;
- // TODO: is this better? Or is a "vis_pattern" better?
- Pattern &get_pattern_to_bind ()
+ Pattern &get_subpattern ()
{
rust_assert (has_subpattern ());
return *subpattern;
@@ -949,7 +948,7 @@ public:
* is empty). */
bool has_struct_pattern_elems () const { return !elems.is_empty (); }
- location_t get_locus () const override { return path.get_locus (); }
+ location_t get_locus () const override { return locus; }
void accept_vis (ASTVisitor &vis) override;
@@ -1522,41 +1521,217 @@ protected:
}
};
+// Base abstract class representing patterns in a SlicePattern
+class SlicePatternItems
+{
+public:
+ enum SlicePatternItemType
+ {
+ NO_REST,
+ HAS_REST,
+ };
+
+ virtual ~SlicePatternItems () {}
+
+ // TODO: should this store location data?
+
+ // Unique pointer custom clone function
+ std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
+ {
+ return std::unique_ptr<SlicePatternItems> (
+ clone_slice_pattern_items_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual SlicePatternItemType get_pattern_type () const = 0;
+
+protected:
+ // pure virtual clone implementation
+ virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0;
+};
+
+// Class representing the patterns in a SlicePattern without `..`
+class SlicePatternItemsNoRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> patterns;
+
+public:
+ SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
+ : patterns (std::move (patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other)
+ {
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to vector clone
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
+ {
+ patterns.clear ();
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
+ {
+ return patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::NO_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsNoRest (*this);
+ }
+};
+
+// Class representing the patterns in a SlicePattern that contains a `..`
+class SlicePatternItemsHasRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> lower_patterns;
+ std::vector<std::unique_ptr<Pattern>> upper_patterns;
+
+public:
+ SlicePatternItemsHasRest (
+ std::vector<std::unique_ptr<Pattern>> lower_patterns,
+ std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ : lower_patterns (std::move (lower_patterns)),
+ upper_patterns (std::move (upper_patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to clone
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.clear ();
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.clear ();
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::HAS_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsHasRest (*this);
+ }
+};
+
// AST node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
- std::vector<std::unique_ptr<Pattern>> items;
+ std::unique_ptr<SlicePatternItems> items;
location_t locus;
NodeId node_id;
public:
std::string as_string () const override;
- SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+ SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus)
: items (std::move (items)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- // Copy constructor with vector clone
+ // Copy constructor requires clone
SlicePattern (SlicePattern const &other) : locus (other.locus)
{
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+
node_id = other.node_id;
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ items = other.items->clone_slice_pattern_items ();
}
- // Overloaded assignment operator to vector clone
+ // Overloaded assignment operator to clone
SlicePattern &operator= (SlicePattern const &other)
{
locus = other.locus;
node_id = other.node_id;
- items.clear ();
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+ items = other.items->clone_slice_pattern_items ();
return *this;
}
@@ -1569,10 +1744,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
- const std::vector<std::unique_ptr<Pattern>> &get_items () const
+ SlicePatternItems &get_items ()
{
- return items;
+ rust_assert (items != nullptr);
+ return *items;
}
NodeId get_node_id () const override { return node_id; }
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 6c0652a..2a3496b 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -19,7 +19,9 @@
#ifndef RUST_AST_TYPE_H
#define RUST_AST_TYPE_H
+#include "optional.h"
#include "rust-ast.h"
+#include "rust-expr.h"
#include "rust-path.h"
namespace Rust {
@@ -106,6 +108,11 @@ protected:
return new TraitBound (node_id, type_path, locus, in_parens,
opening_question_mark, for_lifetimes);
}
+ TraitBound *reconstruct_impl () const override
+ {
+ return new TraitBound (type_path, locus, in_parens, opening_question_mark,
+ for_lifetimes);
+ }
};
// definition moved to rust-ast.h
@@ -127,6 +134,10 @@ protected:
{
return new ImplTraitType (*this);
}
+ ImplTraitType *reconstruct_impl () const override
+ {
+ return new ImplTraitType (reconstruct_vec (type_param_bounds), locus);
+ }
public:
ImplTraitType (
@@ -136,7 +147,8 @@ public:
{}
// copy constructor with vector clone
- ImplTraitType (ImplTraitType const &other) : locus (other.locus)
+ ImplTraitType (ImplTraitType const &other)
+ : Type (other.node_id), locus (other.locus)
{
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -191,6 +203,11 @@ protected:
{
return new TraitObjectType (*this);
}
+ TraitObjectType *reconstruct_impl () const override
+ {
+ return new TraitObjectType (reconstruct_vec (type_param_bounds), locus,
+ has_dyn);
+ }
public:
TraitObjectType (
@@ -202,7 +219,7 @@ public:
// copy constructor with vector clone
TraitObjectType (TraitObjectType const &other)
- : has_dyn (other.has_dyn), locus (other.locus)
+ : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus)
{
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -258,6 +275,10 @@ protected:
{
return new ParenthesisedType (*this);
}
+ ParenthesisedType *reconstruct_impl () const override
+ {
+ return new ParenthesisedType (type_in_parens->reconstruct (), locus);
+ }
public:
// Constructor uses Type pointer for polymorphism
@@ -338,6 +359,10 @@ public:
{
return new ImplTraitTypeOneBound (*this);
}
+ TypeNoBounds *reconstruct_impl () const override
+ {
+ return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus);
+ }
};
/* A trait object with a single trait bound. The "trait bound" is really just
@@ -355,6 +380,10 @@ protected:
{
return new TraitObjectTypeOneBound (*this);
}
+ TraitObjectTypeOneBound *reconstruct_impl () const override
+ {
+ return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn);
+ }
public:
TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
@@ -448,6 +477,10 @@ protected:
{
return new TupleType (*this);
}
+ TupleType *reconstruct_impl () const override
+ {
+ return new TupleType (reconstruct_vec (elems), locus);
+ }
};
/* A type with no values, representing the result of computations that never
@@ -464,6 +497,10 @@ protected:
{
return new NeverType (*this);
}
+ NeverType *reconstruct_impl () const override
+ {
+ return new NeverType (locus);
+ }
public:
NeverType (location_t locus) : locus (locus) {}
@@ -544,6 +581,10 @@ protected:
{
return new RawPointerType (*this);
}
+ RawPointerType *reconstruct_impl () const override
+ {
+ return new RawPointerType (pointer_type, type->reconstruct (), locus);
+ }
};
// A type pointing to memory owned by another value
@@ -622,33 +663,42 @@ protected:
{
return new ReferenceType (*this);
}
+ ReferenceType *reconstruct_impl () const override
+ {
+ return new ReferenceType (has_mut, type->reconstruct (), locus,
+ // TODO: Improve this - it's ugly!
+ has_lifetime () ? tl::make_optional<Lifetime> (
+ lifetime->get_lifetime_type (),
+ lifetime->get_lifetime_name (),
+ lifetime->get_locus ())
+ : tl::nullopt);
+ }
};
// A fixed-size sequence of elements of a specified type
class ArrayType : public TypeNoBounds
{
std::unique_ptr<Type> elem_type;
- std::unique_ptr<Expr> size;
+ AnonConst size;
location_t locus;
public:
// Constructor requires pointers for polymorphism
- ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
- location_t locus)
+ ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus)
: elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
{}
// Copy constructor requires deep copies of both unique pointers
ArrayType (ArrayType const &other)
- : elem_type (other.elem_type->clone_type ()),
- size (other.size->clone_expr ()), locus (other.locus)
+ : elem_type (other.elem_type->clone_type ()), size (other.size),
+ locus (other.locus)
{}
// Overload assignment operator to deep copy pointers
ArrayType &operator= (ArrayType const &other)
{
elem_type = other.elem_type->clone_type ();
- size = other.size->clone_expr ();
+ size = other.size;
locus = other.locus;
return *this;
}
@@ -671,17 +721,15 @@ public:
}
// TODO: would a "vis_expr" be better?
- Expr &get_size_expr ()
+ AnonConst &get_size_expr ()
{
- rust_assert (size != nullptr);
- return *size;
+ // rust_assert (size != nullptr);
+
+ return size;
}
std::unique_ptr<Type> &get_element_type () { return elem_type; }
- // Additional getter for direct access to the size expr unique_ptr
- std::unique_ptr<Expr> &get_size_ptr () { return size; }
-
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -689,6 +737,12 @@ protected:
{
return new ArrayType (*this);
}
+ ArrayType *reconstruct_impl () const override
+ {
+ return new ArrayType (elem_type->reconstruct (),
+ size /* FIXME: This should be `reconstruct_expr()` */,
+ locus);
+ }
};
/* A dynamically-sized type representing a "view" into a sequence of elements of
@@ -739,12 +793,16 @@ public:
std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; }
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
SliceType *clone_type_no_bounds_impl () const override
{
return new SliceType (*this);
}
+ SliceType *reconstruct_impl () const override
+ {
+ return new SliceType (elem_type->reconstruct (), locus);
+ }
};
/* Type used in generic arguments to explicitly request type inference (wildcard
@@ -755,13 +813,21 @@ class InferredType : public TypeNoBounds
// e.g. Vec<_> = whatever
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
InferredType *clone_type_no_bounds_impl () const override
{
+ // This goes through the copy constructor
return new InferredType (*this);
}
+ InferredType *reconstruct_impl () const override
+ {
+ // This goes through the base constructor which calls the base
+ // TypeNoBounds constructor, which allocates a new NodeId
+ return new InferredType (locus);
+ }
+
public:
InferredType (location_t locus) : locus (locus) {}
@@ -980,9 +1046,17 @@ public:
FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
+ BareFunctionType *reconstruct_impl () const override
+ {
+ return new BareFunctionType (
+ for_lifetimes, function_qualifiers, params,
+ /* FIXME: Should params be reconstruct() as well? */
+ _is_variadic, variadic_attrs, return_type->reconstruct (), locus);
+ }
+
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
BareFunctionType *clone_type_no_bounds_impl () const override
{
return new BareFunctionType (*this);
@@ -999,13 +1073,13 @@ class MacroInvocation;
* function item type?
* closure expression types?
* primitive types (bool, int, float, char, str (the slice))
- * Although supposedly TypePaths are used to reference these types (including
- * primitives) */
+ * Although supposedly TypePaths are used to reference these types
+ * (including primitives) */
/* FIXME: Incomplete spec references:
- * anonymous type parameters, aka "impl Trait in argument position" - impl then
- * trait bounds abstract return types, aka "impl Trait in return position" -
- * impl then trait bounds */
+ * anonymous type parameters, aka "impl Trait in argument position" - impl
+ * then trait bounds abstract return types, aka "impl Trait in return
+ * position" - impl then trait bounds */
} // namespace AST
} // namespace Rust