From: Yap Zhi Heng <[email protected]>

GIMPLE output for literalpattern_neg.rs test case:

...
  x = -55;
  RUSTTMP.2 = x;
  if (RUSTTMP.2 == 55) goto <D.113>; else goto <D.114>;
  <D.113>:
  {
    RUSTTMP.1 = 1;
    goto <D.107>;
  }
  <D.114>:
  if (RUSTTMP.2 == -55) goto <D.115>; else goto <D.116>;
  <D.115>:
  {
    RUSTTMP.1 = 0;
    goto <D.107>;
  }
  <D.116>:
  if (1 != 0) goto <D.117>; else goto <D.118>;
  <D.117>:
  {
    RUSTTMP.1 = 1;
    goto <D.107>;
  }
...

gcc/rust/ChangeLog:

        * parse/rust-parse-impl.h (parse_literal_or_range_pattern): Parse minus 
sign
        properly for LiteralPattern.
        * ast/rust-pattern.h (LiteralPattern): Add has_minus boolean for 
LiteralPattern.
        * hir/tree/rust-hir-pattern.h (LiteralPattern): Ditto.
        * ast/rust-pattern.cc (LiteralPattern::as_string): Update to include 
minus sign
        if present.
        * hir/tree/rust-hir.cc (LiteralPattern::as_string): Ditto.
        * hir/rust-ast-lower-pattern.cc (visit(LiteralPattern)): Pass has_minus 
boolean
        from AST to HIR.
        * backend/rust-compile-pattern.cc 
(CompilePatternCheckExpr::visit(LiteralPattern)):
        Compile litexpr as negative if minus sign is present.

Signed-off-by: Yap Zhi Heng <[email protected]>
---
 gcc/rust/ast/rust-pattern.cc                  |  2 +-
 gcc/rust/ast/rust-pattern.h                   | 22 +++++++++++++++++--
 gcc/rust/backend/rust-compile-pattern.cc      |  2 ++
 gcc/rust/hir/rust-ast-lower-pattern.cc        |  3 ++-
 gcc/rust/hir/tree/rust-hir-pattern.h          | 14 ++++++++++--
 gcc/rust/hir/tree/rust-hir.cc                 |  2 +-
 gcc/rust/parse/rust-parse-impl.h              |  2 +-
 .../execute/torture/literalpattern_neg.rs     |  9 ++++++++
 8 files changed, 48 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/literalpattern_neg.rs

diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index a2fe5d59081..80189d3746b 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -48,7 +48,7 @@ tokenid_to_rangekind (TokenId id)
 std::string
 LiteralPattern::as_string () const
 {
-  return lit.as_string ();
+  return (has_minus ? "-" : "") + lit.as_string ();
 }
 
 std::string
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 0da1981928f..3b1bd1c29ec 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -30,6 +30,7 @@ class LiteralPattern : public Pattern
   Literal lit;
   location_t locus;
   NodeId node_id;
+  bool has_minus;
 
 public:
   std::string as_string () const override;
@@ -37,17 +38,34 @@ public:
   // Constructor for a literal pattern
   LiteralPattern (Literal lit, location_t locus)
     : lit (std::move (lit)), locus (locus),
-      node_id (Analysis::Mappings::get ().get_next_node_id ())
+      node_id (Analysis::Mappings::get ().get_next_node_id ()),
+      has_minus (false)
+  {}
+
+  LiteralPattern (Literal lit, location_t locus, bool has_minus)
+    : lit (std::move (lit)), locus (locus),
+      node_id (Analysis::Mappings::get ().get_next_node_id ()),
+      has_minus (has_minus)
   {}
 
   LiteralPattern (std::string val, Literal::LitType type, location_t locus,
                  PrimitiveCoreType type_hint)
     : lit (Literal (std::move (val), type, type_hint)), locus (locus),
