From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 715D2398AC33; Wed, 8 Jun 2022 11:51:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 715D2398AC33 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Add negation operator overload support X-Act-Checkin: gcc X-Git-Author: Philip Herron X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 0f74fe23c6d602c257ba94b2522bd9d6a594609e X-Git-Newrev: 04a49acfa3caa7a85a1a9edd24d69da0ad575ad5 Message-Id: <20220608115119.715D2398AC33@sourceware.org> Date: Wed, 8 Jun 2022 11:51:19 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Jun 2022 11:51:19 -0000 https://gcc.gnu.org/g:04a49acfa3caa7a85a1a9edd24d69da0ad575ad5 commit 04a49acfa3caa7a85a1a9edd24d69da0ad575ad5 Author: Philip Herron Date: Mon Nov 15 18:13:32 2021 +0000 Add negation operator overload support Unary operator expressions can be treated as simply having a nullptr rvalue. This patch updates the shared operator overloading code to allow for a nullptr rhs to canonicalize the code path for all operator overloads. Fixes #249 Diff: --- gcc/rust/backend/rust-compile-expr.cc | 31 +++++++++++++++++-- gcc/rust/backend/rust-compile-expr.h | 10 +----- gcc/rust/typecheck/rust-hir-type-check-expr.h | 26 +++++++++++++--- gcc/rust/util/rust-hir-map.h | 34 ++++++++++++++------ .../rust/execute/torture/operator_overload_4.rs | 36 ++++++++++++++++++++++ .../rust/execute/torture/operator_overload_5.rs | 36 ++++++++++++++++++++++ 6 files changed, 147 insertions(+), 26 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 8902574baec..594cfffb498 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -92,6 +92,31 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr) ctx->add_statement (assignment); } +void +CompileExpr::visit (HIR::NegationExpr &expr) +{ + auto op = expr.get_expr_type (); + auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + auto location = expr.get_locus (); + + // 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::NegationOperatorToLangItem (op); + translated + = resolve_operator_overload (lang_item_type, expr, negated_expr, + nullptr, expr.get_expr ().get (), nullptr); + return; + } + + translated + = ctx->get_backend ()->negation_expression (op, negated_expr, location); +} + Bexpression * CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, TyTy::BaseType *receiver, @@ -311,7 +336,8 @@ CompileExpr::resolve_operator_overload ( = static_cast (receiver->get_root ()); std::vector arguments; - arguments.push_back (rhs_expr); + if (rhs_expr != nullptr) // can be null for negation_expr (unary ones) + arguments.push_back (rhs_expr); return compile_dyn_dispatch_call (dyn, receiver, fntype, lhs, arguments, expr.get_locus ()); @@ -356,7 +382,8 @@ CompileExpr::resolve_operator_overload ( std::vector args; args.push_back (self); // adjusted self - args.push_back (rhs); + if (rhs != nullptr) // can be null for negation_expr (unary ones) + args.push_back (rhs); auto fncontext = ctx->peek_fn (); return ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args, diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 7238d45a270..b4079f7e4ac 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -474,15 +474,7 @@ public: = ctx->get_backend ()->lazy_boolean_expression (op, lhs, rhs, location); } - void visit (HIR::NegationExpr &expr) override - { - auto op = expr.get_expr_type (); - auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); - auto location = expr.get_locus (); - - translated - = ctx->get_backend ()->negation_expression (op, negated_expr, location); - } + void visit (HIR::NegationExpr &expr) override; void visit (HIR::TypeCastExpr &expr) override { diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 37cd6b303dd..642bde241d8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -792,6 +792,15 @@ public: auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ().get (), false); + // check for operator overload + auto lang_item_type = Analysis::RustLangItem::NegationOperatorToLangItem ( + expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, negated_expr_ty, + nullptr); + if (operator_overloaded) + return; + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_expr_type ()) { @@ -1380,11 +1389,18 @@ protected: } } - // type check the arguments + // type check the arguments if required TyTy::FnType *type = static_cast (lookup); - rust_assert (type->num_params () == 2); - auto fnparam = type->param_at (1); - fnparam.second->unify (rhs); // typecheck the rhs + if (rhs == nullptr) + { + rust_assert (type->num_params () == 1); + } + else + { + rust_assert (type->num_params () == 2); + auto fnparam = type->param_at (1); + fnparam.second->unify (rhs); // typecheck the rhs + } // get the return type TyTy::BaseType *function_ret_tyty = fn->get_return_type ()->clone (); @@ -1481,7 +1497,7 @@ private: Location root_array_expr_locus; bool inside_loop; -}; +}; // namespace Resolver } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index bcbd582b34b..4f8c3899a33 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -43,6 +43,7 @@ public: REMAINDER, NEGATION, + NOT, ADD_ASSIGN, SUB_ASSIGN, @@ -79,6 +80,10 @@ public: { return ItemType::NEGATION; } + else if (item.compare ("not") == 0) + { + return ItemType::NOT; + } else if (item.compare ("add_assign") == 0) { return ItemType::ADD_ASSIGN; @@ -119,6 +124,8 @@ public: return "rem"; case NEGATION: return "neg"; + case NOT: + return "not"; case ADD_ASSIGN: return "add_assign"; case SUB_ASSIGN: @@ -151,11 +158,7 @@ public: case ArithmeticOrLogicalOperator::MODULUS: return ItemType::REMAINDER; - case ArithmeticOrLogicalOperator::BITWISE_AND: - case ArithmeticOrLogicalOperator::BITWISE_OR: - case ArithmeticOrLogicalOperator::BITWISE_XOR: - case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + default: return ItemType::UNKNOWN; } return ItemType::UNKNOWN; @@ -177,11 +180,22 @@ public: case ArithmeticOrLogicalOperator::MODULUS: return ItemType::REM_ASSIGN; - case ArithmeticOrLogicalOperator::BITWISE_AND: - case ArithmeticOrLogicalOperator::BITWISE_OR: - case ArithmeticOrLogicalOperator::BITWISE_XOR: - case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + default: + return ItemType::UNKNOWN; + } + return ItemType::UNKNOWN; + } + + static ItemType NegationOperatorToLangItem (NegationOperator op) + { + switch (op) + { + case NegationOperator::NEGATE: + return ItemType::NEGATION; + case NegationOperator::NOT: + return ItemType::NOT; + + default: return ItemType::UNKNOWN; } return ItemType::UNKNOWN; diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs new file mode 100644 index 00000000000..eca19de309a --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs @@ -0,0 +1,36 @@ +/* { dg-output "neg\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "neg"] +pub trait Neg { + type Output; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn neg(self) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Neg::neg." "" { target *-*-* } .-2 } +} + +impl Neg for i32 { + type Output = i32; + + fn neg(self) -> i32 { + unsafe { + let a = "neg\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + -self + } +} + +fn main() -> i32 { + let a: i32 = 1; + let _b = -a; + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs new file mode 100644 index 00000000000..ffdc8c23280 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs @@ -0,0 +1,36 @@ +/* { dg-output "not\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "not"] +pub trait Not { + type Output; + // { dg-warning "unused name" "" { target *-*-* } .-1 } + + fn not(self) -> Self::Output; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Not::not." "" { target *-*-* } .-2 } +} + +impl Not for i32 { + type Output = i32; + + fn not(self) -> i32 { + unsafe { + let a = "not\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + !self + } +} + +fn main() -> i32 { + let a: i32 = 1; + let _b = !a; + + 0 +}