]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: hir: Add OffsetOf node
authorArthur Cohen <arthur.cohen@embecosm.com>
Mon, 28 Jul 2025 08:05:04 +0000 (10:05 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:59 +0000 (16:36 +0200)
gcc/rust/ChangeLog:

* hir/tree/rust-hir-expr.h (class OffsetOf): New.
* hir/tree/rust-hir-expr.cc: Define its methods.
* hir/tree/rust-hir-expr-abstract.h: Add ExprType::OffsetOf.
* hir/tree/rust-hir-full-decls.h (class OffsetOf): Declare it.
* backend/rust-compile-block.h: Add handling for OffsetOf.
* backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
* backend/rust-compile-expr.h: Likewise.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.h (RUST_BIR_BUILDER_EXPR_H): Likewise.
* checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise.
* checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
* checks/errors/borrowck/rust-function-collector.h: Likewise.
* checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit): Likewise.
* checks/errors/privacy/rust-privacy-reporter.h (RUST_PRIVACY_REPORTER_H): Likewise.
* checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise.
* checks/errors/rust-const-checker.h: Likewise.
* checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise.
* checks/errors/rust-hir-pattern-analysis.h: Likewise.
* checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise.
* checks/errors/rust-unsafe-checker.h: Likewise.
* hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
* hir/rust-hir-dump.cc (Dump::visit): Likewise.
* hir/rust-hir-dump.h: Likewise.
* hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise.
* hir/tree/rust-hir-visitor.h: Likewise.
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
* typecheck/rust-hir-type-check-expr.h (RUST_HIR_TYPE_CHECK_EXPR): Likewise.

gcc/testsuite/ChangeLog:

* rust/compile/offset_of2.rs: New test.

28 files changed:
gcc/rust/backend/rust-compile-block.h
gcc/rust/backend/rust-compile-expr.cc
gcc/rust/backend/rust-compile-expr.h
gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
gcc/rust/checks/errors/borrowck/rust-function-collector.h
gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
gcc/rust/checks/errors/rust-const-checker.cc
gcc/rust/checks/errors/rust-const-checker.h
gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
gcc/rust/checks/errors/rust-hir-pattern-analysis.h
gcc/rust/checks/errors/rust-unsafe-checker.cc
gcc/rust/checks/errors/rust-unsafe-checker.h
gcc/rust/hir/rust-ast-lower-expr.cc
gcc/rust/hir/rust-hir-dump.cc
gcc/rust/hir/rust-hir-dump.h
gcc/rust/hir/tree/rust-hir-expr-abstract.h
gcc/rust/hir/tree/rust-hir-expr.cc
gcc/rust/hir/tree/rust-hir-expr.h
gcc/rust/hir/tree/rust-hir-full-decls.h
gcc/rust/hir/tree/rust-hir-visitor.cc
gcc/rust/hir/tree/rust-hir-visitor.h
gcc/rust/typecheck/rust-hir-type-check-expr.cc
gcc/rust/typecheck/rust-hir-type-check-expr.h
gcc/testsuite/rust/compile/offset_of2.rs [new file with mode: 0644]

index 90515f648831cacbcb02398c2d365844f687d5f2..f84bace15af7bd273d3371e39e74291083b43f71 100644 (file)
@@ -20,6 +20,7 @@
 #define RUST_COMPILE_BLOCK
 
 #include "rust-compile-base.h"
