]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: ast: Add PointerVisitor
authorArthur Cohen <arthur.cohen@embecosm.com>
Wed, 13 Aug 2025 12:32:41 +0000 (14:32 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 19:58:48 +0000 (20:58 +0100)
gcc/rust/ChangeLog:

* Make-lang.in: Compile it.
* ast/rust-builtin-ast-nodes.h: Add missing methods for getting pointers.
* ast/rust-expr.h: Likewise.
* ast/rust-item.h: Likewise.
* ast/rust-path.h: Likewise.
* ast/rust-pattern.h: Likewise.
* ast/rust-type.h: Likewise.
* ast/rust-ast-pointer-visitor.cc: New file.
* ast/rust-ast-pointer-visitor.h: New file.

gcc/rust/Make-lang.in
gcc/rust/ast/rust-ast-pointer-visitor.cc [new file with mode: 0644]
gcc/rust/ast/rust-ast-pointer-visitor.h [new file with mode: 0644]
gcc/rust/ast/rust-builtin-ast-nodes.h
gcc/rust/ast/rust-expr.h
gcc/rust/ast/rust-item.h
gcc/rust/ast/rust-path.h
gcc/rust/ast/rust-pattern.h
gcc/rust/ast/rust-type.h

index ffe3137dd7045ac01000b415ef4a49190bf3f275..26ad514fae3d1a532abe44eb2c6bacb58c082ac4 100644 (file)
@@ -84,6 +84,7 @@ GRS_OBJS = \
     rust/rust-ast-dump.o \
     rust/rust-ast-collector.o \
     rust/rust-ast-visitor.o \
+    rust/rust-ast-pointer-visitor.o \
     rust/rust-hir-visitor.o \
     rust/rust-hir-dump.o \
     rust/rust-session-manager.o \
diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.cc b/gcc/rust/ast/rust-ast-pointer-visitor.cc
new file mode 100644 (file)
index 0000000..8a470a9
--- /dev/null
@@ -0,0 +1,1483 @@
+// 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-ast-pointer-visitor.h"
+#include "rust-ast-visitor.h"
+#include "rust-ast-full.h"
+
+namespace Rust {
+namespace AST {
+
+void
+PointerVisitor::visit (AST::Crate &crate)
+{
+  visit_inner_attrs (crate);
+  for (auto &item : crate.items)
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::AttrInputMetaItemContainer &input)
+{
+  // FIXME: I think we might actually have to reseat sub-items for macro
+  // invocations within attributes correct?
+
+  for (auto &item : input.get_items ())
+    visit (item);
+}
+
+void
+PointerVisitor::visit (AST::IdentifierExpr &ident_expr)
+{
+  visit_outer_attrs (ident_expr);
+}
+
+void
+PointerVisitor::visit (AST::LifetimeParam &lifetime_param)
+{
+  visit_outer_attrs (lifetime_param);
+
+  // Nothing to do for lifetimes right?
+}
+
+void
+PointerVisitor::visit (AST::ConstGenericParam &const_param)
+{
+  visit_outer_attrs (const_param);
+  if (const_param.has_type ())
+    reseat (const_param.get_type_ptr ());
+
+  if (const_param.has_default_value ())
+    visit (const_param.get_default_value_unchecked ());
+}
+
+void
+PointerVisitor::visit (AST::PathInExpression &path)
+{
+  visit_outer_attrs (path);
+
+  if (!path.is_lang_item ())
+    for (auto &segment : path.get_segments ())
+      visit (segment);
+}
+
+void
+PointerVisitor::visit (GenericArgsBinding &binding)
+{
+  reseat (binding.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TypePathSegmentGeneric &segment)
+{
+  if (segment.has_generic_args ())
+    visit (segment.get_generic_args ());
+}
+
+void
+PointerVisitor::visit (AST::TypePathFunction &tpf)
+{
+  for (auto &input : tpf.get_params ())
+    reseat (input);
+  if (tpf.has_return_type ())
+    reseat (tpf.get_return_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TypePathSegmentFunction &segment)
+{
+  // FIXME: No reseating here correct? No macros possible or desugar?
+  visit (segment.get_type_path_function ());
+  visit (segment.get_ident_segment ());
+}
+
+void
+PointerVisitor::visit (AST::GenericArgs &args)
+{
+  // Nothing to do for lifetimes?
+  // for (auto &lifetime : args.get_lifetime_args ())
+  //   reseat (lifetime);
+
+  // FIXME: Actually this can probably be a macro invocation, so we need to
+  // reseat them?
+  for (auto &generic : args.get_generic_args ())
+    visit (generic);
+
+  for (auto &binding : args.get_binding_args ())
+    visit (binding);
+}
+
+void
+PointerVisitor::visit (AST::PathExprSegment &segment)
+{
+  visit (segment.get_ident_segment ());
+  if (segment.has_generic_args ())
+    visit (segment.get_generic_args ());
+}
+void
+PointerVisitor::visit (AST::TypePath &path)
+{
+  for (auto &segment : path.get_segments ())
+    visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::QualifiedPathInExpression &path)
+{
+  visit_outer_attrs (path);
+  visit (path.get_qualified_path_type ());
+
+  for (auto &segment : path.get_segments ())
+    visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::QualifiedPathType &path)
+{
+  reseat (path.get_type_ptr ());
+  if (path.has_as_clause ())
+    visit (path.get_as_type_path ());
+}
+
+void
+PointerVisitor::visit (AST::QualifiedPathInType &path)
+{
+  visit (path.get_qualified_path_type ());
+  visit (path.get_associated_segment ());
+
+  for (auto &segment : path.get_segments ())
+    visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::LiteralExpr &expr)
+{
+  visit_outer_attrs (expr);
+}
+
+void
+PointerVisitor::visit (AST::AttrInputLiteral &attr_input)
+{
+  visit (attr_input.get_literal ());
+}
+
+void
+PointerVisitor::visit (AST::AttrInputMacro &attr_input)
+{
+  visit (attr_input.get_macro ());
+}
+
+void
+PointerVisitor::visit (AST::MetaItemLitExpr &meta_item)
+{
+  visit (meta_item.get_literal ());
+}
+
+void
+PointerVisitor::visit (AST::SimplePath &path)
+{
+  for (auto &segment : path.get_segments ())
+    visit (segment);
+}
+
+void
+PointerVisitor::visit (AST::MetaItemPathExpr &meta_item)
+{
+  visit (meta_item.get_path ());
+  reseat (meta_item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::BorrowExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_borrowed_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::DereferenceExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_dereferenced_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ErrorPropagationExpr &expr)
+{
+  visit_outer_attrs (expr);
+}
+
+void
+PointerVisitor::visit (AST::NegationExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_negated_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_left_expr_ptr ());
+  reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ComparisonExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_left_expr_ptr ());
+  reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::LazyBooleanExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_left_expr_ptr ());
+  reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TypeCastExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_casted_expr_ptr ());
+  reseat (expr.get_type_to_cast_to_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::AssignmentExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_left_expr_ptr ());
+  reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::CompoundAssignmentExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_left_expr_ptr ());
+  reseat (expr.get_right_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::GroupedExpr &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  reseat (expr.get_expr_in_parens_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayElemsValues &elems)
+{
+  for (auto &value : elems.get_values ())
+    reseat (value);
+}
+
+void
+PointerVisitor::visit (AST::ArrayElemsCopied &elems)
+{
+  reseat (elems.get_elem_to_copy_ptr ());
+  reseat (elems.get_num_copies_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayExpr &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  visit (expr.get_array_elems ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayIndexExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_array_expr_ptr ());
+  reseat (expr.get_index_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TupleExpr &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  for (auto &elem : expr.get_tuple_elems ())
+    reseat (elem);
+}
+
+void
+PointerVisitor::visit (AST::TupleIndexExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_tuple_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprStruct &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  visit (expr.get_struct_name ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprFieldIdentifier &field)
+{}
+
+void
+PointerVisitor::visit (AST::StructExprFieldIdentifierValue &field)
+{
+  reseat (field.get_value_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprFieldIndexValue &field)
+{
+  reseat (field.get_value_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructBase &base)
+{
+  reseat (base.get_base_struct_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructExprStructFields &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  visit (expr.get_struct_name ());
+  if (expr.has_struct_base ())
+    visit (expr.get_struct_base ());
+  for (auto &field : expr.get_fields ())
+    visit (field);
+}
+
+void
+PointerVisitor::visit (AST::StructExprStructBase &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  visit (expr.get_struct_name ());
+  visit (expr.get_struct_base ());
+}
+
+void
+PointerVisitor::visit (AST::CallExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_function_expr_ptr ());
+  for (auto &param : expr.get_params ())
+    reseat (param);
+}
+
+void
+PointerVisitor::visit (AST::MethodCallExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_receiver_expr_ptr ());
+  visit (expr.get_method_name ());
+  for (auto &param : expr.get_params ())
+    reseat (param);
+}
+
+void
+PointerVisitor::visit (AST::FieldAccessExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_receiver_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ClosureExprInner &expr)
+{
+  visit_outer_attrs (expr);
+
+  // TODO: Actually we need to handle macro invocations as closure parameters so
+  // this needs to be a reseat
+  for (auto &param : expr.get_params ())
+    visit (param);
+
+  reseat (expr.get_definition_expr_ptr ());
+}
+
+void
+PointerVisitor::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 ())
+    reseat (stmt);
+
+  if (expr.has_tail_expr ())
+    reseat (expr.get_tail_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ConstBlock &expr)
+{
+  visit (expr.get_const_expr ());
+}
+
+void
+PointerVisitor::visit (AST::AnonConst &expr)
+{
+  if (!expr.is_deferred ())
+    reseat (expr.get_inner_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ClosureExprInnerTyped &expr)
+{
+  visit_outer_attrs (expr);
+
+  // TODO: Same as ClosureExprInner
+  for (auto &param : expr.get_params ())
+    visit (param);
+
+  reseat (expr.get_return_type_ptr ());
+
+  reseat (expr.get_definition_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ClosureParam &param)
+{
+  visit_outer_attrs (param);
+  reseat (param.get_pattern_ptr ());
+  if (param.has_type_given ())
+    reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ContinueExpr &expr)
+{
+  visit_outer_attrs (expr);
+  if (expr.has_label ())
+    visit (expr.get_label_unchecked ());
+}
+
+void
+PointerVisitor::visit (AST::BreakExpr &expr)
+{
+  visit_outer_attrs (expr);
+  if (expr.has_label ())
+    visit (expr.get_label_unchecked ());
+
+  if (expr.has_break_expr ())
+    reseat (expr.get_break_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeFromToExpr &expr)
+{
+  reseat (expr.get_from_expr_ptr ());
+  reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeFromExpr &expr)
+{
+  reseat (expr.get_from_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeToExpr &expr)
+{
+  reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeFullExpr &expr)
+{}
+
+void
+PointerVisitor::visit (AST::RangeFromToInclExpr &expr)
+{
+  reseat (expr.get_from_expr_ptr ());
+  reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangeToInclExpr &expr)
+{
+  reseat (expr.get_to_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ReturnExpr &expr)
+{
+  visit_outer_attrs (expr);
+  if (expr.has_returned_expr ())
+    reseat (expr.get_returned_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TryExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_block_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::BoxExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_boxed_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::UnsafeBlockExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_block_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::LoopLabel &label)
+{
+  visit (label.get_lifetime ());
+}
+
+void
+PointerVisitor::visit (AST::LoopExpr &expr)
+{
+  visit_outer_attrs (expr);
+  if (expr.has_loop_label ())
+    visit (expr.get_loop_label ());
+  reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::WhileLoopExpr &expr)
+{
+  visit_outer_attrs (expr);
+  if (expr.has_loop_label ())
+    visit (expr.get_loop_label ());
+  reseat (expr.get_predicate_expr_ptr ());
+  reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::WhileLetLoopExpr &expr)
+{
+  visit_outer_attrs (expr);
+  for (auto &pattern : expr.get_patterns ())
+    reseat (pattern);
+
+  if (expr.has_loop_label ())
+    visit (expr.get_loop_label ());
+
+  reseat (expr.get_scrutinee_expr_ptr ());
+  reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ForLoopExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_pattern_ptr ());
+  reseat (expr.get_iterator_expr_ptr ());
+  if (expr.has_loop_label ())
+    visit (expr.get_loop_label ());
+  reseat (expr.get_loop_block_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::IfExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_condition_expr_ptr ());
+  visit (expr.get_if_block ());
+}
+
+void
+PointerVisitor::visit (AST::IfExprConseqElse &expr)
+{
+  visit (reinterpret_cast<AST::IfExpr &> (expr));
+  visit (expr.get_else_block ());
+}
+
+void
+PointerVisitor::visit (AST::IfLetExpr &expr)
+{
+  visit_outer_attrs (expr);
+  for (auto &pattern : expr.get_patterns ())
+    reseat (pattern);
+  reseat (expr.get_value_expr_ptr ());
+  visit (expr.get_if_block ());
+}
+
+void
+PointerVisitor::visit (AST::IfLetExprConseqElse &expr)
+{
+  visit (reinterpret_cast<AST::IfLetExpr &> (expr));
+  visit (expr.get_else_block ());
+}
+
+void
+PointerVisitor::visit (AST::MatchArm &arm)
+{
+  visit_outer_attrs (arm);
+  for (auto &pattern : arm.get_patterns ())
+    reseat (pattern);
+  if (arm.has_match_arm_guard ())
+    reseat (arm.get_guard_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::MatchCase &arm)
+{
+  visit (arm.get_arm ());
+  reseat (arm.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::MatchExpr &expr)
+{
+  visit_outer_attrs (expr);
+  visit_inner_attrs (expr);
+  reseat (expr.get_scrutinee_expr_ptr ());
+  for (auto &arm : expr.get_match_cases ())
+    visit (arm);
+}
+
+void
+PointerVisitor::visit (AST::AwaitExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_awaited_expr ());
+}
+
+void
+PointerVisitor::visit (AST::AsyncBlockExpr &expr)
+{
+  visit_outer_attrs (expr);
+  reseat (expr.get_block_expr ());
+}
+
+void
+PointerVisitor::visit (AST::InlineAsm &expr)
+{
+  visit_outer_attrs (expr);
+  using RegisterType = AST::InlineAsmOperand::RegisterType;
+  for (auto &operand : expr.get_operands ())
+    {
+      switch (operand.get_register_type ())
+       {
+       case RegisterType::In:
+         {
+           reseat (operand.get_in ().expr);
+           break;
+         }
+       case RegisterType::Out:
+         {
+           reseat (operand.get_out ().expr);
+           break;
+         }
+       case RegisterType::InOut:
+         {
+           reseat (operand.get_in_out ().expr);
+           break;
+         }
+       case RegisterType::SplitInOut:
+         {
+           auto split = operand.get_split_in_out ();
+           reseat (split.in_expr);
+           reseat (split.out_expr);
+           break;
+         }
+       case RegisterType::Const:
+         {
+           reseat (operand.get_const ().anon_const.get_inner_expr_ptr ());
+           break;
+         }
+       case RegisterType::Sym:
+         {
+           reseat (operand.get_sym ().expr);
+           break;
+         }
+       case RegisterType::Label:
+         {
+           reseat (operand.get_label ().expr);
+           break;
+         }
+       }
+    }
+}
+
+void
+PointerVisitor::visit (AST::LlvmInlineAsm &expr)
+{
+  for (auto &output : expr.get_outputs ())
+    reseat (output.expr);
+
+  for (auto &input : expr.get_inputs ())
+    reseat (input.expr);
+}
+
+void
+PointerVisitor::visit (AST::TypeParam &param)
+{
+  visit_outer_attrs (param);
+  // FIXME: Can we do macro expansion here?
+  for (auto &bound : param.get_type_param_bounds ())
+    visit (bound);
+  if (param.has_type ())
+    reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::LifetimeWhereClauseItem &item)
+{
+  visit (item.get_lifetime ());
+  for (auto &bound : item.get_lifetime_bounds ())
+    visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::TypeBoundWhereClauseItem &item)
+{
+  for (auto &lifetime : item.get_for_lifetimes ())
+    visit (lifetime);
+  reseat (item.get_type_ptr ());
+  // FIXME: Likewise?
+  for (auto &param : item.get_type_param_bounds ())
+    visit (param);
+}
+
+void
+PointerVisitor::visit (AST::Visibility &vis)
+{
+  if (vis.has_path ())
+    visit (vis.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::WhereClause &where)
+{
+  for (auto &item : where.get_items ())
+    visit (item);
+}
+
+void
+PointerVisitor::visit (AST::FunctionParam &param)
+{
+  visit_outer_attrs (param);
+  if (param.has_name ())
+    reseat (param.get_pattern_ptr ());
+
+  reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::SelfParam &param)
+{
+  visit_outer_attrs (param);
+
+  if (param.has_lifetime ())
+    visit (param.get_lifetime ());
+
+  if (param.has_type ())
+    reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::Module &module)
+{
+  visit_outer_attrs (module);
+  visit (module.get_visibility ());
+  visit_inner_attrs (module);
+  for (auto &item : module.get_items ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::ExternCrate &crate)
+{
+  visit_outer_attrs (crate);
+  visit (crate.get_visibility ());
+}
+
+void
+PointerVisitor::visit (AST::UseTreeGlob &use_tree)
+{
+  visit (use_tree.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::UseTreeList &use_tree)
+{
+  visit (use_tree.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::UseTreeRebind &use_tree)
+{
+  visit (use_tree.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::UseDeclaration &use_decl)
+{
+  visit (use_decl.get_visibility ());
+  visit (use_decl.get_tree ());
+}
+
+void
+PointerVisitor::visit_function_params (AST::Function &function)
+{
+  for (auto &param : function.get_function_params ())
+    visit (param);
+}
+
+void
+PointerVisitor::visit (AST::Function &function)
+{
+  visit_outer_attrs (function);
+  visit (function.get_visibility ());
+  visit (function.get_qualifiers ());
+  for (auto &generic : function.get_generic_params ())
+    visit (generic);
+
+  visit_function_params (function);
+
+  if (function.has_return_type ())
+    reseat (function.get_return_type_ptr ());
+  if (function.has_where_clause ())
+    visit (function.get_where_clause ());
+  if (function.has_body ())
+    reseat (*function.get_definition ());
+}
+
+void
+PointerVisitor::visit (AST::TypeAlias &type_alias)
+{
+  visit_outer_attrs (type_alias);
+  visit (type_alias.get_visibility ());
+  for (auto &generic : type_alias.get_generic_params ())
+    visit (generic);
+  if (type_alias.has_where_clause ())
+    visit (type_alias.get_where_clause ());
+  reseat (type_alias.get_type_aliased_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructField &field)
+{
+  visit_outer_attrs (field);
+  visit (field.get_visibility ());
+  reseat (field.get_field_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructStruct &struct_item)
+{
+  visit_outer_attrs (struct_item);
+  visit (struct_item.get_visibility ());
+  for (auto &generic : struct_item.get_generic_params ())
+    visit (generic);
+  if (struct_item.has_where_clause ())
+    visit (struct_item.get_where_clause ());
+  for (auto &field : struct_item.get_fields ())
+    visit (field);
+}
+
+void
+PointerVisitor::visit (AST::TupleField &field)
+{
+  visit_outer_attrs (field);
+  visit (field.get_visibility ());
+  reseat (field.get_field_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TupleStruct &tuple_struct)
+{
+  visit_outer_attrs (tuple_struct);
+  visit (tuple_struct.get_visibility ());
+  for (auto &generic : tuple_struct.get_generic_params ())
+    visit (generic);
+  if (tuple_struct.has_where_clause ())
+    visit (tuple_struct.get_where_clause ());
+  for (auto &field : tuple_struct.get_fields ())
+    visit (field);
+}
+
+void
+PointerVisitor::visit (AST::EnumItem &item)
+{
+  visit_outer_attrs (item);
+  visit (item.get_visibility ());
+}
+
+void
+PointerVisitor::visit (AST::EnumItemTuple &item)
+{
+  PointerVisitor::visit (static_cast<EnumItem &> (item));
+  for (auto &field : item.get_tuple_fields ())
+    visit (field);
+}
+
+void
+PointerVisitor::visit (AST::EnumItemStruct &item)
+{
+  PointerVisitor::visit (static_cast<EnumItem &> (item));
+  for (auto &field : item.get_struct_fields ())
+    visit (field);
+}
+
+void
+PointerVisitor::visit (AST::EnumItemDiscriminant &item)
+{
+  PointerVisitor::visit (static_cast<EnumItem &> (item));
+  reseat (item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::Enum &enum_item)
+{
+  visit_outer_attrs (enum_item);
+  visit (enum_item.get_visibility ());
+  for (auto &generic : enum_item.get_generic_params ())
+    visit (generic);
+  if (enum_item.has_where_clause ())
+    visit (enum_item.get_where_clause ());
+  for (auto &item : enum_item.get_variants ())
+    visit (item);
+}
+
+void
+PointerVisitor::visit (AST::Union &union_item)
+{
+  visit_outer_attrs (union_item);
+  visit (union_item.get_visibility ());
+  for (auto &generic : union_item.get_generic_params ())
+    visit (generic);
+  if (union_item.has_where_clause ())
+    visit (union_item.get_where_clause ());
+  for (auto &variant : union_item.get_variants ())
+    visit (variant);
+}
+
+void
+PointerVisitor::visit (AST::ConstantItem &const_item)
+{
+  visit_outer_attrs (const_item);
+  visit (const_item.get_visibility ());
+  reseat (const_item.get_type_ptr ());
+  if (const_item.has_expr ())
+    reseat (const_item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StaticItem &static_item)
+{
+  visit_outer_attrs (static_item);
+  visit (static_item.get_visibility ());
+  reseat (static_item.get_type_ptr ());
+  reseat (static_item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TraitItemConst &item)
+{
+  visit_outer_attrs (item);
+  reseat (item.get_type_ptr ());
+  if (item.has_expr ())
+    reseat (item.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TraitItemType &item)
+{
+  visit_outer_attrs (item);
+  for (auto &bound : item.get_type_param_bounds ())
+    visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::Trait &trait)
+{
+  visit_outer_attrs (trait);
+  visit (trait.get_visibility ());
+
+  visit_inner_attrs (trait);
+
+  visit (trait.get_implicit_self ());
+
+  for (auto &generic : trait.get_generic_params ())
+    visit (generic);
+
+  if (trait.has_where_clause ())
+    visit (trait.get_where_clause ());
+
+  for (auto &bound : trait.get_type_param_bounds ())
+    visit (bound);
+
+  for (auto &item : trait.get_trait_items ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::InherentImpl &impl)
+{
+  visit_outer_attrs (impl);
+  visit (impl.get_visibility ());
+
+  for (auto &generic : impl.get_generic_params ())
+    visit (generic);
+  if (impl.has_where_clause ())
+    visit (impl.get_where_clause ());
+  reseat (impl.get_type_ptr ());
+  visit_inner_attrs (impl);
+  for (auto &item : impl.get_impl_items ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::TraitImpl &impl)
+{
+  visit_outer_attrs (impl);
+  visit (impl.get_visibility ());
+
+  for (auto &generic : impl.get_generic_params ())
+    visit (generic);
+  if (impl.has_where_clause ())
+    visit (impl.get_where_clause ());
+  reseat (impl.get_type_ptr ());
+  visit (impl.get_trait_path ());
+  visit_inner_attrs (impl);
+  for (auto &item : impl.get_impl_items ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::ExternalTypeItem &item)
+{
+  visit_outer_attrs (item);
+  visit (item.get_visibility ());
+}
+
+void
+PointerVisitor::visit (AST::ExternalStaticItem &item)
+{
+  visit_outer_attrs (item);
+  visit (item.get_visibility ());
+  reseat (item.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ExternBlock &block)
+{
+  visit_outer_attrs (block);
+  visit (block.get_visibility ());
+  visit_inner_attrs (block);
+  for (auto &item : block.get_extern_items ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::MacroMatchFragment &match)
+{}
+
+void
+PointerVisitor::visit (AST::MacroMatchRepetition &match)
+{
+  for (auto &m : match.get_matches ())
+    visit (m);
+}
+
+void
+PointerVisitor::visit (AST::MacroMatcher &matcher)
+{
+  for (auto &m : matcher.get_matches ())
+    visit (m);
+}
+
+void
+PointerVisitor::visit (AST::MacroTranscriber &transcriber)
+{
+  visit (transcriber.get_token_tree ());
+}
+
+void
+PointerVisitor::visit (AST::MacroRule &rule)
+{
+  visit (rule.get_matcher ());
+  visit (rule.get_transcriber ());
+}
+
+void
+PointerVisitor::visit (AST::MacroRulesDefinition &rules_def)
+{
+  visit_outer_attrs (rules_def);
+  for (auto &rule : rules_def.get_macro_rules ())
+    visit (rule);
+}
+
+void
+PointerVisitor::visit (AST::MacroInvocData &data)
+{
+  visit (data.get_path ());
+  visit (data.get_delim_tok_tree ());
+}
+
+void
+PointerVisitor::visit (AST::MacroInvocation &macro_invoc)
+{
+  visit_outer_attrs (macro_invoc);
+  visit (macro_invoc.get_invoc_data ());
+}
+
+void
+PointerVisitor::visit (AST::MetaItemPath &meta_item)
+{
+  visit (meta_item.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::MetaItemSeq &meta_item)
+{
+  visit (meta_item.get_path ());
+  for (auto &inner : meta_item.get_seq ())
+    visit (inner);
+}
+
+void
+PointerVisitor::visit (AST::MetaListPaths &meta_item)
+{
+  for (auto &path : meta_item.get_paths ())
+    visit (path);
+}
+
+void
+PointerVisitor::visit (AST::MetaListNameValueStr &meta_item)
+{
+  for (auto &str : meta_item.get_values ())
+    visit (str);
+}
+
+void
+PointerVisitor::visit (AST::IdentifierPattern &pattern)
+{
+  if (pattern.has_subpattern ())
+    reseat (pattern.get_subpattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::RangePatternBoundPath &bound)
+{
+  visit (bound.get_path ());
+}
+
+void
+PointerVisitor::visit (AST::RangePatternBoundQualPath &bound)
+{
+  visit (bound.get_qualified_path ());
+}
+
+void
+PointerVisitor::visit (AST::RangePattern &pattern)
+{
+  // FIXME: So should this be reseat() instead? Can we have macro invocations as
+  // patterns in range patterns?
+  if (pattern.get_has_lower_bound ())
+    visit (pattern.get_lower_bound ());
+  if (pattern.get_has_upper_bound ())
+    visit (pattern.get_upper_bound ());
+}
+
+void
+PointerVisitor::visit (AST::ReferencePattern &pattern)
+{
+  reseat (pattern.get_referenced_pattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructPatternFieldTuplePat &field)
+{
+  visit_outer_attrs (field);
+  reseat (field.get_index_pattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructPatternFieldIdentPat &field)
+{
+  visit_outer_attrs (field);
+  reseat (field.get_ident_pattern_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::StructPatternFieldIdent &field)
+{
+  visit_outer_attrs (field);
+}
+
+void
+PointerVisitor::visit (AST::StructPatternElements &spe)
+{
+  for (auto &field : spe.get_struct_pattern_fields ())
+    visit (field);
+  for (auto &attribute : spe.get_etc_outer_attrs ())
+    visit (attribute);
+}
+
+void
+PointerVisitor::visit (AST::StructPattern &pattern)
+{
+  visit (pattern.get_path ());
+  visit (pattern.get_struct_pattern_elems ());
+}
+
+void
+PointerVisitor::visit (AST::TupleStructItemsNoRest &tuple_items)
+{
+  for (auto &pattern : tuple_items.get_patterns ())
+    reseat (pattern);
+}
+
+void
+PointerVisitor::visit (AST::TupleStructItemsHasRest &tuple_items)
+{
+  for (auto &lower : tuple_items.get_lower_patterns ())
+    reseat (lower);
+  for (auto &upper : tuple_items.get_upper_patterns ())
+    reseat (upper);
+}
+
+void
+PointerVisitor::visit (AST::TupleStructPattern &pattern)
+{
+  visit (pattern.get_path ());
+  visit (pattern.get_items ());
+}
+
+void
+PointerVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items)
+{
+  for (auto &pattern : tuple_items.get_patterns ())
+    reseat (pattern);
+}
+
+void
+PointerVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items)
+{
+  for (auto &lower : tuple_items.get_lower_patterns ())
+    reseat (lower);
+  for (auto &upper : tuple_items.get_upper_patterns ())
+    reseat (upper);
+}
+
+void
+PointerVisitor::visit (AST::TuplePattern &pattern)
+{
+  visit (pattern.get_items ());
+}
+
+void
+PointerVisitor::visit (AST::GroupedPattern &pattern)
+{
+  reseat (pattern.get_pattern_in_parens_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::SlicePatternItemsNoRest &items)
+{
+  for (auto &item : items.get_patterns ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::SlicePatternItemsHasRest &items)
+{
+  for (auto &item : items.get_lower_patterns ())
+    reseat (item);
+  for (auto &item : items.get_upper_patterns ())
+    reseat (item);
+}
+
+void
+PointerVisitor::visit (AST::SlicePattern &pattern)
+{
+  visit (pattern.get_items ());
+}
+
+void
+PointerVisitor::visit (AST::AltPattern &pattern)
+{
+  for (auto &alt : pattern.get_alts ())
+    reseat (alt);
+}
+
+void
+PointerVisitor::visit (AST::EmptyStmt &stmt)
+{}
+
+void
+PointerVisitor::visit (AST::LetStmt &stmt)
+{
+  visit_outer_attrs (stmt);
+  reseat (stmt.get_pattern_ptr ());
+  if (stmt.has_type ())
+    reseat (stmt.get_type_ptr ());
+  if (stmt.has_init_expr ())
+    reseat (stmt.get_init_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ExprStmt &stmt)
+{
+  reseat (stmt.get_expr_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::TraitBound &bound)
+{
+  for (auto &lifetime : bound.get_for_lifetimes ())
+    visit (lifetime);
+  visit (bound.get_type_path ());
+}
+
+void
+PointerVisitor::visit (AST::ImplTraitType &type)
+{
+  for (auto &bound : type.get_type_param_bounds ())
+    visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::TraitObjectType &type)
+{
+  for (auto &bound : type.get_type_param_bounds ())
+    visit (bound);
+}
+
+void
+PointerVisitor::visit (AST::ParenthesisedType &type)
+{
+  reseat (type.get_type_in_parens ());
+}
+
+void
+PointerVisitor::visit (AST::ImplTraitTypeOneBound &type)
+{
+  // FIXME: Do we need to reseat here?
+  visit (type.get_trait_bound ());
+}
+
+void
+PointerVisitor::visit (AST::TraitObjectTypeOneBound &type)
+{
+  // FIXME: Do we need to reseat here?
+  visit (type.get_trait_bound ());
+}
+
+void
+PointerVisitor::visit (AST::TupleType &type)
+{
+  for (auto &elem : type.get_elems ())
+    reseat (elem);
+}
+
+void
+PointerVisitor::visit (AST::NeverType &type)
+{}
+
+void
+PointerVisitor::visit (AST::RawPointerType &type)
+{
+  reseat (type.get_type_pointed_to_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ReferenceType &type)
+{
+  visit (type.get_lifetime ());
+  reseat (type.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::ArrayType &type)
+{
+  reseat (type.get_elem_type_ptr ());
+  visit (type.get_size_expr ());
+}
+
+void
+PointerVisitor::visit (AST::SliceType &type)
+{
+  reseat (type.get_elem_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::InferredType &type)
+{}
+
+void
+PointerVisitor::visit (AST::MaybeNamedParam &param)
+{
+  visit_outer_attrs (param);
+  reseat (param.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::BareFunctionType &type)
+{
+  for (auto &lifetime : type.get_for_lifetimes ())
+    visit (lifetime);
+  visit (type.get_function_qualifiers ());
+  for (auto &param : type.get_function_params ())
+    visit (param);
+  if (type.is_variadic ())
+    for (auto attr : type.get_variadic_attr ())
+      visit (attr);
+  if (type.has_return_type ())
+    reseat (type.get_return_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::FormatArgs &)
+{
+  // FIXME: Do we have anything to do? any subnodes to visit? Probably, right?
+}
+
+void
+PointerVisitor::visit (AST::OffsetOf &offset_of)
+{
+  reseat (offset_of.get_type_ptr ());
+}
+
+void
+PointerVisitor::visit (AST::VariadicParam &param)
+{
+  if (param.has_pattern ())
+    reseat (param.get_pattern_ptr ());
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.h b/gcc/rust/ast/rust-ast-pointer-visitor.h
new file mode 100644 (file)
index 0000000..1f899ea
--- /dev/null
@@ -0,0 +1,235 @@
+// 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_AST_POINTER_VISITOR_H
+#define RUST_AST_POINTER_VISITOR_H
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * Regular AST visitor which may reseat pointers when necessary.
+ */
+class PointerVisitor : public DefaultASTVisitor
+{
+public:
+  using DefaultASTVisitor::visit;
+
+  virtual void reseat (std::unique_ptr<AST::Expr> &ptr) { visit (ptr); }
+  virtual void reseat (std::unique_ptr<AST::BlockExpr> &ptr) { visit (ptr); }
+
+  virtual void reseat (std::unique_ptr<AST::Stmt> &ptr) { visit (ptr); }
+
+  virtual void reseat (std::unique_ptr<AST::Item> &ptr) { visit (ptr); }
+
+  virtual void reseat (std::unique_ptr<AST::AssociatedItem> &ptr)
+  {
+    visit (ptr);
+  }
+
+  virtual void reseat (std::unique_ptr<AST::ExternalItem> &ptr) { visit (ptr); }
+
+  virtual void reseat (std::unique_ptr<AST::Type> &ptr) { visit (ptr); }
+
+  virtual void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) { visit (ptr); }
+
+  virtual void reseat (std::unique_ptr<AST::Pattern> &ptr) { visit (ptr); }
+
+  void visit (AST::Crate &crate) override;
+  void visit (AST::AttrInputMetaItemContainer &input) override;
+  void visit (AST::IdentifierExpr &ident_expr) override;
+  void visit (AST::LifetimeParam &lifetime_param) override;
+  void visit (AST::ConstGenericParam &const_param) override;
+  void visit (AST::PathInExpression &path) override;
+  void visit (GenericArgsBinding &binding) override;
+  void visit (AST::TypePathSegmentGeneric &segment) override;
+  void visit (AST::TypePathFunction &tpf) override;
+  void visit (AST::TypePathSegmentFunction &segment) override;
+  void visit (AST::GenericArgs &args) override;
+  void visit (AST::PathExprSegment &segment) override;
+  void visit (AST::TypePath &path) override;
+  void visit (AST::QualifiedPathInExpression &path) override;
+  void visit (AST::QualifiedPathType &path) override;
+  void visit (AST::QualifiedPathInType &path) override;
+  void visit (AST::LiteralExpr &expr) override;
+  void visit (AST::AttrInputLiteral &attr_input) override;
+  void visit (AST::AttrInputMacro &attr_input) override;
+  void visit (AST::MetaItemLitExpr &meta_item) override;
+  void visit (AST::SimplePath &path) override;
+  void visit (AST::MetaItemPathExpr &meta_item) override;
+  void visit (AST::BorrowExpr &expr) override;
+  void visit (AST::DereferenceExpr &expr) override;
+  void visit (AST::ErrorPropagationExpr &expr) override;
+  void visit (AST::NegationExpr &expr) override;
+  void visit (AST::ArithmeticOrLogicalExpr &expr) override;
+  void visit (AST::ComparisonExpr &expr) override;
+  void visit (AST::LazyBooleanExpr &expr) override;
+  void visit (AST::TypeCastExpr &expr) override;
+  void visit (AST::AssignmentExpr &expr) override;
+  void visit (AST::CompoundAssignmentExpr &expr) override;
+  void visit (AST::GroupedExpr &expr) override;
+  void visit (AST::ArrayElemsValues &elems) override;
+  void visit (AST::ArrayElemsCopied &elems) override;
+  void visit (AST::ArrayExpr &expr) override;
+  void visit (AST::ArrayIndexExpr &expr) override;
+  void visit (AST::TupleExpr &expr) override;
+  void visit (AST::TupleIndexExpr &expr) override;
+  void visit (AST::StructExprStruct &expr) override;
+  void visit (AST::StructExprFieldIdentifier &field) override;
+  void visit (AST::StructExprFieldIdentifierValue &field) override;
+  void visit (AST::StructExprFieldIndexValue &field) override;
+  void visit (AST::StructBase &base) override;
+  void visit (AST::StructExprStructFields &expr) override;
+  void visit (AST::StructExprStructBase &expr) override;
+  void visit (AST::CallExpr &expr) override;
+  void visit (AST::MethodCallExpr &expr) override;
+  void visit (AST::FieldAccessExpr &expr) override;
+  void visit (AST::ClosureExprInner &expr) override;
+  void visit (AST::BlockExpr &expr) override;
+  void visit (AST::ConstBlock &expr) override;
+  void visit (AST::AnonConst &expr) override;
+  void visit (AST::ClosureExprInnerTyped &expr) override;
+  void visit (AST::ClosureParam &param) override;
+  void visit (AST::ContinueExpr &expr) override;
+  void visit (AST::BreakExpr &expr) override;
+  void visit (AST::RangeFromToExpr &expr) override;
+  void visit (AST::RangeFromExpr &expr) override;
+  void visit (AST::RangeToExpr &expr) override;
+  void visit (AST::RangeFullExpr &expr) override;
+  void visit (AST::RangeFromToInclExpr &expr) override;
+  void visit (AST::RangeToInclExpr &expr) override;
+  void visit (AST::ReturnExpr &expr) override;
+  void visit (AST::TryExpr &expr) override;
+  void visit (AST::BoxExpr &expr) override;
+  void visit (AST::UnsafeBlockExpr &expr) override;
+  void visit (AST::LoopLabel &label) override;
+  void visit (AST::LoopExpr &expr) override;
+  void visit (AST::WhileLoopExpr &expr) override;
+  void visit (AST::WhileLetLoopExpr &expr) override;
+  void visit (AST::ForLoopExpr &expr) override;
+  void visit (AST::IfExpr &expr) override;
+  void visit (AST::IfExprConseqElse &expr) override;
+  void visit (AST::IfLetExpr &expr) override;
+  void visit (AST::IfLetExprConseqElse &expr) override;
+  void visit (AST::MatchArm &arm) override;
+  void visit (AST::MatchCase &arm) override;
+  void visit (AST::MatchExpr &expr) override;
+  void visit (AST::AwaitExpr &expr) override;
+  void visit (AST::AsyncBlockExpr &expr) override;
+  void visit (AST::InlineAsm &expr) override;
+  void visit (AST::LlvmInlineAsm &expr) override;
+  void visit (AST::TypeParam &param) override;
+  void visit (AST::LifetimeWhereClauseItem &item) override;
+  void visit (AST::TypeBoundWhereClauseItem &item) override;
+  void visit (AST::Visibility &vis) override;
+  void visit (AST::WhereClause &where) override;
+  void visit (AST::FunctionParam &param) override;
+  void visit (AST::SelfParam &param) override;
+  void visit (AST::Module &module) override;
+  void visit (AST::ExternCrate &crate) override;
+  void visit (AST::UseTreeGlob &use_tree) override;
+  void visit (AST::UseTreeList &use_tree) override;
+  void visit (AST::UseTreeRebind &use_tree) override;
+  void visit (AST::UseDeclaration &use_decl) override;
+  void visit_function_params (AST::Function &function) override;
+  void visit (AST::Function &function) override;
+  void visit (AST::TypeAlias &type_alias) override;
+  void visit (AST::StructField &field) override;
+  void visit (AST::StructStruct &struct_item) override;
+  void visit (AST::TupleField &field) override;
+  void visit (AST::TupleStruct &tuple_struct) override;
+  void visit (AST::EnumItem &item) override;
+  void visit (AST::EnumItemTuple &item) override;
+  void visit (AST::EnumItemStruct &item) override;
+  void visit (AST::EnumItemDiscriminant &item) override;
+  void visit (AST::Enum &enum_item) override;
+  void visit (AST::Union &union_item) override;
+  void visit (AST::ConstantItem &const_item) override;
+  void visit (AST::StaticItem &static_item) override;
+  void visit (AST::TraitItemConst &item) override;
+  void visit (AST::TraitItemType &item) override;
+  void visit (AST::Trait &trait) override;
+  void visit (AST::InherentImpl &impl) override;
+  void visit (AST::TraitImpl &impl) override;
+  void visit (AST::ExternalTypeItem &item) override;
+  void visit (AST::ExternalStaticItem &item) override;
+  void visit (AST::ExternBlock &block) override;
+  void visit (AST::MacroMatchFragment &match) override;
+  void visit (AST::MacroMatchRepetition &match) override;
+  void visit (AST::MacroMatcher &matcher) override;
+  void visit (AST::MacroTranscriber &transcriber) override;
+  void visit (AST::MacroRule &rule) override;
+  void visit (AST::MacroRulesDefinition &rules_def) override;
+  void visit (AST::MacroInvocData &data) override;
+  void visit (AST::MacroInvocation &macro_invoc) override;
+  void visit (AST::MetaItemPath &meta_item) override;
+  void visit (AST::MetaItemSeq &meta_item) override;
+  void visit (AST::MetaListPaths &meta_item) override;
+  void visit (AST::MetaListNameValueStr &meta_item) override;
+  void visit (AST::IdentifierPattern &pattern) override;
+  void visit (AST::RangePatternBoundPath &bound) override;
+  void visit (AST::RangePatternBoundQualPath &bound) override;
+  void visit (AST::RangePattern &pattern) override;
+  void visit (AST::ReferencePattern &pattern) override;
+  void visit (AST::StructPatternFieldTuplePat &field) override;
+  void visit (AST::StructPatternFieldIdentPat &field) override;
+  void visit (AST::StructPatternFieldIdent &field) override;
+  void visit (AST::StructPatternElements &spe) override;
+  void visit (AST::StructPattern &pattern) override;
+  void visit (AST::TupleStructItemsNoRest &tuple_items) override;
+  void visit (AST::TupleStructItemsHasRest &tuple_items) override;
+  void visit (AST::TupleStructPattern &pattern) override;
+  void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
+  void visit (AST::TuplePatternItemsHasRest &tuple_items) override;
+  void visit (AST::TuplePattern &pattern) override;
+  void visit (AST::GroupedPattern &pattern) override;
+  void visit (AST::SlicePatternItemsNoRest &items) override;
+  void visit (AST::SlicePatternItemsHasRest &items) override;
+  void visit (AST::SlicePattern &pattern) override;
+  void visit (AST::AltPattern &pattern) override;
+  void visit (AST::EmptyStmt &stmt) override;
+  void visit (AST::LetStmt &stmt) override;
+  void visit (AST::ExprStmt &stmt) override;
+  void visit (AST::TraitBound &bound) override;
+  void visit (AST::ImplTraitType &type) override;
+  void visit (AST::TraitObjectType &type) override;
+  void visit (AST::ParenthesisedType &type) override;
+  void visit (AST::ImplTraitTypeOneBound &type) override;
+  void visit (AST::TraitObjectTypeOneBound &type) override;
+  void visit (AST::TupleType &type) override;
+  void visit (AST::NeverType &type) override;
+  void visit (AST::RawPointerType &type) override;
+  void visit (AST::ReferenceType &type) override;
+  void visit (AST::ArrayType &type) override;
+  void visit (AST::SliceType &type) override;
+  void visit (AST::InferredType &type) override;
+  void visit (AST::MaybeNamedParam &param) override;
+  void visit (AST::BareFunctionType &type) override;
+  void visit (AST::FormatArgs &) override;
+  void visit (AST::OffsetOf &offset_of) override;
+  void visit (AST::VariadicParam &param) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif
index 2893e7b46760a7f63b5a56043813a9353f2d37f2..2856a643449531c7d1e29a7f8a25312fc97c65f6 100644 (file)
@@ -255,6 +255,7 @@ public:
   virtual location_t get_locus () const override { return loc; }
   const Type &get_type () const { return *type; }
   Type &get_type () { return *type; }
+  std::unique_ptr<Type> &get_type_ptr () { return type; }
   const Identifier &get_field () const { return field; }
 
   bool is_expr_without_block () const override { return false; }
index 189fb9afc49a64c16be6626f4fe1a2addd75e382..239b9511f67f1ef3dc0c658423232d3289798bbf 100644 (file)
@@ -282,6 +282,8 @@ public:
 
   Expr &get_expr () { return *expr; }
 
+  std::unique_ptr<Expr> &get_expr_ptr () { return expr; }
+
   std::string as_string () const override
   {
     return path.as_string () + " = " + expr->as_string ();
@@ -414,6 +416,12 @@ public:
     return *main_or_left_expr;
   }
 
+  std::unique_ptr<Expr> &get_borrowed_expr_ptr ()
+  {
+    rust_assert (main_or_left_expr != nullptr);
+    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; }
@@ -455,6 +463,12 @@ public:
     return *main_or_left_expr;
   }
 
+  std::unique_ptr<Expr> &get_dereferenced_expr_ptr ()
+  {
+    rust_assert (main_or_left_expr != nullptr);
+    return main_or_left_expr;
+  }
+
   Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; }
 
 protected:
@@ -488,6 +502,12 @@ public:
     return *main_or_left_expr;
   }
 
+  std::unique_ptr<Expr> &get_propagating_expr_ptr ()
+  {
+    rust_assert (main_or_left_expr != nullptr);
+    return main_or_left_expr;
+  }
+
   Expr::Kind get_expr_kind () const override
   {
     return Expr::Kind::ErrorPropagation;
@@ -536,6 +556,12 @@ public:
     return *main_or_left_expr;
   }
 
+  std::unique_ptr<Expr> &get_negated_expr_ptr ()
+  {
+    rust_assert (main_or_left_expr != nullptr);
+    return main_or_left_expr;
+  }
+
   Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; }
 
 protected:
@@ -1294,6 +1320,12 @@ public:
     return *elem_to_copy;
   }
 
+  std::unique_ptr<Expr> &get_elem_to_copy_ptr ()
+  {
+    rust_assert (elem_to_copy != nullptr);
+    return elem_to_copy;
+  }
+
   // TODO: is this better? Or is a "vis_block" better?
   Expr &get_num_copies ()
   {
@@ -1301,6 +1333,12 @@ public:
     return *num_copies;
   }
 
+  std::unique_ptr<Expr> &get_num_copies_ptr ()
+  {
+    rust_assert (num_copies != nullptr);
+    return num_copies;
+  }
+
 protected:
   ArrayElemsCopied *clone_array_elems_impl () const override
   {
@@ -1480,6 +1518,12 @@ public:
     return *array_expr;
   }
 
+  std::unique_ptr<Expr> &get_array_expr_ptr ()
+  {
+    rust_assert (array_expr != nullptr);
+    return array_expr;
+  }
+
   // TODO: is this better? Or is a "vis_block" better?
   Expr &get_index_expr ()
   {
@@ -1487,6 +1531,12 @@ public:
     return *index_expr;
   }
 
+  std::unique_ptr<Expr> &get_index_expr_ptr ()
+  {
+    rust_assert (index_expr != nullptr);
+    return index_expr;
+  }
+
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
 
@@ -1675,6 +1725,12 @@ public:
     return *tuple_expr;
   }
 
+  std::unique_ptr<Expr> &get_tuple_expr_ptr ()
+  {
+    rust_assert (tuple_expr != nullptr);
+    return tuple_expr;
+  }
+
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
 
@@ -1823,6 +1879,12 @@ public:
     rust_assert (base_struct != nullptr);
     return *base_struct;
   }
+
+  std::unique_ptr<Expr> &get_base_struct_ptr ()
+  {
+    rust_assert (base_struct != nullptr);
+    return base_struct;
+  }
 };
 
 /* Base AST node for a single struct expression field (in struct instance
@@ -1939,6 +2001,12 @@ public:
     rust_assert (value != nullptr);
     return *value;
   }
+
+  std::unique_ptr<Expr> &get_value_ptr ()
+  {
+    rust_assert (value != nullptr);
+    return value;
+  }
 };
 
 // Identifier and value variant of StructExprField AST node
@@ -2309,6 +2377,12 @@ public:
     return *receiver;
   }
 
+  std::unique_ptr<Expr> &get_receiver_expr_ptr ()
+  {
+    rust_assert (receiver != nullptr);
+    return receiver;
+  }
+
   const PathExprSegment &get_method_name () const { return method_name; }
   PathExprSegment &get_method_name () { return method_name; }
 
@@ -2397,6 +2471,12 @@ public:
     return *receiver;
   }
 
+  std::unique_ptr<Expr> &get_receiver_expr_ptr ()
+  {
+    rust_assert (receiver != nullptr);
+    return receiver;
+  }
+
   Identifier get_field_name () const { return field; }
 
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
@@ -2554,6 +2634,7 @@ public:
   Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; }
 
   virtual Expr &get_definition_expr () = 0;
+  virtual std::unique_ptr<Expr> &get_definition_expr_ptr () = 0;
 };
 
 // Represents a non-type-specified closure expression AST node
@@ -2619,7 +2700,7 @@ public:
     return *closure_inner;
   }
 
-  std::unique_ptr<Expr> &get_definition_expr_ptr ()
+  std::unique_ptr<Expr> &get_definition_expr_ptr () override
   {
     rust_assert (closure_inner != nullptr);
     return closure_inner;
@@ -2855,6 +2936,12 @@ public:
     return *expr.value ();
   }
 
+  std::unique_ptr<Expr> &get_inner_expr_ptr ()
+  {
+    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
@@ -2950,8 +3037,7 @@ class ClosureExprInnerTyped : public ClosureExpr
 {
   // TODO: spec says typenobounds
   std::unique_ptr<Type> return_type;
-  std::unique_ptr<BlockExpr>
-    expr; // only used because may be polymorphic in future
+  std::unique_ptr<Expr> expr; // only used because may be polymorphic in future
 
 public:
   std::string as_string () const override;
@@ -2975,7 +3061,7 @@ public:
   {
     // guard to prevent null dereference (only required if error state)
     if (other.expr != nullptr)
-      expr = other.expr->clone_block_expr ();
+      expr = other.expr->clone_expr ();
     if (other.return_type != nullptr)
       return_type = other.return_type->clone_type ();
   }
@@ -2990,7 +3076,7 @@ public:
 
     // guard to prevent null dereference (only required if error state)
     if (other.expr != nullptr)
-      expr = other.expr->clone_block_expr ();
+      expr = other.expr->clone_expr ();
     else
       expr = nullptr;
     if (other.return_type != nullptr)
@@ -3013,12 +3099,19 @@ public:
   bool is_marked_for_strip () const override { return expr == nullptr; }
 
   // TODO: is this better? Or is a "vis_block" better?
-  BlockExpr &get_definition_expr () override
+  Expr &get_definition_expr () override
   {
     rust_assert (expr != nullptr);
     return *expr;
   }
 
+  std::unique_ptr<Expr> &get_definition_expr_ptr () override
+  {
+    rust_assert (expr != nullptr);
+
+    return expr;
+  }
+
   // TODO: is this better? Or is a "vis_block" better?
   Type &get_return_type ()
   {
@@ -3175,6 +3268,12 @@ public:
     return *break_expr;
   }
 
+  std::unique_ptr<Expr> &get_break_expr_ptr ()
+  {
+    rust_assert (has_break_expr ());
+    return break_expr;
+  }
+
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
 
@@ -3302,6 +3401,18 @@ public:
     return *to;
   }
 
+  std::unique_ptr<Expr> &get_from_expr_ptr ()
+  {
+    rust_assert (from != nullptr);
+    return from;
+  }
+
+  std::unique_ptr<Expr> &get_to_expr_ptr ()
+  {
+    rust_assert (to != nullptr);
+    return to;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -3363,6 +3474,12 @@ public:
     return *from;
   }
 
+  std::unique_ptr<Expr> &get_from_expr_ptr ()
+  {
+    rust_assert (from != nullptr);
+    return from;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -3425,6 +3542,12 @@ public:
     return *to;
   }
 
+  std::unique_ptr<Expr> &get_to_expr_ptr ()
+  {
+    rust_assert (to != nullptr);
+    return to;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -3538,6 +3661,18 @@ public:
     return *to;
   }
 
+  std::unique_ptr<Expr> &get_from_expr_ptr ()
+  {
+    rust_assert (from != nullptr);
+    return from;
+  }
+
+  std::unique_ptr<Expr> &get_to_expr_ptr ()
+  {
+    rust_assert (to != nullptr);
+    return to;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -3600,6 +3735,12 @@ public:
     return *to;
   }
 
+  std::unique_ptr<Expr> &get_to_expr_ptr ()
+  {
+    rust_assert (to != nullptr);
+    return to;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -3673,6 +3814,12 @@ public:
     return *expr;
   }
 
+  std::unique_ptr<Expr> &get_boxed_expr_ptr ()
+  {
+    rust_assert (expr != nullptr);
+    return expr;
+  }
+
   Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; }
 
 protected:
@@ -3754,6 +3901,12 @@ public:
     return *return_expr;
   }
 
+  std::unique_ptr<Expr> &get_returned_expr_ptr ()
+  {
+    rust_assert (return_expr != nullptr);
+    return return_expr;
+  }
+
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
 
@@ -3829,6 +3982,7 @@ public:
 
   // TODO: is this better? Or is a "vis_block" better?
   BlockExpr &get_block_expr () { return *block_expr; }
+  std::unique_ptr<BlockExpr> &get_block_expr_ptr () { return block_expr; }
 
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -3914,6 +4068,12 @@ public:
     return *expr;
   }
 
+  std::unique_ptr<BlockExpr> &get_block_expr_ptr ()
+  {
+    rust_assert (expr != nullptr);
+    return expr;
+  }
+
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
 
@@ -4006,6 +4166,12 @@ public:
     return *loop_block;
   }
 
+  std::unique_ptr<BlockExpr> &get_loop_block_ptr ()
+  {
+    rust_assert (loop_block != nullptr);
+    return loop_block;
+  }
+
   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
 
@@ -4106,6 +4272,12 @@ public:
     return *condition;
   }
 
+  std::unique_ptr<Expr> &get_predicate_expr_ptr ()
+  {
+    rust_assert (condition != nullptr);
+    return condition;
+  }
+
   BaseLoopExpr::Kind get_loop_kind () const override
   {
     return BaseLoopExpr::Kind::While;
@@ -4184,6 +4356,12 @@ public:
     return *scrutinee;
   }
 
+  std::unique_ptr<Expr> &get_scrutinee_expr_ptr ()
+  {
+    rust_assert (scrutinee != nullptr);
+    return scrutinee;
+  }
+
   // TODO: this mutable getter seems really dodgy. Think up better way.
   const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
   {
@@ -4261,6 +4439,12 @@ public:
     return *iterator_expr;
   }
 
+  std::unique_ptr<Expr> &get_iterator_expr_ptr ()
+  {
+    rust_assert (iterator_expr != nullptr);
+    return iterator_expr;
+  }
+
   // TODO: is this better? Or is a "vis_block" better?
   Pattern &get_pattern ()
   {
@@ -4268,6 +4452,12 @@ public:
     return *pattern;
   }
 
+  std::unique_ptr<Pattern> &get_pattern_ptr ()
+  {
+    rust_assert (pattern != nullptr);
+    return pattern;
+  }
+
   BaseLoopExpr::Kind get_loop_kind () const override
   {
     return BaseLoopExpr::Kind::For;
@@ -4920,6 +5110,12 @@ public:
     return *branch_value;
   }
 
+  std::unique_ptr<Expr> &get_scrutinee_expr_ptr ()
+  {
+    rust_assert (branch_value != nullptr);
+    return branch_value;
+  }
+
   const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
   std::vector<MatchCase> &get_match_cases () { return match_arms; }
 
index 3fd49f4b199dcb97a668668618d6c8ebbd35a12d..dbc75a2cbd4c3f46ed45983cb3cc93b874730864 100644 (file)
@@ -1610,6 +1610,12 @@ public:
     return *existing_type;
   }
 
+  std::unique_ptr<Type> &get_type_aliased_ptr ()
+  {
+    rust_assert (existing_type != nullptr);
+    return existing_type;
+  }
+
   Identifier get_new_type_name () const { return new_type_name; }
 
   Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; }
index c12f41f311acbf2bd9bb3343dc1184868a2041c7..88b5327c33ce12a72a7f6b5ee4b3dbbb306e7cce 100644 (file)
@@ -377,6 +377,13 @@ public:
     return *type;
   }
 
+  std::unique_ptr<AST::Type> &get_type_ptr ()
+  {
+    rust_assert (has_type ());
+
+    return type;
+  }
+
   GenericArg &get_default_value_unchecked ()
   {
     rust_assert (has_default_value ());
index e66a733f33bda2062f4ea55e5cabbc1b390907e9..51986763fad9e2c2e77553c8e7a17f13c2a4ea25 100644 (file)
@@ -144,6 +144,12 @@ public:
     return *subpattern;
   }
 
+  std::unique_ptr<Pattern> &get_subpattern_ptr ()
+  {
+    rust_assert (has_subpattern ());
+    return subpattern;
+  }
+
   Identifier get_ident () const { return variable_ident; }
 
   bool get_is_mut () const { return is_mut; }
@@ -519,6 +525,12 @@ public:
     return *pattern;
   }
 
+  std::unique_ptr<Pattern> &get_referenced_pattern_ptr ()
+  {
+    rust_assert (pattern != nullptr);
+    return pattern;
+  }
+
   bool is_double_reference () const { return has_two_amps; }
 
   bool get_is_mut () const { return is_mut; }
@@ -682,6 +694,12 @@ public:
     return *tuple_pattern;
   }
 
+  std::unique_ptr<Pattern> &get_index_pattern_ptr ()
+  {
+    rust_assert (tuple_pattern != nullptr);
+    return tuple_pattern;
+  }
+
   ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; }
 
 protected:
@@ -762,6 +780,12 @@ public:
     return *ident_pattern;
   }
 
+  std::unique_ptr<Pattern> &get_ident_pattern_ptr ()
+  {
+    rust_assert (ident_pattern != nullptr);
+    return ident_pattern;
+  }
+
   ItemType get_item_type () const override final { return ItemType::IDENT_PAT; }
 
 protected:
index 8d6c3e5166fc947cf0ba57e5bba412df94ace69e..014963fb520bb1ddb2e0c2059a2a25bef7eebbc0 100644 (file)
@@ -571,6 +571,12 @@ public:
     return *type;
   }
 
+  std::unique_ptr<TypeNoBounds> &get_type_pointed_to_ptr ()
+  {
+    rust_assert (type != nullptr);
+    return type;
+  }
+
   // Getter for direct access to the type unique_ptr
   std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
 
@@ -646,6 +652,12 @@ public:
     return *type;
   }
 
+  std::unique_ptr<TypeNoBounds> &get_type_referenced_ptr ()
+  {
+    rust_assert (type != nullptr);
+    return type;
+  }
+
   bool get_has_mut () const { return has_mut; }
 
   Lifetime &get_lifetime () { return lifetime.value (); }
@@ -720,6 +732,12 @@ public:
     return *elem_type;
   }
 
+  std::unique_ptr<Type> &get_elem_type_ptr ()
+  {
+    rust_assert (elem_type != nullptr);
+    return elem_type;
+  }
+
   // TODO: would a "vis_expr" be better?
   AnonConst &get_size_expr ()
   {
@@ -1044,6 +1062,12 @@ public:
     return *return_type;
   }
 
+  std::unique_ptr<TypeNoBounds> &get_return_type_ptr ()
+  {
+    rust_assert (has_return_type ());
+    return return_type;
+  }
+
   FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
 
   BareFunctionType *reconstruct_impl () const override