From 528dd22fd9375ef4334c493b95c03c2db6633fc1 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 2 Jul 2025 18:48:07 -0400 Subject: [PATCH] gccrs: Parse try expressions This doesn't do anything beyond creating TryExpr and parsing them, so try expressions shouldn't be able to make it past AST lowering yet. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor for TryExpr. * ast/rust-ast-collector.h (TokenCollector::visit): Likewise. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise. (DefaultASTVisitor::visit): Likewise. * expand/rust-derive.h (DeriveVisitor::visit): Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise. * resolve/rust-ast-resolve-base.h (ResolverBase::visit): Likewise. * ast/rust-ast-full-decls.h (class TryExpr): New forward class declaration. * ast/rust-ast.cc (TryExpr::as_string): New function. (TryExpr::accept_vis): Likewise. * ast/rust-expr.h (class TryExpr): New class. * parse/rust-parse.h (Parser::parse_try_expr): New function. * parse/rust-parse-impl.h (Parser::parse_try_expr): Likewise. (Parser::null_denotation_not_path): Use parse_try_expr to parse try expressions. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-collector.cc | 7 +++ gcc/rust/ast/rust-ast-collector.h | 1 + gcc/rust/ast/rust-ast-full-decls.h | 1 + gcc/rust/ast/rust-ast-visitor.cc | 7 +++ gcc/rust/ast/rust-ast-visitor.h | 2 + gcc/rust/ast/rust-ast.cc | 19 ++++++ gcc/rust/ast/rust-expr.h | 76 +++++++++++++++++++++++ gcc/rust/expand/rust-derive.h | 1 + gcc/rust/hir/rust-ast-lower-base.cc | 3 + gcc/rust/hir/rust-ast-lower-base.h | 1 + gcc/rust/parse/rust-parse-impl.h | 31 +++++++++ gcc/rust/parse/rust-parse.h | 3 + gcc/rust/resolve/rust-ast-resolve-base.cc | 4 ++ gcc/rust/resolve/rust-ast-resolve-base.h | 1 + 14 files changed, 157 insertions(+) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 5a8d462dbd7..0b5f27d36d2 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1370,6 +1370,13 @@ TokenCollector::visit (ReturnExpr &expr) visit (expr.get_returned_expr ()); } +void +TokenCollector::visit (TryExpr &expr) +{ + push (Rust::Token::make (TRY, expr.get_locus ())); + visit (expr.get_block_expr ()); +} + void TokenCollector::visit (UnsafeBlockExpr &expr) { diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index cec2365892e..e8af5878a2c 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -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); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index b410f3ad006..eb1f3ea890c 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -128,6 +128,7 @@ class RangeFullExpr; class RangeFromToInclExpr; class RangeToInclExpr; class ReturnExpr; +class TryExpr; class UnsafeBlockExpr; class LoopLabel; class BaseLoopExpr; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index c24425bbb38..fd45fb1060d 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -549,6 +549,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr) visit (expr.get_returned_expr ()); } +void +DefaultASTVisitor::visit (AST::TryExpr &expr) +{ + visit_outer_attrs (expr); + visit (expr.get_block_expr ()); +} + void DefaultASTVisitor::visit (AST::BoxExpr &expr) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 22fd98b6ea8..6111b0548ed 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -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; @@ -307,6 +308,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; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 916829fe95c..4d928ca7a2d 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1636,6 +1636,19 @@ ReturnExpr::as_string () const return str; } +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 { @@ -4604,6 +4617,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis) vis.visit (*this); } +void +TryExpr::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + void UnsafeBlockExpr::accept_vis (ASTVisitor &vis) { diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 21e856bb1d0..3e50c46e58d 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3700,6 +3700,82 @@ protected: } }; +// Try expression AST node representation +class TryExpr : public ExprWithBlock +{ + std::vector outer_attrs; + std::unique_ptr 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 block_expr, + std::vector 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 &get_outer_attrs () const { return outer_attrs; } + std::vector &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Return; } + +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; diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index ff4f427695a..61c7355e7ab 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -159,6 +159,7 @@ private: virtual void visit (RangeFromToInclExpr &expr) override final{}; virtual void visit (RangeToInclExpr &expr) override final{}; virtual void visit (ReturnExpr &expr) override final{}; + virtual void visit (TryExpr &expr) override final{}; virtual void visit (BoxExpr &expr) override final{}; virtual void visit (UnsafeBlockExpr &expr) override final{}; virtual void visit (LoopExpr &expr) override final{}; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 5b35052b665..b07ac0c0750 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -242,6 +242,9 @@ void ASTLoweringBase::visit (AST::ReturnExpr &) {} void +ASTLoweringBase::visit (AST::TryExpr &) +{} +void ASTLoweringBase::visit (AST::UnsafeBlockExpr &) {} void diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 51912be66b4..0284ff0c82b 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -144,6 +144,7 @@ public: virtual void visit (AST::RangeToInclExpr &expr) override; virtual void visit (AST::BoxExpr &expr) override; virtual void visit (AST::ReturnExpr &expr) override; + virtual void visit (AST::TryExpr &expr) override; virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; virtual void visit (AST::WhileLoopExpr &expr) override; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 120817b88b8..9608cd885f4 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7570,6 +7570,34 @@ Parser::parse_return_expr (AST::AttrVec outer_attrs, locus)); } +// Parses a try expression. +template +std::unique_ptr +Parser::parse_try_expr (AST::AttrVec outer_attrs, + location_t pratt_parsed_loc) +{ + location_t locus = pratt_parsed_loc; + if (locus == UNKNOWN_LOCATION) + { + locus = lexer.peek_token ()->get_locus (); + skip_token (TRY); + } + + std::unique_ptr block_expr = parse_block_expr (); + + if (!block_expr) + { + Error error (lexer.peek_token ()->get_locus (), + "failed to parse try block expression"); + add_error (std::move (error)); + + return nullptr; + } + + return std::unique_ptr ( + new AST::TryExpr (std::move (block_expr), std::move (outer_attrs), locus)); +} + /* Parses a break expression (including any label to break to AND any return * expression). */ template @@ -12508,6 +12536,9 @@ Parser::null_denotation_not_path ( case RETURN_KW: // FIXME: is this really a null denotation expression? return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); + case TRY: + // FIXME: is this really a null denotation expression? + return parse_try_expr (std::move (outer_attrs), tok->get_locus ()); case BREAK: // FIXME: is this really a null denotation expression? return parse_break_expr (std::move (outer_attrs), tok->get_locus ()); diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index c9b6edb60e9..36426d56f8d 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -649,6 +649,9 @@ private: std::unique_ptr parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); + std::unique_ptr + parse_try_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + location_t pratt_parsed_loc = UNKNOWN_LOCATION); std::unique_ptr parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 71c4c4834db..05f34bc3f87 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -283,6 +283,10 @@ void ResolverBase::visit (AST::ReturnExpr &) {} +void +ResolverBase::visit (AST::TryExpr &) +{} + void ResolverBase::visit (AST::UnsafeBlockExpr &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index e17bdcb5eaa..0cbf78e39ab 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -99,6 +99,7 @@ public: void visit (AST::RangeToInclExpr &); void visit (AST::BoxExpr &); void visit (AST::ReturnExpr &); + void visit (AST::TryExpr &); void visit (AST::UnsafeBlockExpr &); void visit (AST::LoopExpr &); void visit (AST::WhileLoopExpr &); -- 2.47.2