+#include "rust-hir-expr.h"
 #include "rust-hir-visitor.h"
 
 namespace Rust {
@@ -103,6 +104,7 @@ public:
   void visit (HIR::AsyncBlockExpr &) override {}
   void visit (HIR::InlineAsm &) override {}
   void visit (HIR::LlvmInlineAsm &) override {}
+  void visit (HIR::OffsetOf &) override {}
 
 private:
   CompileConditionalBlocks (Context *ctx, Bvariable *result)
@@ -192,6 +194,7 @@ public:
   void visit (HIR::AsyncBlockExpr &) override {}
   void visit (HIR::InlineAsm &) override {}
   void visit (HIR::LlvmInlineAsm &) override {}
+  void visit (HIR::OffsetOf &) override {}
   void visit (HIR::AnonConst &) override {}
 
 private:
index 25da59d982d223ce572a20809626e2b3e8d9b659..547bb7c27a8eb3557ebaeb455dadf2309e23a70c 100644 (file)
@@ -375,6 +375,12 @@ CompileExpr::visit (HIR::LlvmInlineAsm &expr)
   ctx->add_statement (asm_codegen.tree_codegen_asm (expr));
 }
 
+void
+CompileExpr::visit (HIR::OffsetOf &expr)
+{
+  rust_unreachable ();
+}
+
 void
 CompileExpr::visit (HIR::IfExprConseqElse &expr)
 {
index bc347bf5066f58cfcf708fe616662f52f7ab52a8..b8b4e8dfdd5a3ffadeb6e54ef02a797d9ab0c3c2 100644 (file)
@@ -72,6 +72,7 @@ public:
   void visit (HIR::ClosureExpr &expr) override;
   void visit (HIR::InlineAsm &expr) override;
   void visit (HIR::LlvmInlineAsm &expr) override;
+  void visit (HIR::OffsetOf &expr) override;
 
   // TODO
   void visit (HIR::ErrorPropagationExpr &) override {}
index 0799a4ea84c1304cfe467e753087d1547b3ccb59..5b22c1a68a3d88ebeb889ea023d5c9919594cc8d 100644 (file)
@@ -330,6 +330,10 @@ void
 ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr)
 {}
 
+void
+ExprStmtBuilder::visit (HIR::OffsetOf &expr)
+{}
+
 void
 ExprStmtBuilder::visit (HIR::MethodCallExpr &expr)
 {}
index 45d3d584825b61dc1fca4c941148c69aa672dbfb..ba5db8b0c3e7029a67cdd4d8e622cacf286f734c 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef RUST_BIR_BUILDER_EXPR_H
 #define RUST_BIR_BUILDER_EXPR_H
 
+#include "rust-hir-expr.h"
 #include "rust-hir-visitor.h"
 #include "rust-bir-builder-internal.h"
 
@@ -103,6 +104,7 @@ protected: // Expr
   void visit (HIR::IfExprConseqElse &expr) override;
   void visit (HIR::InlineAsm &expr) override;
   void visit (HIR::LlvmInlineAsm &expr) override;
+  void visit (HIR::OffsetOf &expr) override;
 
   void visit (HIR::MatchExpr &expr) override;
   void visit (HIR::AwaitExpr &expr) override;
index a5ec5690743871f8b70b6df26ef632b5b8a2a574..9108009de1021f19e9820a0423388b737595b9cd 100644 (file)
@@ -216,6 +216,7 @@ public:
 
   void visit (HIR::InlineAsm &expr) override {}
   void visit (HIR::LlvmInlineAsm &expr) override {}
+  void visit (HIR::OffsetOf &expr) override {}
 
 protected: // Illegal at this position.
   void visit (HIR::StructExprFieldIdentifier &field) override
index 2e11f635110f390fd3429b65aa29cfc54549c145..d87ff8cb33c6c7704b97b698b4915c5fb6e3191f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "rust-bir-builder-internal.h"
 #include "rust-bir-builder-expr-stmt.h"
