diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 392a9fe42f1..a6933bb6aab 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -30,18 +30,14 @@ SubstituteCtx::substitute_metavar (std::unique_ptr &metavar) return expanded; } -std::vector> -SubstituteCtx::substitute_repetition ( - size_t pattern_start, size_t pattern_end, - std::unique_ptr separator_token) +bool +SubstituteCtx::check_repetition_amount (size_t pattern_start, + size_t pattern_end, + size_t &expected_repetition_amount) { - rust_assert (pattern_end < macro.size ()); + bool first_fragment_found = false; + bool is_valid = true; - std::vector> expanded; - - // Find the first fragment and get the amount of repetitions that we should - // perform - size_t repeat_amount = 0; for (size_t i = pattern_start; i < pattern_end; i++) { if (macro.at (i)->get_id () == DOLLAR_SIGN) @@ -59,17 +55,48 @@ SubstituteCtx::substitute_repetition ( rust_error_at (frag_token->get_locus (), "metavar %s used in repetition does not exist", frag_token->get_str ().c_str ()); - // FIXME: - return expanded; + + is_valid = false; } - // FIXME: Refactor, ugly - repeat_amount = it->second.get_match_amount (); + size_t repeat_amount = it->second.get_match_amount (); + if (!first_fragment_found) + { + first_fragment_found = true; + expected_repetition_amount = repeat_amount; + } + else + { + if (repeat_amount != expected_repetition_amount) + { + rust_error_at ( + frag_token->get_locus (), + "different amount of matches used in merged " + "repetitions: expected %ld, got %ld", + expected_repetition_amount, repeat_amount); + is_valid = false; + } + } } } } + return is_valid; +} + +std::vector> +SubstituteCtx::substitute_repetition ( + size_t pattern_start, size_t pattern_end, + std::unique_ptr separator_token) +{ + rust_assert (pattern_end < macro.size ()); + + size_t repeat_amount = 0; + if (!check_repetition_amount (pattern_start, pattern_end, repeat_amount)) + return {}; + rust_debug ("repetition amount to use: %lu", repeat_amount); + std::vector> expanded; std::vector> new_macro; // We want to generate a "new macro" to substitute with. This new macro diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h index e89f9d788a1..81dcab7643b 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.h +++ b/gcc/rust/expand/rust-macro-substitute-ctx.h @@ -26,6 +26,17 @@ class SubstituteCtx std::vector> ¯o; std::map &fragments; + /** + * Find the repetition amount to use when expanding a repetition, and + * check that all fragments used respect that repetition amount + * + * @param pattern_start Start of the repetition pattern + * @param pattern_end End of the repetition pattern + * @param repeat_amount Reference to fill with the matched repetition amount + */ + bool check_repetition_amount (size_t pattern_start, size_t pattern_end, + size_t &repeat_amount); + public: SubstituteCtx (std::vector> &input, std::vector> ¯o, diff --git a/gcc/testsuite/rust/compile/macro26.rs b/gcc/testsuite/rust/compile/macro26.rs new file mode 100644 index 00000000000..f6588e75eb0 --- /dev/null +++ b/gcc/testsuite/rust/compile/macro26.rs @@ -0,0 +1,10 @@ +macro_rules! repeat { + ( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* )) + // { dg-error "different amount of matches used in merged repetitions" "" { target *-*-* } .-1 } +} + +fn main() -> i32 { + let _ = repeat!(1, 2, 3; 2, 3); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/macros24.rs b/gcc/testsuite/rust/execute/torture/macros24.rs new file mode 100644 index 00000000000..f838a83af66 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/macros24.rs @@ -0,0 +1,9 @@ +macro_rules! repeat { + ( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* )) +} + +fn main() -> i32 { + let t = repeat!(1, 1; 2, 2); + + t.0 .0 + t.0 .1 + t.1 .0 + t.1 .1 - 6 +}