aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand/rust-macro-substitute-ctx.cc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2025-02-24 13:09:17 +0100
committerCohenArthur <arthur.cohen@embecosm.com>2025-03-06 15:44:14 +0000
commitf88af6176e24e62670f33f3d119db02850c11af2 (patch)
tree510f16e233618fa414528254692bf3f04b5048ab /gcc/rust/expand/rust-macro-substitute-ctx.cc
parent912ebb6b74936e6e69bba116af7e45caab3c414c (diff)
downloadgcc-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/rust-macro-substitute-ctx.cc')
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc51
1 files changed, 45 insertions, 6 deletions
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