+#include "rust-hir-expr.h"
 
 namespace Rust {
 namespace BIR {
@@ -156,6 +157,7 @@ protected:
   void visit (HIR::AsyncBlockExpr &expr) override { rust_unreachable (); }
   void visit (HIR::InlineAsm &expr) override { rust_unreachable (); }
   void visit (HIR::LlvmInlineAsm &expr) override { rust_unreachable (); }
+  void visit (HIR::OffsetOf &expr) override { rust_unreachable (); }
   void visit (HIR::TypeParam &param) override { rust_unreachable (); }
   void visit (HIR::ConstGenericParam &param) override { rust_unreachable (); }
   void visit (HIR::LifetimeWhereClauseItem &item) override
index 860915e09202736f546d6b13bcf29687212239db..86f96c14d624ac8cb84e6e69eedc1cabc1592bcb 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef RUST_HIR_FUNCTION_COLLECTOR_H
 #define RUST_HIR_FUNCTION_COLLECTOR_H
 
+#include "rust-hir-expr.h"
 #include "rust-hir-item.h"
 #include "rust-hir-visitor.h"
 #include "rust-hir.h"
@@ -126,6 +127,7 @@ public:
   void visit (HIR::AsyncBlockExpr &expr) override {}
   void visit (HIR::InlineAsm &expr) override {}
   void visit (HIR::LlvmInlineAsm &expr) override {}
+  void visit (HIR::OffsetOf &expr) override {}
   void visit (HIR::TypeParam &param) override {}
   void visit (HIR::ConstGenericParam &param) override {}
   void visit (HIR::LifetimeWhereClauseItem &item) override {}
index e8a679214d4878fd7d6067422928b2885f57a5b2..af529931b26a14c0b6fba52d3f7cd2a021b3b36b 100644 (file)
@@ -313,6 +313,12 @@ void
 PrivacyReporter::visit (HIR::LlvmInlineAsm &)
 {}
 
+void
+PrivacyReporter::visit (HIR::OffsetOf &expr)
+{
+  // TODO: Do we have to do anything?
+}
+
 void
 PrivacyReporter::visit (HIR::TypePath &path)
 {
index 07eebf65df0256a361573be0bbca6bdbe2e9864a..72716a6aa8a335dc56f102e8f41a67060aa7bbaa 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef RUST_PRIVACY_REPORTER_H
 #define RUST_PRIVACY_REPORTER_H
 
+#include "rust-hir-expr.h"
 #include "rust-hir-map.h"
 #include "rust-hir-visitor.h"
 #include "rust-mapping-common.h"
@@ -128,6 +129,7 @@ types
   virtual void visit (HIR::AsyncBlockExpr &expr);
   virtual void visit (HIR::InlineAsm &expr);
   virtual void visit (HIR::LlvmInlineAsm &expr);
+  virtual void visit (HIR::OffsetOf &expr);
 
   virtual void visit (HIR::EnumItemTuple &);
   virtual void visit (HIR::EnumItemStruct &);
index 5cbab3d554ca17f9ea556123fb985617099a5679..c40f9db7d2cf412a33170f2b5cf3f3f24c3c8adf 100644 (file)
@@ -560,6 +560,10 @@ void
 ConstChecker::visit (LlvmInlineAsm &)
 {}
 
+void
+ConstChecker::visit (OffsetOf &)
+{}
+
 void
 ConstChecker::visit (TypeParam &)
 {}
index 22398747e585b2e478170f22afc6618e28b7aa8e..eb63095a2250841f5e8b18a5c388625adcd8fac3 100644 (file)
@@ -135,6 +135,7 @@ private:
   virtual void visit (AsyncBlockExpr &expr) override;
   virtual void visit (InlineAsm &expr) override;
   virtual void visit (LlvmInlineAsm &expr) override;
+  virtual void visit (OffsetOf &expr) override;
 
   virtual void visit (TypeParam &param) override;
   virtual void visit (ConstGenericParam &param) override;
index ec22a0ee92eba9343df5b81c1491024dde377bd2..25669713a00198158fe3f03a0349d2907d02f1fa 100644 (file)
@@ -438,6 +438,10 @@ void
 PatternChecker::visit (LlvmInlineAsm &expr)
 {}
 
+void
+PatternChecker::visit (OffsetOf &expr)
+{}
+
 void
 PatternChecker::visit (TypeParam &)
 {}
index 5766180ec799632688308575f45351e593d01748..dd44abca527dd74346d62032e8bde8942b912a7c 100644 (file)
@@ -109,6 +109,7 @@ private:
   virtual void visit (AsyncBlockExpr &expr) override;
   virtual void visit (InlineAsm &expr) override;
   virtual void visit (LlvmInlineAsm &expr) override;
+  virtual void visit (OffsetOf &expr) override;
   virtual void visit (TypeParam &param) override;
   virtual void visit (ConstGenericParam &param) override;
   virtual void visit (LifetimeWhereClauseItem &item) override;
index d90088faf74e2383d34c7f511882fc90e53409cd..405c59be09654979ef4a80dd84159bd0a56d2387 100644 (file)
@@ -693,6 +693,12 @@ UnsafeChecker::visit (LlvmInlineAsm &expr)
     "use of inline assembly is unsafe and requires unsafe function or block");
 }
 
+void
+UnsafeChecker::visit (OffsetOf &expr)
+{
+  // nothing to do, offset_of!() is safe
+}
+
 void
 UnsafeChecker::visit (TypeParam &)
 {}
index 8a9830f7cd6ef00bbb120670dc8d1dd8c95fd370..dc3b482f15bceef76e31a88dfb3f57fdaa816f8b 100644 (file)
@@ -117,6 +117,7 @@ private:
   virtual void visit (AsyncBlockExpr &expr) override;
   virtual void visit (InlineAsm &expr) override;
   virtual void visit (LlvmInlineAsm &expr) override;
+  virtual void visit (OffsetOf &expr) override;
   virtual void visit (TypeParam &param) override;
   virtual void visit (ConstGenericParam &param) override;
   virtual void visit (LifetimeWhereClauseItem &item) override;
index 31126a8ad35df139e4a6ac8c9faec32cb54a45d4..e9c9acc06c8e81d7ee672b6a98b99e5d01559306 100644 (file)
@@ -1059,8 +1059,16 @@ ASTLoweringExpr::visit (AST::FormatArgs &fmt)
 void
 ASTLoweringExpr::visit (AST::OffsetOf &offset_of)
 {
-  // FIXME: Implement HIR::OffsetOf node and const evaluation
-  rust_unreachable ();
+  auto type = std::unique_ptr<Type> (
+    ASTLoweringType::translate (offset_of.get_type ()));
+
+  auto crate_num = mappings.get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, offset_of.get_node_id (),
+                                mappings.get_next_hir_id (crate_num),
+                                mappings.get_next_localdef_id (crate_num));
+
+  translated = new HIR::OffsetOf (std::move (type), offset_of.get_field (),
+                                 mapping, offset_of.get_locus ());
 }
 
 } // namespace HIR
