diff options
author | Owen Avery <powerboat9.gamer@gmail.com> | 2023-05-28 13:33:52 -0400 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-01-16 18:37:22 +0100 |
commit | 57c5d234792b6bc00f3ef29148733617db8c86d2 (patch) | |
tree | 54e18358d7ab846809708fde57e717a3dc0282fa /gcc/rust | |
parent | 253c7343bbb7dcae208ed9342e76b8a5715ad829 (diff) | |
download | gcc-57c5d234792b6bc00f3ef29148733617db8c86d2.zip gcc-57c5d234792b6bc00f3ef29148733617db8c86d2.tar.gz gcc-57c5d234792b6bc00f3ef29148733617db8c86d2.tar.bz2 |
gccrs: Avoid invalid metavariable substitutions
gcc/rust/ChangeLog:
* expand/rust-macro-substitute-ctx.cc
(SubstituteCtx::substitute_metavar): Allow substitution failure.
(SubstituteCtx::substitute_token):
Handle substitution failure, include dollar sign in count of tokens to substitute.
(SubstituteCtx::substitute_tokens):
Include dollar sign in count of tokens to substitute.
* expand/rust-macro-substitute-ctx.h
(SubstituteCtx::substitute_metavar):
Adjust signature and document new substitution failure handling.
gcc/testsuite/ChangeLog:
* rust/compile/issue-2225.rs: New test.
Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/expand/rust-macro-substitute-ctx.cc | 49 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-substitute-ctx.h | 9 |
2 files changed, 32 insertions, 26 deletions
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 85c9d7e..84df2c2 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -2,17 +2,18 @@ namespace Rust { -std::vector<std::unique_ptr<AST::Token>> -SubstituteCtx::substitute_metavar (std::unique_ptr<AST::Token> &metavar) +bool +SubstituteCtx::substitute_metavar ( + std::unique_ptr<AST::Token> &metavar, + std::vector<std::unique_ptr<AST::Token>> &expanded) { auto metavar_name = metavar->get_str (); - std::vector<std::unique_ptr<AST::Token>> expanded; auto it = fragments.find (metavar_name); if (it == fragments.end ()) { - // Return a copy of the original token - expanded.push_back (metavar->clone_token ()); + // fail to substitute + return false; } else { @@ -28,7 +29,7 @@ SubstituteCtx::substitute_metavar (std::unique_ptr<AST::Token> &metavar) metavar->get_locus (), "you probably forgot the repetition operator: %<%s%s%s%>", "$(", metavar->as_string ().c_str (), ")*"); - return expanded; + return true; } // We only care about the vector when expanding repetitions. @@ -42,7 +43,7 @@ SubstituteCtx::substitute_metavar (std::unique_ptr<AST::Token> &metavar) } } - return expanded; + return true; } bool @@ -209,14 +210,17 @@ SubstituteCtx::substitute_token (size_t token_idx) if (token_id_is_keyword (token->get_id ())) { case IDENTIFIER: + std::vector<std::unique_ptr<AST::Token>> expanded; + rust_debug ("expanding metavar: %s", token->get_str ().c_str ()); - return {substitute_metavar (token), 1}; + + if (substitute_metavar (token, expanded)) + return {std::move (expanded), 2}; } - rust_error_at (token->get_locus (), - "unexpected token in macro transcribe: expected " - "%<(%> or identifier after %<$%>, got %<%s%>", - get_token_description (token->get_id ())); - break; + + // don't substitute, dollar sign is alone/metavar is unknown + return {std::vector<std::unique_ptr<AST::Token>> (), 0}; + case LEFT_PAREN: { // We need to parse up until the closing delimiter and expand this // fragment->n times. @@ -285,17 +289,11 @@ SubstituteCtx::substitute_token (size_t token_idx) return {substitute_repetition (pattern_start, pattern_end, std::move (separator_token)), - pattern_end - pattern_start + to_skip}; + pattern_end - pattern_start + to_skip + 1}; } - // TODO: We need to check if the $ was alone. In that case, do - // not error out: Simply act as if there was an empty identifier - // with no associated fragment and paste the dollar sign in the - // transcription. Unsure how to do that since we always have at - // least the closing curly brace after an empty $... } - // FIXME: gcc_unreachable() error case? - return {std::vector<std::unique_ptr<AST::Token>> (), 0}; + gcc_unreachable (); } std::vector<std::unique_ptr<AST::Token>> @@ -304,7 +302,7 @@ SubstituteCtx::substitute_tokens () std::vector<std::unique_ptr<AST::Token>> replaced_tokens; rust_debug ("expanding tokens"); - for (size_t i = 0; i < macro.size (); i++) + for (size_t i = 0; i < macro.size ();) { auto &tok = macro.at (i); if (tok->get_id () == DOLLAR_SIGN) @@ -315,6 +313,12 @@ SubstituteCtx::substitute_tokens () auto expanded = std::move (p.first); auto tok_to_skip = p.second; + if (!tok_to_skip) + { + replaced_tokens.emplace_back (tok->clone_token ()); + tok_to_skip++; + } + i += tok_to_skip; for (auto &token : expanded) @@ -323,6 +327,7 @@ SubstituteCtx::substitute_tokens () else { replaced_tokens.emplace_back (tok->clone_token ()); + i++; } } diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h index 86dddb2..dd49bb1 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.h +++ b/gcc/rust/expand/rust-macro-substitute-ctx.h @@ -49,12 +49,13 @@ public: * i.e. replacing $var with the associated fragment. * * @param metavar Metavariable to try and replace + * @param expanded Reference to a vector upon which expanded tokens will be + * pushed * - * @return A token containing the associated fragment expanded into tokens if - * any, or the cloned token if no fragment was associated + * @return True iff the substitution succeeded */ - std::vector<std::unique_ptr<AST::Token>> - substitute_metavar (std::unique_ptr<AST::Token> &metavar); + bool substitute_metavar (std::unique_ptr<AST::Token> &metavar, + std::vector<std::unique_ptr<AST::Token>> &expanded); /** * Substitute a macro repetition by its given fragments |