[gcc r14-7556] gccrs: enr: Accumulate nested escaped macros properly.

Arthur Cohen cohenarthur@gcc.gnu.org
Tue Jan 16 17:40:17 GMT 2024


https://gcc.gnu.org/g:12dd77c19fbcf2446a895804848ffb498e0d3688

commit r14-7556-g12dd77c19fbcf2446a895804848ffb498e0d3688
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Tue Apr 18 16:22:22 2023 +0200

    gccrs: enr: Accumulate nested escaped macros properly.
    
    gcc/rust/ChangeLog:
            * resolve/rust-early-name-resolver.cc (is_macro_use_module): New function.
            (EarlyNameResolver::accumulate_escaped_macros): New function.
            (EarlyNameResolver::go): Use `accumulate_escaped_macros`.
            (EarlyNameResolver::visit): Likewise.
            * resolve/rust-early-name-resolver.h: Declare `accumulate_escaped_macros`.
    
    gcc/testsuite/ChangeLog:
            * rust/compile/macro_use1.rs: New test.
            * rust/execute/torture/macro_use1.rs: New test.
            * rust/compile/nested_macro_use1.rs: New test.
            * rust/compile/nested_macro_use2.rs: New test.

Diff:
---
 gcc/rust/resolve/rust-early-name-resolver.cc     | 101 ++++++++++++++++++++++-
 gcc/rust/resolve/rust-early-name-resolver.h      |  12 +++
 gcc/testsuite/rust/compile/macro_use1.rs         |  15 ++++
 gcc/testsuite/rust/compile/nested_macro_use1.rs  |  19 +++++
 gcc/testsuite/rust/compile/nested_macro_use2.rs  |  12 +++
 gcc/testsuite/rust/execute/torture/macro_use1.rs |  18 ++++
 6 files changed, 174 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index 145b3931188..f3e4b198f09 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -24,6 +24,55 @@
 namespace Rust {
 namespace Resolver {
 
+// Check if a module contains the `#[macro_use]` attribute
+static bool
+is_macro_use_module (const AST::Module &mod)
+{
+  for (const auto &attr : mod.get_outer_attrs ())
+    if (attr.get_path ().as_string () == "macro_use")
+      return true;
+
+  return false;
+}
+
+std::vector<std::unique_ptr<AST::Item>>
+EarlyNameResolver::accumulate_escaped_macros (AST::Module &module)
+{
+  if (!is_macro_use_module (module))
+    return {};
+
+  // Parse the module's items if they haven't been expanded and the file
+  // should be parsed (i.e isn't hidden behind an untrue or impossible cfg
+  // directive)
+  if (module.get_kind () == AST::Module::UNLOADED)
+    module.load_items ();
+
+  std::vector<std::unique_ptr<AST::Item>> escaped_macros;
+
+  scoped (module.get_node_id (), [&module, &escaped_macros, this] {
+    for (auto &item : module.get_items ())
+      {
+	if (item->get_ast_kind () == AST::Kind::MODULE)
+	  {
+	    auto &module = *static_cast<AST::Module *> (item.get ());
+	    auto new_macros = accumulate_escaped_macros (module);
+
+	    std::move (new_macros.begin (), new_macros.end (),
+		       std::back_inserter (escaped_macros));
+
+	    continue;
+	  }
+
+	item->accept_vis (*this);
+
+	if (item->get_ast_kind () == AST::Kind::MACRO_RULES_DEFINITION)
+	  escaped_macros.emplace_back (item->clone_item ());
+      }
+  });
+
+  return escaped_macros;
+}
+
 EarlyNameResolver::EarlyNameResolver ()
   : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()),
     mappings (*Analysis::Mappings::get ())
@@ -32,6 +81,29 @@ EarlyNameResolver::EarlyNameResolver ()
 void
 EarlyNameResolver::go (AST::Crate &crate)
 {
+  std::vector<std::unique_ptr<AST::Item>> new_items;
+  auto items = crate.take_items ();
+
+  scoped (crate.get_node_id (), [&items, &new_items, this] {
+    for (auto &&item : items)
+      {
+	if (item->get_ast_kind () == AST::Kind::MODULE)
+	  {
+	    auto macros = accumulate_escaped_macros (
+	      *static_cast<AST::Module *> (item.get ()));
+	    new_items.emplace_back (std::move (item));
+	    std::move (macros.begin (), macros.end (),
+		       std::back_inserter (new_items));
+	  }
+	else
+	  {
+	    new_items.emplace_back (std::move (item));
+	  }
+      }
+  });
+
+  crate.set_items (std::move (new_items));
+
   scoped (crate.get_node_id (), [&crate, this] () {
     for (auto &item : crate.items)
       item->accept_vis (*this);
@@ -550,12 +622,35 @@ EarlyNameResolver::visit (AST::Method &method)
 void
 EarlyNameResolver::visit (AST::Module &module)
 {
-  // Parse the module's items if they haven't been expanded and the file
-  // should be parsed (i.e isn't hidden behind an untrue or impossible cfg
-  // directive)
   if (module.get_kind () == AST::Module::UNLOADED)
     module.load_items ();
 
+  // so we need to only go "one scope down" for fetching macros. Macros within
+  // functions are still scoped only within that function. But we have to be
+  // careful because nested modules with #[macro_use] actually works!
+  std::vector<std::unique_ptr<AST::Item>> new_items;
+  auto items = module.take_items ();
+
+  scoped (module.get_node_id (), [&items, &new_items, this] {
+    for (auto &&item : items)
+      {
+	if (item->get_ast_kind () == AST::Kind::MODULE)
+	  {
+	    auto macros = accumulate_escaped_macros (
+	      *static_cast<AST::Module *> (item.get ()));
+	    new_items.emplace_back (std::move (item));
+	    std::move (macros.begin (), macros.end (),
+		       std::back_inserter (new_items));
+	  }
+	else
+	  {
+	    new_items.emplace_back (std::move (item));
+	  }
+      }
+  });
+
+  module.set_items (std::move (new_items));
+
   scoped (module.get_node_id (), [&module, this] () {
     for (auto &item : module.get_items ())
       item->accept_vis (*this);
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index 07281378c5b..dfdab817d00 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -53,6 +53,18 @@ private:
     current_scope = old_scope;
   }
 
+  /**
+   * Accumulate all of the nested macros which escape their module through the
+   * use of the #[macro_use] attribute.
+   *
+   * This function recursively accumulates macros in all of the nested modules
+   * of an item container (an AST::Crate or an AST::Module) and returns this new
+   * list of items. You can then use the `take_items` and `set_items` functions
+   * on these containers to replace their list of items.
+   */
+  std::vector<std::unique_ptr<AST::Item>>
+  accumulate_escaped_macros (AST::Module &module);
+
   /**
    * The "scope" we are currently in.
    *
diff --git a/gcc/testsuite/rust/compile/macro_use1.rs b/gcc/testsuite/rust/compile/macro_use1.rs
new file mode 100644
index 00000000000..e98eadff0ae
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro_use1.rs
@@ -0,0 +1,15 @@
+#[macro_use]
+mod foo {
+    macro_rules! a {
+        () => {};
+    }
+
+    macro_rules! b {
+        () => {};
+    }
+}
+
+fn main() {
+    a!();
+    b!();
+}
diff --git a/gcc/testsuite/rust/compile/nested_macro_use1.rs b/gcc/testsuite/rust/compile/nested_macro_use1.rs
new file mode 100644
index 00000000000..8a2fd2ac82d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/nested_macro_use1.rs
@@ -0,0 +1,19 @@
+#[macro_use]
+mod foo {
+    #[macro_use]
+    mod zim {
+        #[macro_use]
+        mod zoom {
+            #[macro_use]
+            mod zum {
+                macro_rules! qux {
+                    () => {};
+                }
+            }
+        }
+    }
+}
+
+fn main() {
+    qux!(); // OK
+}
diff --git a/gcc/testsuite/rust/compile/nested_macro_use2.rs b/gcc/testsuite/rust/compile/nested_macro_use2.rs
new file mode 100644
index 00000000000..46595008710
--- /dev/null
+++ b/gcc/testsuite/rust/compile/nested_macro_use2.rs
@@ -0,0 +1,12 @@
+#[macro_use]
+mod foo {
+    fn bar() {
+        macro_rules! baz {
+            () => {{}};
+        }
+    }
+}
+
+fn main() {
+    baz!(); // { dg-error "unknown macro: .baz." }
+}
diff --git a/gcc/testsuite/rust/execute/torture/macro_use1.rs b/gcc/testsuite/rust/execute/torture/macro_use1.rs
new file mode 100644
index 00000000000..fdf553012eb
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macro_use1.rs
@@ -0,0 +1,18 @@
+#[macro_use]
+mod foo {
+    macro_rules! a {
+        () => {
+            15
+        };
+    }
+
+    macro_rules! b {
+        () => {
+            14
+        };
+    }
+}
+
+fn main() -> i32 {
+    a!() + b!() - 29
+}


More information about the Gcc-cvs mailing list