index 3d61de9e8bd582ce30d23df4af747dee260a743e..afee7b42f47f310360297452583b740adde5bf62 100644 (file)
@@ -1602,6 +1602,17 @@ void
 Dump::visit (LlvmInlineAsm &e)
 {}
 
+void
+Dump::visit (OffsetOf &e)
+{
+  begin ("OffsetOf");
+
+  put_field ("type", e.get_type ().as_string ());
+  put_field ("field", e.get_field ());
+
+  end ("OffsetOf");
+}
+
 void
 Dump::visit (TypeParam &e)
 {
index 8c39f489baff43f19b102ea50e9ec8ff167c3947..3e6ae3006a797e1c145c4e3b1d59032b81f6e6c4 100644 (file)
@@ -169,6 +169,7 @@ private:
   virtual void visit (AsyncBlockExpr &) override;
   virtual void visit (InlineAsm &) override;
   virtual void visit (LlvmInlineAsm &) override;
+  virtual void visit (OffsetOf &) override;
 
   virtual void visit (TypeParam &) override;
   virtual void visit (ConstGenericParam &) override;
index 8272a82808c90e76a27cd871bf226fe9066c9c0b..371daa835a248f50a66620b2685d8e8c093f0963 100644 (file)
@@ -74,6 +74,7 @@ public:
     Path,
     InlineAsm,
     LlvmInlineAsm,
+    OffsetOf,
   };
 
   BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; }
