aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-pattern.h28
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc58
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc45
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h3
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc18
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-pattern.h44
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc34
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc77
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.h7
-rw-r--r--gcc/testsuite/rust/execute/torture/match_range1.rs34
-rw-r--r--gcc/testsuite/rust/execute/torture/match_range2.rs40
14 files changed, 393 insertions, 1 deletions
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index a3193f7..247af5d 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -195,6 +195,13 @@ protected:
class RangePatternBound
{
public:
+ enum RangePatternBoundType
+ {
+ LITERAL,
+ PATH,
+ QUALPATH
+ };
+
virtual ~RangePatternBound () {}
// Unique pointer custom clone function
@@ -208,6 +215,8 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ virtual RangePatternBoundType get_bound_type () const = 0;
+
protected:
// pure virtual as RangePatternBound is abstract
virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0;
@@ -234,10 +243,19 @@ public:
std::string as_string () const override;
+ Literal get_literal () const { return literal; }
+
+ bool get_has_minus () const { return has_minus; }
+
Location get_locus () const { return locus; }
void accept_vis (ASTVisitor &vis) override;
+ RangePatternBoundType get_bound_type () const override
+ {
+ return RangePatternBoundType::LITERAL;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -268,6 +286,11 @@ public:
PathInExpression &get_path () { return path; }
const PathInExpression &get_path () const { return path; }
+ RangePatternBoundType get_bound_type () const override
+ {
+ return RangePatternBoundType::PATH;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -300,6 +323,11 @@ public:
QualifiedPathInExpression &get_qualified_path () { return path; }
const QualifiedPathInExpression &get_qualified_path () const { return path; }
+ RangePatternBoundType get_bound_type () const override
+ {
+ return RangePatternBoundType::QUALPATH;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index 9c1a35a..aefa4eb 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -105,6 +105,64 @@ CompilePatternCaseLabelExpr::visit (HIR::LiteralPattern &pattern)
case_label_expr = build_case_label (lit, NULL_TREE, associated_case_label);
}
+static tree
+compile_range_pattern_bound (HIR::RangePatternBound *bound,
+ Analysis::NodeMapping mappings, Location locus,
+ Context *ctx)
+{
+ tree result = NULL_TREE;
+ switch (bound->get_bound_type ())
+ {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ HIR::RangePatternBoundLiteral &ref
+ = *static_cast<HIR::RangePatternBoundLiteral *> (bound);
+
+ HIR::LiteralExpr *litexpr
+ = new HIR::LiteralExpr (mappings, ref.get_literal (), locus,
+ std::vector<AST::Attribute> ());
+
+ result = CompileExpr::Compile (litexpr, ctx);
+ }
+ break;
+
+ case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ HIR::RangePatternBoundPath &ref
+ = *static_cast<HIR::RangePatternBoundPath *> (bound);
+
+ result = ResolvePathRef::Compile (ref.get_path (), ctx);
+
+ // If the path resolves to a const expression, fold it.
+ result = ConstCtx::fold (result);
+ }
+ break;
+
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ HIR::RangePatternBoundQualPath &ref
+ = *static_cast<HIR::RangePatternBoundQualPath *> (bound);
+
+ result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);
+
+ // If the path resolves to a const expression, fold it.
+ result = ConstCtx::fold (result);
+ }
+ }
+
+ return result;
+}
+
+void
+CompilePatternCaseLabelExpr::visit (HIR::RangePattern &pattern)
+{
+ tree upper = compile_range_pattern_bound (pattern.get_upper_bound ().get (),
+ pattern.get_pattern_mappings (),
+ pattern.get_locus (), ctx);
+ tree lower = compile_range_pattern_bound (pattern.get_lower_bound ().get (),
+ pattern.get_pattern_mappings (),
+ pattern.get_locus (), ctx);
+
+ case_label_expr = build_case_label (lower, upper, associated_case_label);
+}
+
// setup the bindings
void
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index 1b6e80f..0eb5d61 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -37,13 +37,13 @@ public:
void visit (HIR::StructPattern &pattern) override;
void visit (HIR::TupleStructPattern &pattern) override;
void visit (HIR::WildcardPattern &pattern) override;
+ void visit (HIR::RangePattern &pattern) override;
// Empty visit for unused Pattern HIR nodes.
void visit (HIR::GroupedPattern &) override {}
void visit (HIR::IdentifierPattern &) override {}
void visit (HIR::LiteralPattern &) override;
void visit (HIR::QualifiedPathInExpression &) override {}
- void visit (HIR::RangePattern &) override {}
void visit (HIR::ReferencePattern &) override {}
void visit (HIR::SlicePattern &) override {}
void visit (HIR::TuplePattern &) override {}
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index e4b3e1e..7afe75c 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -950,6 +950,51 @@ ASTLoweringBase::lower_tuple_pattern_ranged (
std::move (upper_patterns)));
}
+std::unique_ptr<HIR::RangePatternBound>
+ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound *bound)
+{
+ std::unique_ptr<HIR::RangePatternBound> hir_bound = nullptr;
+ switch (bound->get_bound_type ())
+ {
+ case AST::RangePatternBound::RangePatternBoundType::LITERAL: {
+ AST::RangePatternBoundLiteral &ref
+ = *static_cast<AST::RangePatternBoundLiteral *> (bound);
+
+ HIR::Literal literal = lower_literal (ref.get_literal ());
+
+ hir_bound = std::unique_ptr<HIR::RangePatternBound> (
+ new HIR::RangePatternBoundLiteral (literal, ref.get_locus (),
+ ref.get_has_minus ()));
+ }
+ break;
+ case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ AST::RangePatternBoundPath &ref
+ = *static_cast<AST::RangePatternBoundPath *> (bound);
+
+ HIR::PathInExpression *path
+ = ASTLowerPathInExpression::translate (&ref.get_path ());
+
+ hir_bound = std::unique_ptr<HIR::RangePatternBound> (
+ new HIR::RangePatternBoundPath (*path));
+ }
+ break;
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ AST::RangePatternBoundQualPath &ref
+ = *static_cast<AST::RangePatternBoundQualPath *> (bound);
+
+ HIR::QualifiedPathInExpression *qualpath
+ = ASTLowerQualPathInExpression::translate (
+ &ref.get_qualified_path ());
+
+ hir_bound = std::unique_ptr<HIR::RangePatternBound> (
+ new HIR::RangePatternBoundQualPath (*qualpath));
+ }
+ break;
+ }
+
+ return hir_bound;
+}
+
HIR::Literal
ASTLoweringBase::lower_literal (const AST::Literal &literal)
{
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 0041a8f..7e3eee1 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -282,6 +282,9 @@ protected:
std::unique_ptr<TuplePatternItems>
lower_tuple_pattern_ranged (AST::TuplePatternItemsRanged &pattern);
+ std::unique_ptr<HIR::RangePatternBound>
+ lower_range_pattern_bound (AST::RangePatternBound *bound);
+
HIR::Literal lower_literal (const AST::Literal &literal);
};
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index 957f8cd..1c08bf1 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -208,5 +208,23 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
= new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ());
}
+void
+ASTLoweringPattern::visit (AST::RangePattern &pattern)
+{
+ auto upper_bound
+ = lower_range_pattern_bound (pattern.get_upper_bound ().get ());
+ auto lower_bound
+ = lower_range_pattern_bound (pattern.get_lower_bound ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::RangePattern (mapping, std::move (lower_bound),
+ std::move (upper_bound), pattern.get_locus ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h
index 32e9dac..dfd3dc0 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.h
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -62,6 +62,8 @@ public:
void visit (AST::LiteralPattern &pattern) override;
+ void visit (AST::RangePattern &pattern) override;
+
private:
ASTLoweringPattern () : translated (nullptr) {}
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 880fc3e..7129b5a 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -197,6 +197,13 @@ protected:
class RangePatternBound
{
public:
+ enum RangePatternBoundType
+ {
+ LITERAL,
+ PATH,
+ QUALPATH
+ };
+
virtual ~RangePatternBound () {}
// Unique pointer custom clone function
@@ -210,6 +217,8 @@ public:
virtual void accept_vis (HIRFullVisitor &vis) = 0;
+ virtual RangePatternBoundType get_bound_type () const = 0;
+
protected:
// pure virtual as RangePatternBound is abstract
virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0;
@@ -238,8 +247,15 @@ public:
Location get_locus () const { return locus; }
+ Literal get_literal () const { return literal; }
+
void accept_vis (HIRFullVisitor &vis) override;
+ RangePatternBoundType get_bound_type () const override
+ {
+ return RangePatternBoundType::LITERAL;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -264,8 +280,16 @@ public:
Location get_locus () const { return path.get_locus (); }
+ PathInExpression &get_path () { return path; }
+ const PathInExpression &get_path () const { return path; }
+
void accept_vis (HIRFullVisitor &vis) override;
+ RangePatternBoundType get_bound_type () const override
+ {
+ return RangePatternBoundType::PATH;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -294,6 +318,14 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
+ QualifiedPathInExpression &get_qualified_path () { return path; }
+ const QualifiedPathInExpression &get_qualified_path () const { return path; }
+
+ RangePatternBoundType get_bound_type () const override
+ {
+ return RangePatternBoundType::QUALPATH;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -368,6 +400,18 @@ public:
return PatternType::RANGE;
}
+ std::unique_ptr<RangePatternBound> &get_lower_bound ()
+ {
+ rust_assert (lower != nullptr);
+ return lower;
+ }
+
+ std::unique_ptr<RangePatternBound> &get_upper_bound ()
+ {
+ rust_assert (upper != nullptr);
+ return upper;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index bac5521..dc2cca4 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -131,5 +131,39 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
}
}
+static void
+resolve_range_pattern_bound (AST::RangePatternBound *bound, NodeId parent)
+{
+ switch (bound->get_bound_type ())
+ {
+ case AST::RangePatternBound::RangePatternBoundType::LITERAL:
+ // Nothing to resolve for a literal.
+ break;
+
+ case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ AST::RangePatternBoundPath &ref
+ = *static_cast<AST::RangePatternBoundPath *> (bound);
+
+ ResolvePath::go (&ref.get_path (), parent);
+ }
+ break;
+
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ AST::RangePatternBoundQualPath &ref
+ = *static_cast<AST::RangePatternBoundQualPath *> (bound);
+
+ ResolvePath::go (&ref.get_qualified_path (), parent);
+ }
+ break;
+ }
+}
+
+void
+PatternDeclaration::visit (AST::RangePattern &pattern)
+{
+ resolve_range_pattern_bound (pattern.get_upper_bound ().get (), parent);
+ resolve_range_pattern_bound (pattern.get_lower_bound ().get (), parent);
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index 464e362..dfb05d3 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -103,6 +103,8 @@ public:
void visit (AST::TuplePattern &pattern) override;
+ void visit (AST::RangePattern &pattern) override;
+
private:
PatternDeclaration (NodeId parent) : ResolverBase (parent) {}
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 52d0d47..bceafde 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -273,5 +273,82 @@ TypeCheckPattern::visit (HIR::LiteralPattern &pattern)
pattern.get_literal (), pattern.get_locus ());
}
+void
+TypeCheckPattern::visit (HIR::RangePattern &pattern)
+{
+ // Resolve the upper and lower bounds, and ensure they are compatible types
+ TyTy::BaseType *upper = nullptr, *lower = nullptr;
+
+ // TODO: It would be nice to factor this out into a helper since the logic for
+ // both bounds is exactly the same...
+ switch (pattern.get_upper_bound ()->get_bound_type ())
+ {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ HIR::RangePatternBoundLiteral &ref
+ = *static_cast<HIR::RangePatternBoundLiteral *> (
+ pattern.get_upper_bound ().get ());
+
+ HIR::Literal lit = ref.get_literal ();
+
+ upper = resolve_literal (pattern.get_pattern_mappings (), lit,
+ pattern.get_locus ());
+ }
+ break;
+
+ case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ HIR::RangePatternBoundPath &ref
+ = *static_cast<HIR::RangePatternBoundPath *> (
+ pattern.get_upper_bound ().get ());
+
+ upper = TypeCheckExpr::Resolve (&ref.get_path (), false);
+ }
+ break;
+
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ HIR::RangePatternBoundQualPath &ref
+ = *static_cast<HIR::RangePatternBoundQualPath *> (
+ pattern.get_upper_bound ().get ());
+
+ upper = TypeCheckExpr::Resolve (&ref.get_qualified_path (), false);
+ }
+ break;
+ }
+
+ switch (pattern.get_lower_bound ()->get_bound_type ())
+ {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ HIR::RangePatternBoundLiteral &ref
+ = *static_cast<HIR::RangePatternBoundLiteral *> (
+ pattern.get_lower_bound ().get ());
+
+ HIR::Literal lit = ref.get_literal ();
+
+ lower = resolve_literal (pattern.get_pattern_mappings (), lit,
+ pattern.get_locus ());
+ }
+ break;
+
+ case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ HIR::RangePatternBoundPath &ref
+ = *static_cast<HIR::RangePatternBoundPath *> (
+ pattern.get_lower_bound ().get ());
+
+ lower = TypeCheckExpr::Resolve (&ref.get_path (), false);
+ }
+ break;
+
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ HIR::RangePatternBoundQualPath &ref
+ = *static_cast<HIR::RangePatternBoundQualPath *> (
+ pattern.get_lower_bound ().get ());
+
+ lower = TypeCheckExpr::Resolve (&ref.get_qualified_path (), false);
+ }
+ break;
+ }
+
+ infered = upper->unify (lower);
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
index b76c7ba..03c4977 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h
@@ -56,11 +56,18 @@ public:
void visit (HIR::LiteralPattern &pattern) override;
+ void visit (HIR::RangePattern &pattern) override;
+
private:
TypeCheckPattern (TyTy::BaseType *parent)
: TypeCheckBase (), parent (parent), infered (nullptr)
{}
+ static TyTy::BaseType *
+ typecheck_range_pattern_bound (HIR::RangePatternBound *bound,
+ Analysis::NodeMapping mappings,
+ Location locus);
+
TyTy::BaseType *parent;
TyTy::BaseType *infered;
};
diff --git a/gcc/testsuite/rust/execute/torture/match_range1.rs b/gcc/testsuite/rust/execute/torture/match_range1.rs
new file mode 100644
index 0000000..8fe8f4c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_range1.rs
@@ -0,0 +1,34 @@
+// { dg-output "zero to END_RANGE\nzero to END_RANGE\nelse\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+const END_RANGE: i32 = 15;
+
+fn foo (x: i32) {
+ match x {
+ 0..=END_RANGE => {
+ let a = "zero to END_RANGE\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf (c);
+ }
+
+ _ => {
+ let a = "else\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf (c);
+ }
+ }
+}
+
+fn main () -> i32 {
+
+ foo (11);
+ foo (15);
+ foo (21);
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_range2.rs b/gcc/testsuite/rust/execute/torture/match_range2.rs
new file mode 100644
index 0000000..82980c2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_range2.rs
@@ -0,0 +1,40 @@
+// { dg-output "lowercase\nuppercase\nother\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+const BIG_A: char = 'A';
+const BIG_Z: char = 'Z';
+
+fn bar (x: char) {
+ match x {
+
+ 'a'..='z' => {
+ let a = "lowercase\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf (c);
+ }
+ BIG_A..=BIG_Z => {
+ let a = "uppercase\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf (c);
+ }
+ _ => {
+ let a = "other\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf (c);
+ }
+ }
+}
+
+fn main () -> i32 {
+ bar ('b');
+ bar ('X');
+ bar ('!');
+
+ 0
+}