diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-02-22 09:32:52 +0100 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-02-23 10:13:06 +0100 |
commit | 1f546e5e3addda01c5c449833642be8fcdf5dcdc (patch) | |
tree | e0ec05beebb6bcd83042d385920d79f38420d4aa /gcc | |
parent | 6db51e39363a4500dd8d3e04d87f682f9ef11f26 (diff) | |
download | gcc-1f546e5e3addda01c5c449833642be8fcdf5dcdc.zip gcc-1f546e5e3addda01c5c449833642be8fcdf5dcdc.tar.gz gcc-1f546e5e3addda01c5c449833642be8fcdf5dcdc.tar.bz2 |
match_repetition: Set the correct amount of matches for each fragment
Co-authored-by: philberty <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 101 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 12 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/macros14.rs | 20 |
3 files changed, 59 insertions, 74 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 668b89f..45d2b74 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -3611,7 +3611,6 @@ MacroExpander::match_n_matches ( match_amount = 0; const MacroInvocLexer &source = parser.get_token_source (); - std::vector<std::string> fragment_identifiers; while (true) { // If the current token is a closing macro delimiter, break away. @@ -3637,8 +3636,6 @@ MacroExpander::match_n_matches ( {fragment->get_ident (), MatchedFragment (fragment->get_ident (), offs_begin, offs_end)}); - - fragment_identifiers.emplace_back (fragment->get_ident ()); } break; @@ -3677,21 +3674,10 @@ MacroExpander::match_n_matches ( // Check if the amount of matches we got is valid: Is it more than the lower // bound and less than the higher bound? - auto result = hi_bound ? match_amount >= lo_bound && match_amount <= hi_bound - : match_amount >= lo_bound; - - // We can now set the amount to each fragment we matched in the substack - auto &stack_map = sub_stack.peek (); - for (auto &fragment_id : fragment_identifiers) - { - auto it = stack_map.find (fragment_id); - - rust_assert (it != stack_map.end ()); + bool did_meet_lo_bound = match_amount >= lo_bound; + bool did_meet_hi_bound = hi_bound ? match_amount <= hi_bound : true; - it->second.set_match_amount (match_amount); - } - - return result; + return did_meet_lo_bound && did_meet_hi_bound; } bool @@ -3733,6 +3719,31 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser, rust_debug_loc (rep.get_match_locus (), "%s matched %lu times", res ? "successfully" : "unsuccessfully", match_amount); + // We can now set the amount to each fragment we matched in the substack + auto &stack_map = sub_stack.peek (); + for (auto &match : rep.get_matches ()) + { + if (match->get_macro_match_type () + == AST::MacroMatch::MacroMatchType::Fragment) + { + auto fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); + auto it = stack_map.find (fragment->get_ident ()); + + // If we can't find the fragment, but the result was valid, then it's + // a zero-matched fragment and we can insert it + if (it == stack_map.end ()) + { + stack_map.insert ( + {fragment->get_ident (), + MatchedFragment::zero (fragment->get_ident ())}); + } + else + { + it->second.set_match_amount (match_amount); + } + } + } + return res; } @@ -4037,14 +4048,6 @@ MacroExpander::substitute_tokens ( { std::vector<std::unique_ptr<AST::Token>> replaced_tokens; - // for token in macro - // if token == ?: - // // That's not always true: If it's a left paren, it's repetition - // // We probably want to store the matched amount in the fragment so - // // we can expand it here - // id = next_token(); - // frag = fragment.find(id); - for (size_t i = 0; i < macro.size (); i++) { auto &tok = macro.at (i); @@ -4065,54 +4068,6 @@ MacroExpander::substitute_tokens ( { replaced_tokens.emplace_back (tok->clone_token ()); } - - // std::vector<std::unique_ptr<AST::Token>> parsed_toks; - - // std::string ident; - // for (size_t offs = i; i < macro.size (); offs++) - // { - // auto &tok = macro.at (offs); - // if (tok->get_id () == DOLLAR_SIGN && offs == i) - // { - // parsed_toks.push_back (tok->clone_token ()); - // } - // else if (tok->get_id () == IDENTIFIER) - // { - // rust_assert (tok->as_string ().size () == 1); - // ident.push_back (tok->as_string ().at (0)); - // parsed_toks.push_back (tok->clone_token ()); - // } - // else - // { - // break; - // } - // } - - // // lookup the ident - // auto it = fragments.find (ident); - // if (it == fragments.end ()) - // { - // // just leave the tokens in - // for (auto &tok : parsed_toks) - // { - // replaced_tokens.push_back (tok->clone_token ()); - // } - // } - // else - // { - // // replace - // MatchedFragment &frag = it->second; - // for (size_t offs = frag.token_offset_begin; - // offs < frag.token_offset_end; offs++) - // { - // auto &tok = input.at (offs); - // replaced_tokens.push_back (tok->clone_token ()); - // } - // } - // i += parsed_toks.size () - 1; - // - // } - // else { replaced_tokens.push_back (tok->clone_token ()); } } return replaced_tokens; diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 51e5ad1..f3cb36d 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -57,11 +57,21 @@ struct MatchedFragment size_t match_amount; MatchedFragment (std::string identifier, size_t token_offset_begin, - size_t token_offset_end, size_t match_amount = 0) + size_t token_offset_end, size_t match_amount = 1) : fragment_ident (identifier), token_offset_begin (token_offset_begin), token_offset_end (token_offset_end), match_amount (match_amount) {} + /** + * Create a valid fragment matched zero times. This is useful for repetitions + * which allow the absence of a fragment, such as * and ? + */ + static MatchedFragment zero (std::string identifier) + { + // We don't need offsets since there is "no match" + return MatchedFragment (identifier, 0, 0, 0); + } + std::string as_string () const { return fragment_ident + "=" + std::to_string (token_offset_begin) + ":" diff --git a/gcc/testsuite/rust/execute/torture/macros14.rs b/gcc/testsuite/rust/execute/torture/macros14.rs new file mode 100644 index 0000000..2dc95e3 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/macros14.rs @@ -0,0 +1,20 @@ +// { dg-output "15\n" } +extern "C" { + fn printf(s: *const i8, ...); +} + +fn print_int(value: i32) { + let s = "%d\n\0" as *const str as *const i8; + printf(s, value); +} + +macro_rules! add_exprs { + ($($e:expr)*) => (15 $(+ $e)*) +} + +fn main() -> i32 { + // 15 + print_int(add_exprs!()); + + 0 +} |