aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc55
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.h11
-rw-r--r--gcc/testsuite/rust/compile/macro26.rs10
-rw-r--r--gcc/testsuite/rust/execute/torture/macros24.rs9
4 files changed, 71 insertions, 14 deletions
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index 392a9fe..a6933bb 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<AST::Token> &metavar)
return expanded;
}
-std::vector<std::unique_ptr<AST::Token>>
-SubstituteCtx::substitute_repetition (
- size_t pattern_start, size_t pattern_end,
- std::unique_ptr<AST::Token> 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 ());
-
- std::vector<std::unique_ptr<AST::Token>> expanded;
+ bool first_fragment_found = false;
+ bool is_valid = true;
- // 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<std::unique_ptr<AST::Token>>
+SubstituteCtx::substitute_repetition (
+ size_t pattern_start, size_t pattern_end,
+ std::unique_ptr<AST::Token> 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<std::unique_ptr<AST::Token>> expanded;
std::vector<std::unique_ptr<AST::Token>> 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 e89f9d7..81dcab7 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<std::unique_ptr<AST::Token>> &macro;
std::map<std::string, MatchedFragmentContainer> &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<std::unique_ptr<AST::Token>> &input,
std::vector<std::unique_ptr<AST::Token>> &macro,
diff --git a/gcc/testsuite/rust/compile/macro26.rs b/gcc/testsuite/rust/compile/macro26.rs
new file mode 100644
index 0000000..f6588e7
--- /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 0000000..f838a83
--- /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
+}