-      node_id (Analysis::Mappings::get ().get_next_node_id ())
+      node_id (Analysis::Mappings::get ().get_next_node_id ()),
+      has_minus (false)
+  {}
+
+  LiteralPattern (std::string val, Literal::LitType type, location_t locus,
+                 PrimitiveCoreType type_hint, bool has_minus)
+    : lit (Literal (std::move (val), type, type_hint)), locus (locus),
+      node_id (Analysis::Mappings::get ().get_next_node_id ()),
+      has_minus (has_minus)
   {}
 
   location_t get_locus () const override final { return locus; }
 
+  bool get_has_minus () const { return has_minus; }
+
   void accept_vis (ASTVisitor &vis) override;
 
   NodeId get_node_id () const override { return node_id; }
diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index 82333dc39c0..3a983e9bc88 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -87,6 +87,8 @@ CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern)
   auto litexpr = std::make_unique<HIR::LiteralExpr> (
     HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (),
                      pattern.get_locus (), std::vector<AST::Attribute> ()));
+  if (pattern.get_has_minus ())
+    litexpr->set_negative ();
 
   // Note: Floating point literals are currently accepted but will likely be
   // forbidden in LiteralPatterns in a future version of Rust.
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc 
b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 4250adbfbab..c941a5c9af9 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -280,7 +280,8 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
 
   HIR::Literal l = lower_literal (pattern.get_literal ());
   translated
-    = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ());
+    = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (),
+                              pattern.get_has_minus ());
 }
 
 void
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h 
b/gcc/rust/hir/tree/rust-hir-pattern.h
index 89b9cc6a06c..a2c408fdc77 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -32,19 +32,27 @@ class LiteralPattern : public Pattern
   Literal lit;
   location_t locus;
   Analysis::NodeMapping mappings;
+  bool has_minus;
 
 public:
   std::string as_string () const override;
 
   // Constructor for a literal pattern
   LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t 
locus)
-    : lit (std::move (lit)), locus (locus), mappings (mappings)
+    : lit (std::move (lit)), locus (locus), mappings (mappings),
+      has_minus (false)
+  {}
+
+  LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t 
locus,
+                 bool has_minus)
+    : lit (std::move (lit)), locus (locus), mappings (mappings),
+      has_minus (has_minus)
   {}
 
   LiteralPattern (Analysis::NodeMapping mappings, std::string val,
                  Literal::LitType type, location_t locus)
     : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)),
-      locus (locus), mappings (mappings)
+      locus (locus), mappings (mappings), has_minus (false)
   {}
 
   location_t get_locus () const override { return locus; }
@@ -65,6 +73,8 @@ public:
   Literal &get_literal () { return lit; }
   const Literal &get_literal () const { return lit; }
 
+  bool get_has_minus () const { return has_minus; }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index ce10b02303c..57f560b06d3 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -2634,7 +2634,7 @@ StructPattern::as_string () const
 std::string
 LiteralPattern::as_string () const
 {
-  return lit.as_string ();
+  return (has_minus ? "-" : "") + lit.as_string ();
 }
 
 std::string
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index ec4c1c1d6c7..e7972770455 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -10345,7 +10345,7 @@ 
Parser<ManagedTokenSource>::parse_literal_or_range_pattern ()
       return std::unique_ptr<AST::LiteralPattern> (
        new AST::LiteralPattern (range_lower->get_str (), type,
                                 range_lower->get_locus (),
-                                range_lower->get_type_hint ()));
+                                range_lower->get_type_hint (), has_minus));
     }
 }
 
diff --git a/gcc/testsuite/rust/execute/torture/literalpattern_neg.rs 
b/gcc/testsuite/rust/execute/torture/literalpattern_neg.rs
new file mode 100644
index 00000000000..3553c4a3462
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/literalpattern_neg.rs
@@ -0,0 +1,9 @@
+fn main() -> i32 {
+    let x = -55;
+
+    match x {
+        55 => 1,
+        -55 => 0, // correct case
+        _ => 1
+    }
+}
\ No newline at end of file
-- 
2.50.1

Reply via email to