Skip to content

Commit cc6e405

Browse files
Merge #1041
1041: macros: Only expand merged repetitions if they contain the same amount r=CohenArthur a=CohenArthur Depends on #1040 Fixes #948 Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
2 parents 6ecd43c + f8c550f commit cc6e405

File tree

4 files changed

+71
-14
lines changed

4 files changed

+71
-14
lines changed

gcc/rust/expand/rust-macro-substitute-ctx.cc

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,14 @@ SubstituteCtx::substitute_metavar (std::unique_ptr<AST::Token> &metavar)
3030
return expanded;
3131
}
3232

33-
std::vector<std::unique_ptr<AST::Token>>
34-
SubstituteCtx::substitute_repetition (
35-
size_t pattern_start, size_t pattern_end,
36-
std::unique_ptr<AST::Token> separator_token)
33+
bool
34+
SubstituteCtx::check_repetition_amount (size_t pattern_start,
35+
size_t pattern_end,
36+
size_t &expected_repetition_amount)
3737
{
38-
rust_assert (pattern_end < macro.size ());
39-
40-
std::vector<std::unique_ptr<AST::Token>> expanded;
38+
bool first_fragment_found = false;
39+
bool is_valid = true;
4140

42-
// Find the first fragment and get the amount of repetitions that we should
43-
// perform
44-
size_t repeat_amount = 0;
4541
for (size_t i = pattern_start; i < pattern_end; i++)
4642
{
4743
if (macro.at (i)->get_id () == DOLLAR_SIGN)
@@ -59,17 +55,48 @@ SubstituteCtx::substitute_repetition (
5955
rust_error_at (frag_token->get_locus (),
6056
"metavar %s used in repetition does not exist",
6157
frag_token->get_str ().c_str ());
62-
// FIXME:
63-
return expanded;
58+
59+
is_valid = false;
6460
}
6561

66-
// FIXME: Refactor, ugly
67-
repeat_amount = it->second.get_match_amount ();
62+
size_t repeat_amount = it->second.get_match_amount ();
63+
if (!first_fragment_found)
64+
{
65+
first_fragment_found = true;
66+
expected_repetition_amount = repeat_amount;
67+
}
68+
else
69+
{
70+
if (repeat_amount != expected_repetition_amount)
71+
{
72+
rust_error_at (
73+
frag_token->get_locus (),
74+
"different amount of matches used in merged "
75+
"repetitions: expected %ld, got %ld",
76+
expected_repetition_amount, repeat_amount);
77+
is_valid = false;
78+
}
79+
}
6880
}
6981
}
7082
}
7183

84+
return is_valid;
85+
}
86+
87+
std::vector<std::unique_ptr<AST::Token>>
88+
SubstituteCtx::substitute_repetition (
89+
size_t pattern_start, size_t pattern_end,
90+
std::unique_ptr<AST::Token> separator_token)
91+
{
92+
rust_assert (pattern_end < macro.size ());
93+
94+
size_t repeat_amount = 0;
95+
if (!check_repetition_amount (pattern_start, pattern_end, repeat_amount))
96+
return {};
97+
7298
rust_debug ("repetition amount to use: %lu", repeat_amount);
99+
std::vector<std::unique_ptr<AST::Token>> expanded;
73100
std::vector<std::unique_ptr<AST::Token>> new_macro;
74101

75102
// We want to generate a "new macro" to substitute with. This new macro

gcc/rust/expand/rust-macro-substitute-ctx.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ class SubstituteCtx
2626
std::vector<std::unique_ptr<AST::Token>> &macro;
2727
std::map<std::string, MatchedFragmentContainer> &fragments;
2828

29+
/**
30+
* Find the repetition amount to use when expanding a repetition, and
31+
* check that all fragments used respect that repetition amount
32+
*
33+
* @param pattern_start Start of the repetition pattern
34+
* @param pattern_end End of the repetition pattern
35+
* @param repeat_amount Reference to fill with the matched repetition amount
36+
*/
37+
bool check_repetition_amount (size_t pattern_start, size_t pattern_end,
38+
size_t &repeat_amount);
39+
2940
public:
3041
SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input,
3142
std::vector<std::unique_ptr<AST::Token>> &macro,

gcc/testsuite/rust/compile/macro26.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
macro_rules! repeat {
2+
( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
3+
// { dg-error "different amount of matches used in merged repetitions" "" { target *-*-* } .-1 }
4+
}
5+
6+
fn main() -> i32 {
7+
let _ = repeat!(1, 2, 3; 2, 3);
8+
9+
0
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
macro_rules! repeat {
2+
( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
3+
}
4+
5+
fn main() -> i32 {
6+
let t = repeat!(1, 1; 2, 2);
7+
8+
t.0 .0 + t.0 .1 + t.1 .0 + t.1 .1 - 6
9+
}

0 commit comments

Comments
 (0)