diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-02-24 13:09:17 +0100 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2025-03-06 15:44:14 +0000 |
commit | f88af6176e24e62670f33f3d119db02850c11af2 (patch) | |
tree | 510f16e233618fa414528254692bf3f04b5048ab /gcc/rust/expand | |
parent | 912ebb6b74936e6e69bba116af7e45caab3c414c (diff) | |
download | gcc-f88af6176e24e62670f33f3d119db02850c11af2.zip gcc-f88af6176e24e62670f33f3d119db02850c11af2.tar.gz gcc-f88af6176e24e62670f33f3d119db02850c11af2.tar.bz2 |
expansion: Correctly expand $crate metavar
gcc/rust/ChangeLog:
* expand/rust-macro-expand.cc: Use new SubstituteCtx API.
* expand/rust-macro-expand.h: Likewise.
* expand/rust-macro-substitute-ctx.cc: Implement proper expansion of $crate.
* expand/rust-macro-substitute-ctx.h: Adapt APIs to take macro definition when
substituting.
* util/rust-hir-map.cc (Mappings::insert_macro_def): Store crate information when
inserting macro definition in mappings.
(Mappings::lookup_macro_def_crate): New.
* util/rust-hir-map.h: Adapt mappings to store crate in which macros were defined.
gcc/testsuite/ChangeLog:
* rust/execute/crate-metavar1.rs: New test.
* rust/compile/crate-metavar1.rs: New test.
Diffstat (limited to 'gcc/rust/expand')
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 10 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 3 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-substitute-ctx.cc | 51 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-substitute-ctx.h | 25 |
4 files changed, 75 insertions, 14 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 0b01ede..7829757 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -23,6 +23,7 @@ #include "rust-ast-full.h" #include "rust-ast-visitor.h" #include "rust-diagnostics.h" +#include "rust-macro.h" #include "rust-parse.h" #include "rust-cfg-strip.h" #include "rust-early-name-resolver.h" @@ -118,7 +119,7 @@ MacroExpander::expand_decl_macro (location_t invoc_locus, for (auto &ent : matched_fragments) matched_fragments_ptr.emplace (ent.first, ent.second.get ()); - return transcribe_rule (*matched_rule, invoc_token_tree, + return transcribe_rule (rules_def, *matched_rule, invoc_token_tree, matched_fragments_ptr, semicolon, peek_context ()); } @@ -1023,7 +1024,8 @@ tokens_to_str (std::vector<std::unique_ptr<AST::Token>> &tokens) AST::Fragment MacroExpander::transcribe_rule ( - AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree, + AST::MacroRulesDefinition &definition, AST::MacroRule &match_rule, + AST::DelimTokenTree &invoc_token_tree, std::map<std::string, MatchedFragmentContainer *> &matched_fragments, AST::InvocKind invoc_kind, ContextType ctx) { @@ -1037,8 +1039,8 @@ MacroExpander::transcribe_rule ( auto invoc_stream = invoc_token_tree.to_token_stream (); auto macro_rule_tokens = transcribe_tree.to_token_stream (); - auto substitute_context - = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments); + auto substitute_context = SubstituteCtx (invoc_stream, macro_rule_tokens, + matched_fragments, definition); std::vector<std::unique_ptr<AST::Token>> substituted_tokens = substitute_context.substitute_tokens (); diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index c186f3d..3948e44 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -331,7 +331,8 @@ struct MacroExpander AST::DelimTokenTree &invoc_token_tree); AST::Fragment transcribe_rule ( - AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree, + AST::MacroRulesDefinition &definition, AST::MacroRule &match_rule, + AST::DelimTokenTree &invoc_token_tree, std::map<std::string, MatchedFragmentContainer *> &matched_fragments, AST::InvocKind invoc_kind, ContextType ctx); diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 03709a1..9eb2d92 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -17,10 +17,47 @@ // <http://www.gnu.org/licenses/>. #include "rust-macro-substitute-ctx.h" +#include "input.h" +#include "rust-hir-map.h" +#include "rust-token.h" namespace Rust { bool +SubstituteCtx::substitute_dollar_crate ( + std::vector<std::unique_ptr<AST::Token>> &expanded) +{ + auto &mappings = Analysis::Mappings::get (); + + auto def_crate = mappings.lookup_macro_def_crate (definition.get_node_id ()); + auto current_crate = mappings.get_current_crate (); + + rust_assert (def_crate); + + // If we're expanding a macro defined in the current crate which uses $crate, + // we can just replace the metavar with the `crate` path segment. Otherwise, + // use the fully qualified extern-crate lookup path `::<crate_name>` + if (*def_crate == current_crate) + { + expanded.push_back (std::make_unique<AST::Token> ( + Rust::Token::make_identifier (UNKNOWN_LOCATION, "crate"))); + } + else + { + auto name = mappings.get_crate_name (*def_crate); + + rust_assert (name); + + expanded.push_back (std::make_unique<AST::Token> ( + Rust::Token::make (SCOPE_RESOLUTION, UNKNOWN_LOCATION))); + expanded.push_back (std::make_unique<AST::Token> ( + Rust::Token::make_identifier (UNKNOWN_LOCATION, std::string (*name)))); + } + + return true; +} + +bool SubstituteCtx::substitute_metavar ( std::unique_ptr<AST::Token> &metavar, std::vector<std::unique_ptr<AST::Token>> &expanded) @@ -30,14 +67,15 @@ SubstituteCtx::substitute_metavar ( auto it = fragments.find (metavar_name); if (it == fragments.end ()) { - // fail to substitute + // fail to substitute, unless we are dealing with a special-case metavar + // like $crate - // HACK: substitute ($ crate) => (crate) - if (metavar->get_id () != CRATE) - return false; + if (metavar->get_id () == CRATE) + return substitute_dollar_crate (expanded); expanded.push_back (metavar->clone_token ()); - return true; + + return false; } else { @@ -187,7 +225,8 @@ SubstituteCtx::substitute_repetition ( kv_match.second->get_fragments ().at (i).get ()); } - auto substitute_context = SubstituteCtx (input, new_macro, sub_map); + auto substitute_context + = SubstituteCtx (input, new_macro, sub_map, definition); auto new_tokens = substitute_context.substitute_tokens (); // Skip the first repetition, but add the separator to the expanded diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h index 835f48a..7e0175a 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.h +++ b/gcc/rust/expand/rust-macro-substitute-ctx.h @@ -18,6 +18,7 @@ #include "rust-ast.h" #include "rust-macro-expand.h" +#include "rust-macro.h" namespace Rust { class SubstituteCtx @@ -25,6 +26,7 @@ class SubstituteCtx std::vector<std::unique_ptr<AST::Token>> &input; std::vector<std::unique_ptr<AST::Token>> ¯o; std::map<std::string, MatchedFragmentContainer *> &fragments; + AST::MacroRulesDefinition &definition; /** * Find the repetition amount to use when expanding a repetition, and @@ -40,11 +42,28 @@ class SubstituteCtx public: SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input, std::vector<std::unique_ptr<AST::Token>> ¯o, - std::map<std::string, MatchedFragmentContainer *> &fragments) - : input (input), macro (macro), fragments (fragments) + std::map<std::string, MatchedFragmentContainer *> &fragments, + AST::MacroRulesDefinition &definition) + : input (input), macro (macro), fragments (fragments), + definition (definition) {} /** + * Special-case the $crate metavar to expand to the name of the crate in which + * the macro was defined. + * + * https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.hygiene.crate + * + * + * @param expanded Reference to a vector upon which expanded tokens will be + * pushed + * + * @return True if the substitution succeeded + */ + bool + substitute_dollar_crate (std::vector<std::unique_ptr<AST::Token>> &expanded); + + /** * Substitute a metavariable by its given fragment in a transcribing context, * i.e. replacing $var with the associated fragment. * @@ -52,7 +71,7 @@ public: * @param expanded Reference to a vector upon which expanded tokens will be * pushed * - * @return True iff the substitution succeeded + * @return True if the substitution succeeded */ bool substitute_metavar (std::unique_ptr<AST::Token> &metavar, std::vector<std::unique_ptr<AST::Token>> &expanded); |