From: Arthur Cohen <arthur.co...@embecosm.com>

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.
---
 gcc/rust/backend/rust-compile-block.h         |  3 ++
 gcc/rust/backend/rust-compile-expr.cc         |  6 ++++
 gcc/rust/backend/rust-compile-expr.h          |  1 +
 .../borrowck/rust-bir-builder-expr-stmt.cc    |  4 +++
 .../borrowck/rust-bir-builder-expr-stmt.h     |  2 ++
 .../borrowck/rust-bir-builder-lazyboolexpr.h  |  1 +
 .../errors/borrowck/rust-bir-builder-struct.h |  2 ++
 .../errors/borrowck/rust-function-collector.h |  2 ++
 .../errors/privacy/rust-privacy-reporter.cc   |  6 ++++
 .../errors/privacy/rust-privacy-reporter.h    |  2 ++
 gcc/rust/checks/errors/rust-const-checker.cc  |  4 +++
 gcc/rust/checks/errors/rust-const-checker.h   |  1 +
 .../errors/rust-hir-pattern-analysis.cc       |  4 +++
 .../checks/errors/rust-hir-pattern-analysis.h |  1 +
 gcc/rust/checks/errors/rust-unsafe-checker.cc |  6 ++++
 gcc/rust/checks/errors/rust-unsafe-checker.h  |  1 +
 gcc/rust/hir/rust-ast-lower-expr.cc           | 12 +++++--
 gcc/rust/hir/rust-hir-dump.cc                 | 11 ++++++
 gcc/rust/hir/rust-hir-dump.h                  |  1 +
 gcc/rust/hir/tree/rust-hir-expr-abstract.h    |  1 +
 gcc/rust/hir/tree/rust-hir-expr.cc            | 36 +++++++++++++++++++
 gcc/rust/hir/tree/rust-hir-expr.h             | 36 +++++++++++++++++++
 gcc/rust/hir/tree/rust-hir-full-decls.h       |  1 +
 gcc/rust/hir/tree/rust-hir-visitor.cc         |  6 ++++
 gcc/rust/hir/tree/rust-hir-visitor.h          |  5 +++
 .../typecheck/rust-hir-type-check-expr.cc     | 13 +++++++
 gcc/rust/typecheck/rust-hir-type-check-expr.h |  2 ++
 gcc/testsuite/rust/compile/offset_of2.rs      |  9 +++++
 28 files changed, 177 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/offset_of2.rs

diff --git a/gcc/rust/backend/rust-compile-block.h 
b/gcc/rust/backend/rust-compile-block.h
index 90515f64883..f84bace15af 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -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:
diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index 25da59d982d..547bb7c27a8 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -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)
 {
diff --git a/gcc/rust/backend/rust-compile-expr.h 
b/gcc/rust/backend/rust-compile-expr.h
index bc347bf5066..b8b4e8dfdd5 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -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 {}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 0799a4ea84c..5b22c1a68a3 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -330,6 +330,10 @@ void
 ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr)
 {}
 
+void
+ExprStmtBuilder::visit (HIR::OffsetOf &expr)
+{}
+
 void
 ExprStmtBuilder::visit (HIR::MethodCallExpr &expr)
 {}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
index 45d3d584825..ba5db8b0c3e 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
@@ -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;
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
index a5ec5690743..9108009de10 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
@@ -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
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index 2e11f635110..d87ff8cb33c 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -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
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h 
b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index 860915e0920..86f96c14d62 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -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 {}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc 
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index e8a679214d4..af529931b26 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -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)
 {
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h 
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 07eebf65df0..72716a6aa8a 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -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 &);
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc 
b/gcc/rust/checks/errors/rust-const-checker.cc
index 5cbab3d554c..c40f9db7d2c 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -560,6 +560,10 @@ void
 ConstChecker::visit (LlvmInlineAsm &)
 {}
 
+void
+ConstChecker::visit (OffsetOf &)
+{}
+
 void
 ConstChecker::visit (TypeParam &)
 {}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h 
b/gcc/rust/checks/errors/rust-const-checker.h
index 22398747e58..eb63095a225 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -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;
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index ec22a0ee92e..25669713a00 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -438,6 +438,10 @@ void
 PatternChecker::visit (LlvmInlineAsm &expr)
 {}
 
+void
+PatternChecker::visit (OffsetOf &expr)
+{}
+
 void
 PatternChecker::visit (TypeParam &)
 {}
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h 
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 5766180ec79..dd44abca527 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -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;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc 
b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index d90088faf74..405c59be096 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -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 &)
 {}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h 
b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 8a9830f7cd6..dc3b482f15b 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -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;
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc 
b/gcc/rust/hir/rust-ast-lower-expr.cc
index 31126a8ad35..e9c9acc06c8 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -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
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index 3d61de9e8bd..afee7b42f47 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -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)
 {
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 8c39f489baf..3e6ae3006a7 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -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;
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h 
b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
index 8272a82808c..371daa835a2 100644
--- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h
+++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
@@ -74,6 +74,7 @@ public:
     Path,
     InlineAsm,
     LlvmInlineAsm,
+    OffsetOf,
   };
 
   BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; }
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc 
b/gcc/rust/hir/tree/rust-hir-expr.cc
index 8544ed6708b..14786adf6f3 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -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
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h 
b/gcc/rust/hir/tree/rust-hir-expr.h
index 64d01ee6f00..61e35905ea0 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -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;
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h 
b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 2905117dcb7..57b3a4d0915 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -128,6 +128,7 @@ class InlineAsmRegClass;
 class InlineAsmOperand;
 class InlineAsm;
 class LlvmInlineAsm;
+class OffsetOf;
 
 // rust-stmt.h
 class EmptyStmt;
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc 
b/gcc/rust/hir/tree/rust-hir-visitor.cc
index 77b96e547af..c77300aae3a 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.cc
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -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)
 {
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h 
b/gcc/rust/hir/tree/rust-hir-visitor.h
index 544cf5128a5..79962604607 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -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;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index ead751a0a7d..4a105e77d91 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -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)
 {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h 
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 48f28c70079..0343922407e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -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
index 00000000000..d4ad9c2db31
--- /dev/null
+++ b/gcc/testsuite/rust/compile/offset_of2.rs
@@ -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
+}
-- 
2.49.0

Reply via email to