index 8544ed6708b76c3a29790a5eb2c4efc2a8a8415f..14786adf6f3f7e855e8fe0f21d2ef3133cd0b7b6 100644 (file)
@@ -1526,5 +1526,41 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm,
     clobber_abi (std::move (clobber_abi)), options (std::move (options))
 {}
 
+OffsetOf &
+OffsetOf::operator= (const OffsetOf &other)
+{
+  ExprWithoutBlock::operator= (other);
+
+  type = other.type->clone_type ();
+  field = other.field;
+  loc = other.loc;
+
+  return *this;
+}
+
+ExprWithoutBlock *
+OffsetOf::clone_expr_without_block_impl () const
+{
+  return new OffsetOf (*this);
+}
+
+std::string
+OffsetOf::as_string () const
+{
+  return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
+}
+
+void
+OffsetOf::accept_vis (HIRExpressionVisitor &vis)
+{
+  vis.visit (*this);
+}
+
+void
+OffsetOf::accept_vis (HIRFullVisitor &vis)
+{
+  vis.visit (*this);
+}
+
 } // namespace HIR
 } // namespace Rust
index 64d01ee6f00fe7d4524d99840605dbacca25e825..61e35905ea04df5d4109a8b2ea5f956bcc0fbadc 100644 (file)
@@ -3236,6 +3236,42 @@ public:
             AST::AttrVec outer_attribs = AST::AttrVec ());
 };
 
+class OffsetOf : public ExprWithoutBlock
+{
+public:
+  OffsetOf (std::unique_ptr<Type> &&type, Identifier field,
+           Analysis::NodeMapping mappings, location_t loc)
+    : ExprWithoutBlock (mappings), type (std::move (type)), field (field),
+      loc (loc)
+  {}
+
+  OffsetOf (const OffsetOf &other)
+    : ExprWithoutBlock (other), type (other.type->clone_type ()),
+      field (other.field), loc (other.loc)
+  {}
+
+  OffsetOf &operator= (const OffsetOf &other);
+
+  ExprWithoutBlock *clone_expr_without_block_impl () const override;
+  std::string as_string () const override;
+
+  void accept_vis (HIRExpressionVisitor &vis) override;
+  void accept_vis (HIRFullVisitor &vis) override;
+
+  ExprType get_expression_type () const override { return ExprType::OffsetOf; }
+
+  location_t get_locus () const override { return loc; }
+
+  Type &get_type () { return *type; }
+  const Type &get_type () const { return *type; }
+  const Identifier &get_field () const { return field; }
+
+private:
+  std::unique_ptr<Type> type;
+  Identifier field;
+  location_t loc;
+};
+
 struct LlvmOperand
 {
   std::string constraint;
index 2905117dcb7c75057596d0f99f023a06feea2fc6..57b3a4d0915a05f0b63313c61427a93c18f4fc04 100644 (file)
@@ -128,6 +128,7 @@ class InlineAsmRegClass;
 class InlineAsmOperand;
 class InlineAsm;
 class LlvmInlineAsm;
+class OffsetOf;
 
 // rust-stmt.h
 class EmptyStmt;
index 77b96e547af9d5e9e9782430ab641c24c6e42819..c77300aae3affd3d14d15b91760b612a66b43ac7 100644 (file)
@@ -603,6 +603,12 @@ DefaultHIRVisitor::walk (LlvmInlineAsm &expr)
     input.expr->accept_vis (*this);
 }
 
