From 6dd7ab9045ee0ac22ac46dff39bd8dfb69aa2432 Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Mon, 15 Jan 2024 13:48:41 +0530 Subject: [PATCH] Emit error when range pattern is empty Fixes #2794 gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Check values of lower and upper bounds and emit E0030 if needed. * checks/errors/rust-ast-validation.h: Add function declaration for validation of `AST::RangePattern`. * parse/rust-parse-impl.h (Parser::parse_literal_or_range_pattern): Added missed parameter. gcc/testsuite/ChangeLog: * rust/compile/issue-2794.rs: New test. Signed-off-by: Kushal Pal --- gcc/rust/checks/errors/rust-ast-validation.cc | 38 +++++++++++++++++++ gcc/rust/checks/errors/rust-ast-validation.h | 1 + gcc/rust/parse/rust-parse-impl.h | 2 +- gcc/testsuite/rust/compile/issue-2794.rs | 15 ++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/issue-2794.rs diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index b50e9cdf8581..8abbcc11f57f 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -21,6 +21,8 @@ #include "rust-diagnostics.h" #include "rust-item.h" #include "rust-keyword-values.h" +#include "rust-pattern.h" +#include "safe-ctype.h" namespace Rust { @@ -180,4 +182,40 @@ ASTValidation::visit (AST::Module &module) AST::ContextualASTVisitor::visit (module); } +void +ASTValidation::visit (AST::RangePattern &pattern) +{ + if (pattern.get_has_lower_bound () && pattern.get_has_upper_bound ()) + { + auto &lower = pattern.get_lower_bound (); + auto &upper = pattern.get_upper_bound (); + + if (lower->get_bound_type () == AST::RangePatternBound::LITERAL + && upper->get_bound_type () == AST::RangePatternBound::LITERAL) + { + int lower_value{}; + int upper_value{}; + // if numeric range, get lower and upper numeric values + if (ISDIGIT (lower->as_string ()[0])) + { + lower_value = std::stoi (lower->as_string ()); + upper_value = std::stoi (upper->as_string ()); + } + // else if character range, get lower and upper ASCII values + else + { + lower_value = lower->as_string ()[0]; + upper_value = upper->as_string ()[0]; + } + // raise error if range is empty + if (lower_value > upper_value) + { + rust_error_at ( + pattern.get_locus (), ErrorCode::E0030, + "lower range bound must be less than or equal to upper"); + } + } + } +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 963357f86cd8..9c65301aec4e 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -43,6 +43,7 @@ class ASTValidation : public AST::ContextualASTVisitor virtual void visit (AST::Function &function); virtual void visit (AST::Trait &trait); virtual void visit (AST::TraitFunctionDecl &decl); + virtual void visit (AST::RangePattern &pattern); }; } // namespace Rust diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 872c1fae2a3b..efdb81a3142e 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -10435,7 +10435,7 @@ Parser::parse_literal_or_range_pattern () return std::unique_ptr ( new AST::RangePattern (std::move (lower), std::move (upper), - range_lower->get_locus ())); + range_lower->get_locus (), next->get_id () == ELLIPSIS)); } else { diff --git a/gcc/testsuite/rust/compile/issue-2794.rs b/gcc/testsuite/rust/compile/issue-2794.rs new file mode 100644 index 000000000000..3194a346a3ad --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2794.rs @@ -0,0 +1,15 @@ +fn main() { + let mut x = 11; + match x { + 2..=1 => x = 6, + // { dg-error "lower range bound must be less than or equal to upper" "" { target *-*-* } .-1 } + _ => x = 7, + } + + let mut y = 'a'; + match y { + 'z'..='y' => y = 'b', + // { dg-error "lower range bound must be less than or equal to upper" "" { target *-*-* } .-1 } + _ => y = 'c', + } +}