aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-02-22 09:32:52 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2022-02-23 10:13:06 +0100
commit1f546e5e3addda01c5c449833642be8fcdf5dcdc (patch)
treee0ec05beebb6bcd83042d385920d79f38420d4aa /gcc
parent6db51e39363a4500dd8d3e04d87f682f9ef11f26 (diff)
downloadgcc-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.cc101
-rw-r--r--gcc/rust/expand/rust-macro-expand.h12
-rw-r--r--gcc/testsuite/rust/execute/torture/macros14.rs20
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
+}