+void
+DefaultHIRVisitor::walk (OffsetOf &expr)
+{
+  expr.get_type ().accept_vis (*this);
+}
+
 void
 DefaultHIRVisitor::walk (TypeParam &param)
 {
index 544cf5128a5ef85b68831c4578937bca0cbe9dd0..79962604607c02cdf6c5a4b7f556e8fabab99d46 100644 (file)
@@ -88,6 +88,7 @@ public:
   virtual void visit (AsyncBlockExpr &expr) = 0;
   virtual void visit (InlineAsm &expr) = 0;
   virtual void visit (LlvmInlineAsm &expr) = 0;
+  virtual void visit (OffsetOf &expr) = 0;
   virtual void visit (TypeParam &param) = 0;
   virtual void visit (ConstGenericParam &param) = 0;
   virtual void visit (LifetimeWhereClauseItem &item) = 0;
@@ -254,6 +255,7 @@ public:
   virtual void visit (AsyncBlockExpr &node) override { walk (node); }
   virtual void visit (InlineAsm &node) override { walk (node); }
   virtual void visit (LlvmInlineAsm &node) override { walk (node); }
+  virtual void visit (OffsetOf &node) override { walk (node); }
   virtual void visit (TypeParam &node) override { walk (node); }
   virtual void visit (ConstGenericParam &node) override { walk (node); }
   virtual void visit (LifetimeWhereClauseItem &node) override { walk (node); }
@@ -392,6 +394,7 @@ protected:
   virtual void walk (AsyncBlockExpr &) final;
   virtual void walk (InlineAsm &) final;
   virtual void walk (LlvmInlineAsm &) final;
+  virtual void walk (OffsetOf &) final;
   virtual void walk (TypeParam &) final;
   virtual void walk (ConstGenericParam &) final;
   virtual void walk (LifetimeWhereClauseItem &) final;
@@ -531,6 +534,7 @@ public:
   virtual void visit (AsyncBlockExpr &) override {}
   virtual void visit (InlineAsm &) override {}
   virtual void visit (LlvmInlineAsm &) override {}
+  virtual void visit (OffsetOf &) override {}
 
   virtual void visit (TypeParam &) override {}
   virtual void visit (ConstGenericParam &) override {}
@@ -754,6 +758,7 @@ public:
   virtual void visit (IfExpr &expr) = 0;
   virtual void visit (IfExprConseqElse &expr) = 0;
   virtual void visit (InlineAsm &expr) = 0;
+  virtual void visit (OffsetOf &expr) = 0;
   virtual void visit (LlvmInlineAsm &expr) = 0;
   virtual void visit (MatchExpr &expr) = 0;
   virtual void visit (AwaitExpr &expr) = 0;
index ead751a0a7d64693eff76a154231fea9f653aa2e..4a105e77d91962710801db3134fe9589cca77d2e 100644 (file)
@@ -895,6 +895,19 @@ TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr)
   infered = TyTy::TupleType::get_unit_type ();
 }
 
+void
+TypeCheckExpr::visit (HIR::OffsetOf &expr)
+{
+  TypeCheckType::Resolve (expr.get_type ());
+
+  // FIXME: Does offset_of always return a usize?
+  TyTy::BaseType *size_ty;
+  bool ok = context->lookup_builtin ("usize", &size_ty);
+  rust_assert (ok);
+
+  infered = size_ty;
+}
+
 void
 TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
 {
index 48f28c7007959bd6e3ff0a61c7a6cc7c027e57e9..0343922407e3126d122c06e2c4987864e9d3e2f9 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef RUST_HIR_TYPE_CHECK_EXPR
 #define RUST_HIR_TYPE_CHECK_EXPR
 
+#include "rust-hir-expr.h"
 #include "rust-hir-type-check-base.h"
 #include "rust-hir-visitor.h"
 #include "rust-tyty.h"
@@ -78,6 +79,7 @@ public:
   void visit (HIR::ClosureExpr &expr) override;
   void visit (HIR::InlineAsm &expr) override;
   void visit (HIR::LlvmInlineAsm &expr) override;
+  void visit (HIR::OffsetOf &expr) override;
 
   // TODO
   void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/testsuite/rust/compile/offset_of2.rs b/gcc/testsuite/rust/compile/offset_of2.rs
new file mode 100644 (file)
index 0000000..d4ad9c2
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-additional-options "-frust-compile-until=compilation -frust-assume-builtin-offset-of" }
+
+pub struct Foo {
+    a: i32,
+}
+
+fn main() {
+    let _ = offset_of!(Foo, a); // valid
+}