Skip to content

Commit 1f546e5

Browse files
match_repetition: Set the correct amount of matches for each fragment
Co-authored-by: philberty <philip.herron@embecosm.com>
1 parent 6db51e3 commit 1f546e5

File tree

3 files changed

+59
-74
lines changed

3 files changed

+59
-74
lines changed

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

Lines changed: 28 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3611,7 +3611,6 @@ MacroExpander::match_n_matches (
36113611
match_amount = 0;
36123612

36133613
const MacroInvocLexer &source = parser.get_token_source ();
3614-
std::vector<std::string> fragment_identifiers;
36153614
while (true)
36163615
{
36173616
// If the current token is a closing macro delimiter, break away.
@@ -3637,8 +3636,6 @@ MacroExpander::match_n_matches (
36373636
{fragment->get_ident (),
36383637
MatchedFragment (fragment->get_ident (), offs_begin,
36393638
offs_end)});
3640-
3641-
fragment_identifiers.emplace_back (fragment->get_ident ());
36423639
}
36433640
break;
36443641

@@ -3677,21 +3674,10 @@ MacroExpander::match_n_matches (
36773674

36783675
// Check if the amount of matches we got is valid: Is it more than the lower
36793676
// bound and less than the higher bound?
3680-
auto result = hi_bound ? match_amount >= lo_bound && match_amount <= hi_bound
3681-
: match_amount >= lo_bound;
3682-
3683-
// We can now set the amount to each fragment we matched in the substack
3684-
auto &stack_map = sub_stack.peek ();
3685-
for (auto &fragment_id : fragment_identifiers)
3686-
{
3687-
auto it = stack_map.find (fragment_id);
3688-
3689-
rust_assert (it != stack_map.end ());
3677+
bool did_meet_lo_bound = match_amount >= lo_bound;
3678+
bool did_meet_hi_bound = hi_bound ? match_amount <= hi_bound : true;
36903679

3691-
it->second.set_match_amount (match_amount);
3692-
}
3693-
3694-
return result;
3680+
return did_meet_lo_bound && did_meet_hi_bound;
36953681
}
36963682

36973683
bool
@@ -3733,6 +3719,31 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
37333719
rust_debug_loc (rep.get_match_locus (), "%s matched %lu times",
37343720
res ? "successfully" : "unsuccessfully", match_amount);
37353721

3722+
// We can now set the amount to each fragment we matched in the substack
3723+
auto &stack_map = sub_stack.peek ();
3724+
for (auto &match : rep.get_matches ())
3725+
{
3726+
if (match->get_macro_match_type ()
3727+
== AST::MacroMatch::MacroMatchType::Fragment)
3728+
{
3729+
auto fragment = static_cast<AST::MacroMatchFragment *> (match.get ());
3730+
auto it = stack_map.find (fragment->get_ident ());
3731+
3732+
// If we can't find the fragment, but the result was valid, then it's
3733+
// a zero-matched fragment and we can insert it
3734+
if (it == stack_map.end ())
3735+
{
3736+
stack_map.insert (
3737+
{fragment->get_ident (),
3738+
MatchedFragment::zero (fragment->get_ident ())});
3739+
}
3740+
else
3741+
{
3742+
it->second.set_match_amount (match_amount);
3743+
}
3744+
}
3745+
}
3746+
37363747
return res;
37373748
}
37383749

@@ -4037,14 +4048,6 @@ MacroExpander::substitute_tokens (
40374048
{
40384049
std::vector<std::unique_ptr<AST::Token>> replaced_tokens;
40394050

4040-
// for token in macro
4041-
// if token == ?:
4042-
// // That's not always true: If it's a left paren, it's repetition
4043-
// // We probably want to store the matched amount in the fragment so
4044-
// // we can expand it here
4045-
// id = next_token();
4046-
// frag = fragment.find(id);
4047-
40484051
for (size_t i = 0; i < macro.size (); i++)
40494052
{
40504053
auto &tok = macro.at (i);
@@ -4065,54 +4068,6 @@ MacroExpander::substitute_tokens (
40654068
{
40664069
replaced_tokens.emplace_back (tok->clone_token ());
40674070
}
4068-
4069-
// std::vector<std::unique_ptr<AST::Token>> parsed_toks;
4070-
4071-
// std::string ident;
4072-
// for (size_t offs = i; i < macro.size (); offs++)
4073-
// {
4074-
// auto &tok = macro.at (offs);
4075-
// if (tok->get_id () == DOLLAR_SIGN && offs == i)
4076-
// {
4077-
// parsed_toks.push_back (tok->clone_token ());
4078-
// }
4079-
// else if (tok->get_id () == IDENTIFIER)
4080-
// {
4081-
// rust_assert (tok->as_string ().size () == 1);
4082-
// ident.push_back (tok->as_string ().at (0));
4083-
// parsed_toks.push_back (tok->clone_token ());
4084-
// }
4085-
// else
4086-
// {
4087-
// break;
4088-
// }
4089-
// }
4090-
4091-
// // lookup the ident
4092-
// auto it = fragments.find (ident);
4093-
// if (it == fragments.end ())
4094-
// {
4095-
// // just leave the tokens in
4096-
// for (auto &tok : parsed_toks)
4097-
// {
4098-
// replaced_tokens.push_back (tok->clone_token ());
4099-
// }
4100-
// }
4101-
// else
4102-
// {
4103-
// // replace
4104-
// MatchedFragment &frag = it->second;
4105-
// for (size_t offs = frag.token_offset_begin;
4106-
// offs < frag.token_offset_end; offs++)
4107-
// {
4108-
// auto &tok = input.at (offs);
4109-
// replaced_tokens.push_back (tok->clone_token ());
4110-
// }
4111-
// }
4112-
// i += parsed_toks.size () - 1;
4113-
//
4114-
// }
4115-
// else { replaced_tokens.push_back (tok->clone_token ()); }
41164071
}
41174072

41184073
return replaced_tokens;

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,21 @@ struct MatchedFragment
5757
size_t match_amount;
5858

5959
MatchedFragment (std::string identifier, size_t token_offset_begin,
60-
size_t token_offset_end, size_t match_amount = 0)
60+
size_t token_offset_end, size_t match_amount = 1)
6161
: fragment_ident (identifier), token_offset_begin (token_offset_begin),
6262
token_offset_end (token_offset_end), match_amount (match_amount)
6363
{}
6464

65+
/**
66+
* Create a valid fragment matched zero times. This is useful for repetitions
67+
* which allow the absence of a fragment, such as * and ?
68+
*/
69+
static MatchedFragment zero (std::string identifier)
70+
{
71+
// We don't need offsets since there is "no match"
72+
return MatchedFragment (identifier, 0, 0, 0);
73+
}
74+
6575
std::string as_string () const
6676
{
6777
return fragment_ident + "=" + std::to_string (token_offset_begin) + ":"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// { dg-output "15\n" }
2+
extern "C" {
3+
fn printf(s: *const i8, ...);
4+
}
5+
6+
fn print_int(value: i32) {
7+
let s = "%d\n\0" as *const str as *const i8;
8+
printf(s, value);
9+
}
10+
11+
macro_rules! add_exprs {
12+
($($e:expr)*) => (15 $(+ $e)*)
13+
}
14+
15+
fn main() -> i32 {
16+
// 15
17+
print_int(add_exprs!());
18+
19+
0
20+
}

0 commit comments

Comments
 (0)