aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-03-07 12:27:30 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2022-03-08 11:08:26 +0100
commit08b7516191a62e53819e24d08f2a413c84cf4925 (patch)
tree12d649747e87c8266a84ea3e819876469145e905 /gcc
parent865b6090a8f8981cdfc050ea2ee44abbe92de141 (diff)
downloadgcc-08b7516191a62e53819e24d08f2a413c84cf4925.zip
gcc-08b7516191a62e53819e24d08f2a413c84cf4925.tar.gz
gcc-08b7516191a62e53819e24d08f2a413c84cf4925.tar.bz2
macros: Parse macro patterns properly in repetition
Co-authored-by: philberty <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc68
1 files changed, 47 insertions, 21 deletions
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index f9f2005..61ab626 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.cc
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc
@@ -39,9 +39,6 @@ SubstituteCtx::substitute_repetition (
{
rust_assert (pattern_end < macro.size ());
- rust_debug ("pattern start: %lu", pattern_start);
- rust_debug ("pattern end: %lu", pattern_end);
-
std::vector<std::unique_ptr<AST::Token>> expanded;
// Find the first fragment and get the amount of repetitions that we should
@@ -154,19 +151,57 @@ SubstituteCtx::substitute_token (size_t token_idx)
// We need to parse up until the closing delimiter and expand this
// fragment->n times.
rust_debug ("expanding repetition");
- std::vector<std::unique_ptr<AST::Token>> repetition_pattern;
+
+ // We're in a context where macro repetitions have already been
+ // parsed and validated: This means that
+ // 1/ There will be no delimiters as that is an error
+ // 2/ There are no fragment specifiers anymore, which prevents us
+ // from reusing parser functions.
+ //
+ // Repetition patterns are also special in that they cannot contain
+ // "rogue" delimiters: For example, this is invalid, as they are
+ // parsed as MacroMatches and must contain a correct amount of
+ // delimiters.
+ // `$($e:expr ) )`
+ // ^ rogue closing parenthesis
+ //
+ // With all of that in mind, we can simply skip ahead from one
+ // parenthesis to the other to find the pattern to expand. Of course,
+ // pairs of delimiters, including parentheses, are allowed.
+ // `$($e:expr ( ) )`
+ // Parentheses are the sole delimiter for which we need a special
+ // behavior since they delimit the repetition pattern
+
size_t pattern_start = token_idx + 1;
size_t pattern_end = pattern_start;
- for (; pattern_end < macro.size ()
- && macro.at (pattern_end)->get_id () != RIGHT_PAREN;
- pattern_end++)
- ;
+ auto parentheses_stack = 0;
+ for (size_t idx = pattern_start; idx < macro.size (); idx++)
+ {
+ if (macro.at (idx)->get_id () == LEFT_PAREN)
+ {
+ parentheses_stack++;
+ }
+ else if (macro.at (idx)->get_id () == RIGHT_PAREN)
+ {
+ if (parentheses_stack == 0)
+ {
+ pattern_end = idx;
+ break;
+ }
+ parentheses_stack--;
+ }
+ }
+
+ // Unreachable case, but let's make sure we don't ever run into it
+ rust_assert (pattern_end != pattern_start);
std::unique_ptr<AST::Token> separator_token = nullptr;
- // FIXME: Can this go out of bounds?
- auto &post_pattern_token = macro.at (pattern_end + 1);
- if (!is_rep_op (post_pattern_token))
- separator_token = post_pattern_token->clone_token ();
+ if (pattern_end + 1 <= macro.size ())
+ {
+ auto &post_pattern_token = macro.at (pattern_end + 1);
+ if (!is_rep_op (post_pattern_token))
+ separator_token = post_pattern_token->clone_token ();
+ }
// Amount of tokens to skip
auto to_skip = 0;
@@ -178,15 +213,6 @@ SubstituteCtx::substitute_token (size_t token_idx)
if (separator_token)
to_skip += 1;
- // FIXME: This skips whitespaces... Is that okay??
- // FIXME: Is there any existing parsing function that allows us to
- // parse a macro pattern?
-
- // FIXME: Add error handling in the case we haven't found a matching
- // closing delimiter
-
- // FIXME: We need to parse the repetition token now
-
return {substitute_repetition (pattern_start, pattern_end,
std::move (separator_token)),
pattern_end - pattern_start + to_skip};