From: Islam-Imad <[email protected]>

CompoundAssignmentExpr codegen was missing the final assignment statement
when it was evaluated in a const context.

gcc/rust/ChangeLog:

        * backend/rust-compile-expr.cc (CompileExpr::visit): Emit the
        missing assignment for CompoundAssignmentExpr.

gcc/testsuite/ChangeLog:

        * rust/compile/const-compound-assignment.rs: New test.
        * rust/execute/const-compound-assignment.rs: New test.

Signed-off-by: Islam-Imad <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/679aad3804e8443ec5181fd184785d82aec42bdf

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4520

 gcc/rust/backend/rust-compile-expr.cc         | 27 +++++++-------
 .../rust/compile/const-compound-assignment.rs | 15 ++++++++
 .../rust/execute/const-compound-assignment.rs | 35 +++++++++++++++++++
 3 files changed, 63 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/const-compound-assignment.rs
 create mode 100644 gcc/testsuite/rust/execute/const-compound-assignment.rs

diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index 55b3534a1..6b21a7745 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -192,9 +192,9 @@ void
 CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
 {
   auto op = expr.get_expr_type ();
-  auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
-  auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
-
+  tree lhs = CompileExpr::Compile (expr.get_lhs (), ctx);
+  tree rhs = CompileExpr::Compile (expr.get_rhs (), ctx);
+  tree compound_assignment = NULL_TREE;
   // this might be an operator overload situation lets check
   TyTy::FnType *fntype;
   bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
@@ -203,38 +203,37 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
     {
       auto lang_item_type = LangItem::CompoundAssignmentOperatorToLangItem (
        expr.get_expr_type ());
-      auto compound_assignment
+      compound_assignment
        = resolve_operator_overload (lang_item_type, expr, lhs, rhs,
                                     expr.get_lhs (), expr.get_rhs ());
-      ctx->add_statement (compound_assignment);
-
-      return;
     }
-
-  if (ctx->in_fn () && !ctx->const_context_p ())
+  else if (ctx->in_fn () && !ctx->const_context_p ())
     {
-      auto tmp = NULL_TREE;
+      tree tmp = NULL_TREE;
       Bvariable *receiver
        = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
                                       TREE_TYPE (lhs), lhs, true,
                                       expr.get_locus (), &tmp);
-      auto check
+      tree check
        = Backend::arithmetic_or_logical_expression_checked (op, lhs, rhs,
                                                             expr.get_locus (),
                                                             receiver);
       ctx->add_statement (check);
-
-      translated
+      compound_assignment
        = Backend::assignment_statement (lhs,
                                         receiver->get_tree (expr.get_locus ()),
                                         expr.get_locus ());
     }
   else
     {
-      translated
+      tree expr_tree
        = Backend::arithmetic_or_logical_expression (op, lhs, rhs,
                                                     expr.get_locus ());
+      compound_assignment
+       = Backend::assignment_statement (lhs, expr_tree, expr.get_locus ());
     }
+  ctx->add_statement (compound_assignment);
+  translated = unit_expression (expr.get_locus ());
 }
 
 void
diff --git a/gcc/testsuite/rust/compile/const-compound-assignment.rs 
b/gcc/testsuite/rust/compile/const-compound-assignment.rs
new file mode 100644
index 000000000..3ec68ba44
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const-compound-assignment.rs
@@ -0,0 +1,15 @@
+// { dg-options "-w -O0 -fdump-tree-gimple" }
+#![feature(no_core)]
+#![no_core]
+
+const fn test(mut x: i32) -> i32 {
+    x += 5;
+    x
+}
+
+const X: i32 = test(10);
+
+fn main() {
+    // { dg-final { scan-tree-dump-times {x = 15} 1 gimple } }
+    let x = X;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/const-compound-assignment.rs 
b/gcc/testsuite/rust/execute/const-compound-assignment.rs
new file mode 100644
index 000000000..ce5ddde8e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/const-compound-assignment.rs
@@ -0,0 +1,35 @@
+// { dg-output "45\r*\n55\r*\n" }
+#![feature(no_core)]
+#![no_core]
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn dump_number(num: i32) {
+    unsafe {
+        let a = "%i\n\0";
+        let c = a as *const str as *const i8;
+        printf(c, num);
+    }
+}
+
+const fn play(b: i32) -> i32 {
+    let mut res = 0;
+    let mut i = 0;
+    while i < b {
+        res += i;
+        i += 1;
+    }
+    res
+}
+
+fn main() -> i32 {
+    const A: i32 = play(10);
+    dump_number(A);
+
+    let b: i32 = play(11);
+    dump_number(b);
+
+    0
+}

base-commit: 3432069729f6868c92de792e09d0c803dcc1618e
-- 
2.53.0

Reply via email to