From: Owen Avery Date: Sat, 3 Jun 2023 21:40:18 +0000 (-0400) Subject: gccrs: Improve macro repetition handling X-Git-Tag: basepoints/gcc-15~2424 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b8f4ad50394e137113bde1c91f6160034882ca94;p=thirdparty%2Fgcc.git gccrs: Improve macro repetition handling gcc/rust/ChangeLog: * expand/rust-macro-expand.cc (MacroExpander::match_matcher): Remove append_fragment inside repetitions. (MacroExpander::match_n_matches): Use sub_stack push/pop to handle repetitions. (MatchedFragmentContainer::add_fragment): Add MatchedFragmentContainer accepting version. * expand/rust-macro-expand.h (MatchedFragmentContainer::add_fragment): Likewise. (MatchedFragmentContainerRepetition::add_fragment): Likewise. (SubstititionScope::append_fragment): Likewise. gcc/testsuite/ChangeLog: * rust/compile/macro56.rs: New test. Signed-off-by: Owen Avery --- diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 0ed349abb03a..a4ad16a915c9 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -501,14 +501,9 @@ MacroExpander::match_matcher (Parser &parser, // matched fragment get the offset in the token stream size_t offs_end = source.get_offs (); - if (in_repetition) - sub_stack.append_fragment ( - MatchedFragment (fragment->get_ident ().as_string (), - offs_begin, offs_end)); - else - sub_stack.insert_metavar ( - MatchedFragment (fragment->get_ident ().as_string (), - offs_begin, offs_end)); + sub_stack.insert_metavar ( + MatchedFragment (fragment->get_ident ().as_string (), offs_begin, + offs_end)); } break; @@ -598,6 +593,7 @@ MacroExpander::match_n_matches (Parser &parser, if (!match_token (parser, *rep.get_sep ())) break; + sub_stack.push (); bool valid_current_match = false; for (auto &match : matches) { @@ -612,13 +608,7 @@ MacroExpander::match_n_matches (Parser &parser, // matched fragment get the offset in the token stream size_t offs_end = source.get_offs (); - // The main difference with match_matcher happens here: Instead - // of inserting a new fragment, we append to one. If that - // fragment does not exist, then the operation is similar to - // `insert_fragment` with the difference that we are not - // creating a metavariable, but a repetition of one, which is - // really different. - sub_stack.append_fragment ( + sub_stack.insert_metavar ( MatchedFragment (fragment->get_ident ().as_string (), offs_begin, offs_end)); } @@ -645,6 +635,12 @@ MacroExpander::match_n_matches (Parser &parser, break; } } + auto old_stack = sub_stack.pop (); + + // nest metavars into repetitions + for (auto &ent : old_stack) + sub_stack.append_fragment (ent.first, std::move (ent.second)); + // If we've encountered an error once, stop trying to match more // repetitions if (!valid_current_match) @@ -1201,6 +1197,16 @@ MatchedFragmentContainer::add_fragment (MatchedFragment fragment) .add_fragment (fragment); } +void +MatchedFragmentContainer::add_fragment ( + std::unique_ptr fragment) +{ + rust_assert (!is_single_fragment ()); + + return static_cast (*this) + .add_fragment (std::move (fragment)); +} + std::unique_ptr MatchedFragmentContainer::zero () { diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 839c543c9541..14afac042028 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -111,6 +111,11 @@ public: */ void add_fragment (MatchedFragment fragment); + /** + * Add a matched fragment to the container + */ + void add_fragment (std::unique_ptr fragment); + // const std::string &get_fragment_name () const { return fragment_name; } bool is_single_fragment () const { return get_kind () == Kind::MetaVar; } @@ -155,7 +160,15 @@ public: */ void add_fragment (MatchedFragment fragment) { - fragments.emplace_back (metavar (fragment)); + add_fragment (metavar (fragment)); + } + + /** + * Add a matched fragment to the container + */ + void add_fragment (std::unique_ptr fragment) + { + fragments.emplace_back (std::move (fragment)); } virtual Kind get_kind () const { return Kind::Repetition; } @@ -227,6 +240,25 @@ public: it->second->add_fragment (fragment); } + /** + * Append a new matched fragment to a repetition into the current substitution + * map + */ + void append_fragment (std::string ident, + std::unique_ptr fragment) + { + auto ¤t_map = stack.back (); + auto it = current_map.find (ident); + + if (it == current_map.end ()) + it = current_map + .emplace (ident, std::unique_ptr ( + new MatchedFragmentContainerRepetition ())) + .first; + + it->second->add_fragment (std::move (fragment)); + } + void insert_matches (std::string key, std::unique_ptr matches) { diff --git a/gcc/testsuite/rust/compile/macro56.rs b/gcc/testsuite/rust/compile/macro56.rs new file mode 100644 index 000000000000..bf42a64cd8e2 --- /dev/null +++ b/gcc/testsuite/rust/compile/macro56.rs @@ -0,0 +1,9 @@ +macro_rules! check { + (a, b, c ; x, y, z; e, r; a) => {} +} + +macro_rules! foo { + ($($($i:ident),*);*) => {check!($($($i),*);*);} +} + +foo!(a, b, c ; x, y, z; e, r; a);