aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc37
-rw-r--r--gcc/rust/backend/rust-compile-expr.h21
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h33
-rw-r--r--gcc/rust/util/rust-hir-map.h8
-rw-r--r--gcc/testsuite/rust/execute/torture/operator_overload_10.rs79
-rw-r--r--gcc/testsuite/rust/execute/torture/operator_overload_7.rs44
-rw-r--r--gcc/testsuite/rust/execute/torture/operator_overload_8.rs61
-rw-r--r--gcc/testsuite/rust/execute/torture/operator_overload_9.rs61
8 files changed, 321 insertions, 23 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index fb01d8d..6051f50 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -117,6 +117,43 @@ CompileExpr::visit (HIR::NegationExpr &expr)
= ctx->get_backend ()->negation_expression (op, negated_expr, location);
}
+void
+CompileExpr::visit (HIR::DereferenceExpr &expr)
+{
+ TyTy::BaseType *tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty))
+ {
+ rust_fatal_error (expr.get_locus (),
+ "did not resolve type for this TupleExpr");
+ return;
+ }
+
+ tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
+
+ // this might be an operator overload situation lets check
+ TyTy::FnType *fntype;
+ bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
+ expr.get_mappings ().get_hirid (), &fntype);
+ if (is_op_overload)
+ {
+ auto lang_item_type = Analysis::RustLangItem::ItemType::DEREF;
+ tree operator_overload_call
+ = resolve_operator_overload (lang_item_type, expr, main_expr, nullptr,
+ expr.get_expr ().get (), nullptr);
+
+ // rust deref always returns a reference from this overload then we can
+ // actually do the indirection
+ main_expr = operator_overload_call;
+ }
+
+ tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
+ bool known_valid = true;
+ translated
+ = ctx->get_backend ()->indirect_expression (expected_type, main_expr,
+ known_valid, expr.get_locus ());
+}
+
tree
CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn,
TyTy::BaseType *receiver,
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 46d501a..1e8e1f6 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -979,26 +979,7 @@ public:
= ctx->get_backend ()->address_expression (main_expr, expr.get_locus ());
}
- void visit (HIR::DereferenceExpr &expr) override
- {
- tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
-
- TyTy::BaseType *tyty = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &tyty))
- {
- rust_fatal_error (expr.get_locus (),
- "did not resolve type for this TupleExpr");
- return;
- }
-
- tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
- bool known_valid = true;
- translated
- = ctx->get_backend ()->indirect_expression (expected_type, main_expr,
- known_valid,
- expr.get_locus ());
- }
+ void visit (HIR::DereferenceExpr &expr) override;
protected:
tree compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 5d6017c..1015cc2 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -1219,6 +1219,18 @@ public:
TyTy::BaseType *resolved_base
= TypeCheckExpr::Resolve (expr.get_expr ().get (), false);
+ auto lang_item_type = Analysis::RustLangItem::ItemType::DEREF;
+ bool operator_overloaded
+ = resolve_operator_overload (lang_item_type, expr, resolved_base,
+ nullptr);
+ if (operator_overloaded)
+ {
+ // operator overloaded deref always refurns a reference type lets assert
+ // this
+ rust_assert (infered->get_kind () == TyTy::TypeKind::REF);
+ resolved_base = infered;
+ }
+
bool is_valid_type
= resolved_base->get_kind () == TyTy::TypeKind::REF
|| resolved_base->get_kind () == TyTy::TypeKind::POINTER;
@@ -1281,9 +1293,24 @@ protected:
bool probe_impls = !receiver_is_generic;
bool ignore_mandatory_trait_items = !receiver_is_generic;
- auto candidates = PathProbeType::Probe (
- root, HIR::PathIdentSegment (associated_item_name), probe_impls,
- probe_bounds, ignore_mandatory_trait_items, respective_lang_item_id);
+ auto probe_type = probe_impls ? lhs : root;
+ auto candidates
+ = PathProbeType::Probe (probe_type,
+ HIR::PathIdentSegment (associated_item_name),
+ probe_impls, probe_bounds,
+ ignore_mandatory_trait_items);
+ if (candidates.empty ())
+ {
+ if (probe_impls)
+ {
+ candidates = PathProbeType::Probe (
+ root, HIR::PathIdentSegment (associated_item_name), probe_impls,
+ probe_bounds, ignore_mandatory_trait_items);
+ }
+
+ if (candidates.empty ())
+ return false;
+ }
// autoderef to find the relevant method
std::vector<Adjustment> adjustments;
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 4f8c389..77a4caf 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -51,6 +51,8 @@ public:
DIV_ASSIGN,
REM_ASSIGN,
+ DEREF,
+
UNKNOWN,
};
@@ -104,6 +106,10 @@ public:
{
return ItemType::REM_ASSIGN;
}
+ else if (item.compare ("deref") == 0)
+ {
+ return ItemType::DEREF;
+ }
return ItemType::UNKNOWN;
}
@@ -136,6 +142,8 @@ public:
return "div_assign";
case REM_ASSIGN:
return "rem_assign";
+ case DEREF:
+ return "deref";
case UNKNOWN:
break;
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_10.rs b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
new file mode 100644
index 0000000..23ae778
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
@@ -0,0 +1,79 @@
+/* { dg-output "foo_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 }
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+fn main() -> i32 {
+ let foo: Foo<i32> = Foo(123);
+ let bar: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_7.rs b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
new file mode 100644
index 0000000..6ff3a87
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
@@ -0,0 +1,44 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 }
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+fn main() -> i32 {
+ let foo: &i32 = &123;
+ let res: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_8.rs b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
new file mode 100644
index 0000000..d853d71
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
@@ -0,0 +1,61 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 }
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+fn main() -> i32 {
+ let foo: &i32 = &123;
+ let res: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
new file mode 100644
index 0000000..5c770e7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
@@ -0,0 +1,61 @@
+/* { dg-output "mut_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 }
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+fn main() -> i32 {
+ let foo = &mut 123;
+ let res: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}