public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Semicolon based macro invocation
@ 2022-06-08 12:08 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-08 12:08 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:37415eec77438bba2fc61df3e9a396c1e2cbaca8

commit 37415eec77438bba2fc61df3e9a396c1e2cbaca8
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Thu Feb 17 15:26:35 2022 +0000

    Semicolon based macro invocation
    
    This allows for macro invocation at the toplevel or as statements. This
    patched required us to propogate the delimited token tree fix to include
    the delimiter tokens. The rest of the fix was straight forward to call
    the apropriate visitors in names resolution and hir lowering.
    
    Some thought will be needed to handle hir lowering for repeating items.

Diff:
---
 gcc/rust/ast/rust-ast.h                       | 170 +++++++++++++++++++++++++-
 gcc/rust/ast/rust-macro.h                     | 129 -------------------
 gcc/rust/expand/rust-macro-expand.cc          | 127 ++++++++++++++++---
 gcc/rust/expand/rust-macro-expand.h           |  25 +++-
 gcc/rust/hir/rust-ast-lower-implitem.h        |  20 +++
 gcc/rust/hir/rust-ast-lower-item.h            |  10 ++
 gcc/rust/hir/rust-ast-lower-stmt.h            |  10 ++
 gcc/rust/parse/rust-parse-impl.h              |  20 +++
 gcc/rust/resolve/rust-ast-resolve-expr.h      |   7 +-
 gcc/rust/resolve/rust-ast-resolve-implitem.h  |  21 ++++
 gcc/rust/resolve/rust-ast-resolve-item.h      |  14 +++
 gcc/rust/resolve/rust-ast-resolve-stmt.h      |   8 ++
 gcc/rust/resolve/rust-ast-resolve-toplevel.h  |   7 ++
 gcc/rust/typecheck/rust-tycheck-dump.h        |   6 +
 gcc/testsuite/rust/execute/torture/macros6.rs |  12 ++
 15 files changed, 430 insertions(+), 156 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 3e7faf55386..e72937e5d70 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1475,6 +1475,160 @@ public:
   }
 };
 
+class SingleASTNode
+{
+public:
+  enum NodeType
+  {
+    EXPRESSION,
+    ITEM,
+    STMT,
+  };
+
+  SingleASTNode (std::unique_ptr<Expr> expr)
+    : type (EXPRESSION), expr (std::move (expr)), item (nullptr), stmt (nullptr)
+  {}
+
+  SingleASTNode (std::unique_ptr<Item> item)
+    : type (ITEM), expr (nullptr), item (std::move (item)), stmt (nullptr)
+  {}
+
+  SingleASTNode (std::unique_ptr<Stmt> stmt)
+    : type (STMT), expr (nullptr), item (nullptr), stmt (std::move (stmt))
+  {}
+
+  SingleASTNode (SingleASTNode const &other)
+  {
+    type = other.type;
+    switch (type)
+      {
+      case EXPRESSION:
+	expr = other.expr->clone_expr ();
+	break;
+
+      case ITEM:
+	item = other.item->clone_item ();
+	break;
+
+      case STMT:
+	stmt = other.stmt->clone_stmt ();
+	break;
+      }
+  }
+
+  SingleASTNode operator= (SingleASTNode const &other)
+  {
+    type = other.type;
+    switch (type)
+      {
+      case EXPRESSION:
+	expr = other.expr->clone_expr ();
+	break;
+
+      case ITEM:
+	item = other.item->clone_item ();
+	break;
+
+      case STMT:
+	stmt = other.stmt->clone_stmt ();
+	break;
+      }
+    return *this;
+  }
+
+  SingleASTNode (SingleASTNode &&other) = default;
+  SingleASTNode &operator= (SingleASTNode &&other) = default;
+
+  std::unique_ptr<Expr> &get_expr ()
+  {
+    rust_assert (type == EXPRESSION);
+    return expr;
+  }
+
+  std::unique_ptr<Item> &get_item ()
+  {
+    rust_assert (type == ITEM);
+    return item;
+  }
+
+  std::unique_ptr<Stmt> &get_stmt ()
+  {
+    rust_assert (type == STMT);
+    return stmt;
+  }
+
+  void accept_vis (ASTVisitor &vis)
+  {
+    switch (type)
+      {
+      case EXPRESSION:
+	expr->accept_vis (vis);
+	break;
+
+      case ITEM:
+	item->accept_vis (vis);
+	break;
+
+      case STMT:
+	stmt->accept_vis (vis);
+	break;
+      }
+  }
+
+private:
+  NodeType type;
+
+  // FIXME make this a union
+  std::unique_ptr<Expr> expr;
+  std::unique_ptr<Item> item;
+  std::unique_ptr<Stmt> stmt;
+};
+
+/* Basically, a "fragment" that can be incorporated into the AST, created as
+ * a result of macro expansion. Really annoying to work with due to the fact
+ * that macros can really expand to anything. As such, horrible representation
+ * at the moment. */
+class ASTFragment
+{
+private:
+  /* basic idea: essentially, a vector of tagged unions of different AST node
+   * types. Now, this could actually be stored without a tagged union if the
+   * different AST node types had a unified parent, but that would create
+   * issues with the diamond problem or significant performance penalties. So
+   * a tagged union had to be used instead. A vector is used to represent the
+   * ability for a macro to expand to two statements, for instance. */
+
+  std::vector<SingleASTNode> nodes;
+
+public:
+  ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {}
+
+  ASTFragment (ASTFragment const &other)
+  {
+    nodes.clear ();
+    nodes.reserve (other.nodes.size ());
+    for (auto &n : other.nodes)
+      {
+	nodes.push_back (n);
+      }
+  }
+
+  ASTFragment &operator= (ASTFragment const &other)
+  {
+    nodes.clear ();
+    nodes.reserve (other.nodes.size ());
+    for (auto &n : other.nodes)
+      {
+	nodes.push_back (n);
+      }
+    return *this;
+  }
+
+  static ASTFragment create_empty () { return ASTFragment ({}); }
+
+  std::vector<SingleASTNode> &get_nodes () { return nodes; }
+};
+
 /* A macro invocation item (or statement) AST node (i.e. semi-coloned macro
  * invocation) */
 class MacroInvocationSemi : public MacroItem,
@@ -1486,6 +1640,10 @@ class MacroInvocationSemi : public MacroItem,
   std::vector<Attribute> outer_attrs;
   MacroInvocData invoc_data;
   Location locus;
+  NodeId node_id;
+
+  // this is the expanded macro
+  ASTFragment fragment;
 
 public:
   std::string as_string () const override;
@@ -1493,7 +1651,9 @@ public:
   MacroInvocationSemi (MacroInvocData invoc_data,
 		       std::vector<Attribute> outer_attrs, Location locus)
     : outer_attrs (std::move (outer_attrs)),
-      invoc_data (std::move (invoc_data)), locus (locus)
+      invoc_data (std::move (invoc_data)), locus (locus),
+      node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+      fragment (ASTFragment::create_empty ())
   {}
 
   void accept_vis (ASTVisitor &vis) override;
@@ -1517,6 +1677,14 @@ public:
 
   Location get_locus () const override final { return locus; }
 
+  MacroInvocData &get_invoc_data () { return invoc_data; }
+
+  ASTFragment &get_fragment () { return fragment; }
+
+  void set_fragment (ASTFragment &&f) { fragment = std::move (f); }
+
+  NodeId get_macro_node_id () const { return node_id; }
+
 protected:
   MacroInvocationSemi *clone_macro_invocation_semi_impl () const
   {
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 1e95ebe14e3..b5370d853fc 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -84,135 +84,6 @@ get_frag_spec_from_str (std::string str)
     }
 }
 
-class SingleASTNode
-{
-public:
-  enum NodeType
-  {
-    EXPRESSION,
-    ITEM,
-  };
-
-  SingleASTNode (std::unique_ptr<Expr> expr)
-    : type (EXPRESSION), expr (std::move (expr)), item (nullptr)
-  {}
-
-  SingleASTNode (std::unique_ptr<Item> item)
-    : type (ITEM), expr (nullptr), item (std::move (item))
-  {}
-
-  SingleASTNode (SingleASTNode const &other)
-  {
-    type = other.type;
-    switch (type)
-      {
-      case EXPRESSION:
-	expr = other.expr->clone_expr ();
-	break;
-
-      case ITEM:
-	item = other.item->clone_item ();
-	break;
-      }
-  }
-
-  SingleASTNode operator= (SingleASTNode const &other)
-  {
-    type = other.type;
-    switch (type)
-      {
-      case EXPRESSION:
-	expr = other.expr->clone_expr ();
-	break;
-
-      case ITEM:
-	item = other.item->clone_item ();
-	break;
-      }
-    return *this;
-  }
-
-  SingleASTNode (SingleASTNode &&other) = default;
-  SingleASTNode &operator= (SingleASTNode &&other) = default;
-
-  std::unique_ptr<Expr> &get_expr ()
-  {
-    rust_assert (type == EXPRESSION);
-    return expr;
-  }
-
-  std::unique_ptr<Item> &get_item ()
-  {
-    rust_assert (type == ITEM);
-    return item;
-  }
-
-  void accept_vis (ASTVisitor &vis)
-  {
-    switch (type)
-      {
-      case EXPRESSION:
-	expr->accept_vis (vis);
-	break;
-
-      case ITEM:
-	item->accept_vis (vis);
-	break;
-      }
-  }
-
-private:
-  NodeType type;
-  std::unique_ptr<Expr> expr;
-  std::unique_ptr<Item> item;
-  // TODO add meta attribute
-};
-
-/* Basically, a "fragment" that can be incorporated into the AST, created as
- * a result of macro expansion. Really annoying to work with due to the fact
- * that macros can really expand to anything. As such, horrible representation
- * at the moment. */
-class ASTFragment
-{
-private:
-  /* basic idea: essentially, a vector of tagged unions of different AST node
-   * types. Now, this could actually be stored without a tagged union if the
-   * different AST node types had a unified parent, but that would create
-   * issues with the diamond problem or significant performance penalties. So
-   * a tagged union had to be used instead. A vector is used to represent the
-   * ability for a macro to expand to two statements, for instance. */
-
-  std::vector<SingleASTNode> nodes;
-
-public:
-  ASTFragment (std::vector<SingleASTNode> nodes) : nodes (std::move (nodes)) {}
-
-  ASTFragment (ASTFragment const &other)
-  {
-    nodes.clear ();
-    nodes.reserve (other.nodes.size ());
-    for (auto &n : other.nodes)
-      {
-	nodes.push_back (n);
-      }
-  }
-
-  ASTFragment &operator= (ASTFragment const &other)
-  {
-    nodes.clear ();
-    nodes.reserve (other.nodes.size ());
-    for (auto &n : other.nodes)
-      {
-	nodes.push_back (n);
-      }
-    return *this;
-  }
-
-  static ASTFragment create_empty () { return ASTFragment ({}); }
-
-  std::vector<SingleASTNode> &get_nodes () { return nodes; }
-};
-
 // A macro match that has an identifier and fragment spec
 class MacroMatchFragment : public MacroMatch
 {
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index bce524611cb..dcfec7ceeb7 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -324,6 +324,13 @@ public:
     // I don't think any macro token trees can be stripped in any way
 
     // TODO: maybe have cfg! macro stripping behaviour here?
+
+    expander.expand_invoc_semi (macro_invoc);
+
+    // we need to visit the expanded fragments since it may need cfg expansion
+    // and it may be recursive
+    for (auto &node : macro_invoc.get_fragment ().get_nodes ())
+      node.accept_vis (*this);
   }
 
   void visit (AST::PathInExpression &path) override
@@ -1034,13 +1041,17 @@ public:
 		     "cannot strip expression in this position - outer "
 		     "attributes not allowed");
   }
+
   void visit (AST::BlockExpr &expr) override
   {
+    expander.push_context (MacroExpander::BLOCK);
+
     // initial strip test based on outer attrs
     expander.expand_cfg_attrs (expr.get_outer_attrs ());
     if (expander.fails_cfg_with_expand (expr.get_outer_attrs ()))
       {
 	expr.mark_for_strip ();
+	expander.pop_context ();
 	return;
       }
 
@@ -1050,6 +1061,7 @@ public:
     if (expander.fails_cfg_with_expand (expr.get_inner_attrs ()))
       {
 	expr.mark_for_strip ();
+	expander.pop_context ();
 	return;
       }
 
@@ -1066,7 +1078,9 @@ public:
 	if (tail_expr->is_marked_for_strip ())
 	  expr.strip_tail_expr ();
       }
+    expander.pop_context ();
   }
+
   void visit (AST::ClosureExprInnerTyped &expr) override
   {
     // initial strip test based on outer attrs
@@ -2533,7 +2547,6 @@ public:
       }
 
     // I don't think any macro token trees can be stripped in any way
-
     expander.expand_invoc (macro_invoc);
 
     // we need to visit the expanded fragments since it may need cfg expansion
@@ -3059,7 +3072,8 @@ MacroExpander::expand_cfg_macro (AST::MacroInvocData &invoc)
 AST::ASTFragment
 MacroExpander::expand_decl_macro (Location invoc_locus,
 				  AST::MacroInvocData &invoc,
-				  AST::MacroRulesDefinition &rules_def)
+				  AST::MacroRulesDefinition &rules_def,
+				  bool semicolon)
 {
   // ensure that both invocation and rules are in a valid state
   rust_assert (!invoc.is_marked_for_strip ());
@@ -3126,7 +3140,8 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
       return AST::ASTFragment::create_empty ();
     }
 
-  return transcribe_rule (*matched_rule, invoc_token_tree, matched_fragments);
+  return transcribe_rule (*matched_rule, invoc_token_tree, matched_fragments,
+			  semicolon, peek_context ());
 }
 
 void
@@ -3176,7 +3191,42 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
   rust_assert (ok);
 
   auto fragment
-    = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def);
+    = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
+
+  // lets attach this fragment to the invocation
+  invoc.set_fragment (std::move (fragment));
+}
+
+void
+MacroExpander::expand_invoc_semi (AST::MacroInvocationSemi &invoc)
+{
+  if (depth_exceeds_recursion_limit ())
+    {
+      rust_error_at (invoc.get_locus (), "reached recursion limit");
+      return;
+    }
+
+  AST::MacroInvocData &invoc_data = invoc.get_invoc_data ();
+
+  // lookup the rules for this macro
+  NodeId resolved_node = UNKNOWN_NODEID;
+  bool found = resolver->get_macro_scope ().lookup (
+    Resolver::CanonicalPath::new_seg (invoc.get_macro_node_id (),
+				      invoc_data.get_path ().as_string ()),
+    &resolved_node);
+  if (!found)
+    {
+      rust_error_at (invoc.get_locus (), "unknown macro");
+      return;
+    }
+
+  // lookup the rules
+  AST::MacroRulesDefinition *rules_def = nullptr;
+  bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
+  rust_assert (ok);
+
+  auto fragment
+    = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
 
   // lets attach this fragment to the invocation
   invoc.set_fragment (std::move (fragment));
@@ -3301,6 +3351,8 @@ MacroExpander::expand_crate ()
     }
   // expand module attributes?
 
+  push_context (ITEM);
+
   // expand attributes recursively and strip items if required
   AttrVisitor attr_visitor (*this);
   auto &items = crate.items;
@@ -3317,6 +3369,8 @@ MacroExpander::expand_crate ()
 	++it;
     }
 
+  pop_context ();
+
   // TODO: should recursive attribute and macro expansion be done in the same
   // transversal? Or in separate ones like currently?
 
@@ -3555,7 +3609,8 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
 AST::ASTFragment
 MacroExpander::transcribe_rule (
   AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
-  std::map<std::string, MatchedFragment> &matched_fragments)
+  std::map<std::string, MatchedFragment> &matched_fragments, bool semicolon,
+  ContextType ctx)
 {
   // we can manipulate the token tree to substitute the dollar identifiers so
   // that when we call parse its already substituted for us
@@ -3568,7 +3623,7 @@ MacroExpander::transcribe_rule (
   std::vector<std::unique_ptr<AST::Token>> substituted_tokens
     = substitute_tokens (invoc_stream, macro_rule_tokens, matched_fragments);
 
-  // handy for debugging
+  // // handy for debugging
   // for (auto &tok : substituted_tokens)
   //   {
   //     rust_debug ("tok: [%s]", tok->as_string ().c_str ());
@@ -3579,7 +3634,6 @@ MacroExpander::transcribe_rule (
   Parser<MacroInvocLexer> parser (std::move (lex));
 
   // this is used so we can check that we delimit the stream correctly.
-  std::vector<AST::SingleASTNode> nodes;
   switch (transcribe_tree.get_delim_type ())
     {
     case AST::DelimType::PARENS:
@@ -3595,26 +3649,61 @@ MacroExpander::transcribe_rule (
       break;
     }
 
+  // see https://github.com/Rust-GCC/gccrs/issues/22
+  // TL;DR:
+  //   - Treat all macro invocations with parentheses, (), or square brackets,
+  //   [], as expressions.
+  //   - If the macro invocation has curly brackets, {}, it may be parsed as a
+  //   statement depending on the context.
+  //   - If the macro invocation has a semicolon at the end, it must be parsed
+  //   as a statement (either via ExpressionStatement or
+  //   MacroInvocationWithSemi)
+
   // parse the item
+  std::vector<AST::SingleASTNode> nodes;
   switch (invoc_token_tree.get_delim_type ())
     {
-      case AST::DelimType::PARENS: {
-	auto expr = parser.parse_expr ();
-	if (expr != nullptr && !parser.has_errors ())
-	  nodes.push_back (std::move (expr));
+    case AST::DelimType::PARENS:
+      case AST::DelimType::SQUARE: {
+	switch (ctx)
+	  {
+	    case ContextType::ITEM: {
+	      auto item = parser.parse_item (true);
+	      if (item != nullptr && !parser.has_errors ())
+		{
+		  rust_debug ("HELLO WORLD: [%s]", item->as_string ().c_str ());
+		  nodes.push_back (std::move (item));
+		}
+	    }
+	    break;
+
+	    case ContextType::BLOCK: {
+	      auto expr = parser.parse_expr ();
+	      if (expr != nullptr && !parser.has_errors ())
+		nodes.push_back (std::move (expr));
+	    }
+	    break;
+	  }
       }
       break;
 
       case AST::DelimType::CURLY: {
-	auto item = parser.parse_item (false);
-	if (item != nullptr && !parser.has_errors ())
-	  nodes.push_back (std::move (item));
-      }
-      break;
+	switch (ctx)
+	  {
+	    case ContextType::ITEM: {
+	      auto item = parser.parse_item (true);
+	      if (item != nullptr && !parser.has_errors ())
+		nodes.push_back (std::move (item));
+	    }
+	    break;
 
-      case AST::DelimType::SQUARE: {
-	// FIXME
-	gcc_unreachable ();
+	    case ContextType::BLOCK: {
+	      auto stmt = parser.parse_stmt ();
+	      if (stmt != nullptr && !parser.has_errors ())
+		nodes.push_back (std::move (stmt));
+	    }
+	    break;
+	  }
       }
       break;
     }
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 0f13f9e566b..d8a2d5003e6 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -130,6 +130,12 @@ private:
 // Object used to store shared data (between functions) for macro expansion.
 struct MacroExpander
 {
+  enum ContextType
+  {
+    ITEM,
+    BLOCK,
+  };
+
   ExpansionCfg cfg;
   unsigned int expansion_depth = 0;
 
@@ -148,11 +154,13 @@ struct MacroExpander
    * have similar duck-typed interface and use templates?*/
   // should this be public or private?
   void expand_invoc (AST::MacroInvocation &invoc);
+  void expand_invoc_semi (AST::MacroInvocationSemi &invoc);
 
   // Expands a single declarative macro.
   AST::ASTFragment expand_decl_macro (Location locus,
 				      AST::MacroInvocData &invoc,
-				      AST::MacroRulesDefinition &rules_def);
+				      AST::MacroRulesDefinition &rules_def,
+				      bool semicolon);
 
   void expand_cfg_attrs (AST::AttrVec &attrs);
   bool fails_cfg (const AST::AttrVec &attr) const;
@@ -171,7 +179,8 @@ struct MacroExpander
   AST::ASTFragment
   transcribe_rule (AST::MacroRule &match_rule,
 		   AST::DelimTokenTree &invoc_token_tree,
-		   std::map<std::string, MatchedFragment> &matched_fragments);
+		   std::map<std::string, MatchedFragment> &matched_fragments,
+		   bool semicolon, ContextType ctx);
 
   bool match_fragment (Parser<MacroInvocLexer> &parser,
 		       AST::MacroMatchFragment &fragment);
@@ -189,10 +198,22 @@ struct MacroExpander
 		     std::vector<std::unique_ptr<AST::Token>> &macro,
 		     std::map<std::string, MatchedFragment> &fragments);
 
+  void push_context (ContextType t) { context.push_back (t); }
+
+  ContextType pop_context ()
+  {
+    ContextType t = context.back ();
+    context.pop_back ();
+    return t;
+  }
+
+  ContextType peek_context () { return context.back (); }
+
 private:
   AST::Crate &crate;
   Session &session;
   SubstitutionScope sub_stack;
+  std::vector<ContextType> context;
 
 public:
   Resolver::Resolver *resolver;
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index c9dfd1b6505..3d10b70bc17 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -52,6 +52,16 @@ public:
     return resolver.translated;
   }
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+
+    // FIXME
+    // this assertion might go away, maybe on failure's to expand a macro?
+    rust_assert (!fragment.get_nodes ().empty ());
+    fragment.get_nodes ().at (0).accept_vis (*this);
+  }
+
   void visit (AST::TypeAlias &alias) override
   {
     std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
@@ -308,6 +318,16 @@ public:
     return resolver.translated;
   }
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+
+    // FIXME
+    // this assertion might go away, maybe on failure's to expand a macro?
+    rust_assert (!fragment.get_nodes ().empty ());
+    fragment.get_nodes ().at (0).accept_vis (*this);
+  }
+
   void visit (AST::TraitItemFunc &func) override
   {
     AST::TraitFunctionDecl &ref = func.get_trait_function_decl ();
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index d4b591090c0..30bd896a797 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -47,6 +47,16 @@ public:
     return resolver.translated;
   }
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+
+    // FIXME
+    // this assertion might go away, maybe on failure's to expand a macro?
+    rust_assert (!fragment.get_nodes ().empty ());
+    fragment.get_nodes ().at (0).accept_vis (*this);
+  }
+
   void visit (AST::Module &module) override
   {
     auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h
index ede72bd71bf..b25246a43aa 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -45,6 +45,16 @@ public:
     return resolver.translated;
   }
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+
+    // FIXME
+    // this assertion might go away, maybe on failure's to expand a macro?
+    rust_assert (!fragment.get_nodes ().empty ());
+    fragment.get_nodes ().at (0).accept_vis (*this);
+  }
+
   void visit (AST::ExprStmtWithBlock &stmt) override
   {
     HIR::ExprWithBlock *expr
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 2ea42c74663..784e6d1efd2 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1571,6 +1571,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
 
   // parse actual token trees
   std::vector<std::unique_ptr<AST::TokenTree>> token_trees;
+  auto delim_open
+    = std::unique_ptr<AST::Token> (new AST::Token (std::move (t)));
+  token_trees.push_back (std::move (delim_open));
 
   t = lexer.peek_token ();
   // parse token trees until the initial delimiter token is found again
@@ -1593,6 +1596,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
 
       t = lexer.peek_token ();
     }
+  auto delim_close
+    = std::unique_ptr<AST::Token> (new AST::Token (std::move (t)));
+  token_trees.push_back (std::move (delim_close));
 
   AST::DelimTokenTree delim_tok_tree (delim_type, std::move (token_trees),
 				      tok_tree_locus);
@@ -1611,6 +1617,7 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi (
 	  if (!skip_token (SEMICOLON))
 	    {
 	      // as this is the end, allow recovery (probably) - may change
+
 	      return std::unique_ptr<AST::MacroInvocationSemi> (
 		new AST::MacroInvocationSemi (std::move (invoc_data),
 					      std::move (outer_attrs),
@@ -11761,6 +11768,9 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr (
 
 	// parse actual token trees
 	std::vector<std::unique_ptr<AST::TokenTree>> token_trees;
+	auto delim_open
+	  = std::unique_ptr<AST::Token> (new AST::Token (std::move (t3)));
+	token_trees.push_back (std::move (delim_open));
 
 	t3 = lexer.peek_token ();
 	// parse token trees until the initial delimiter token is found again
@@ -11785,6 +11795,10 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr (
 	    t3 = lexer.peek_token ();
 	  }
 
+	auto delim_close
+	  = std::unique_ptr<AST::Token> (new AST::Token (std::move (t3)));
+	token_trees.push_back (std::move (delim_close));
+
 	// parse end delimiters
 	t3 = lexer.peek_token ();
 	if (token_id_matches_delims (t3->get_id (), type))
@@ -12076,6 +12090,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_maybe_semi (
 
   // parse actual token trees
   std::vector<std::unique_ptr<AST::TokenTree>> token_trees;
+  auto delim_open
+    = std::unique_ptr<AST::Token> (new AST::Token (std::move (t3)));
+  token_trees.push_back (std::move (delim_open));
 
   t3 = lexer.peek_token ();
   // parse token trees until the initial delimiter token is found again
@@ -12098,6 +12115,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_maybe_semi (
 
       t3 = lexer.peek_token ();
     }
+  auto delim_close
+    = std::unique_ptr<AST::Token> (new AST::Token (std::move (t3)));
+  token_trees.push_back (std::move (delim_close));
 
   // parse end delimiters
   t3 = lexer.peek_token ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 4ccb72bd4a8..bb1cbb04794 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -73,11 +73,8 @@ public:
   void visit (AST::MacroInvocation &expr) override
   {
     AST::ASTFragment &fragment = expr.get_fragment ();
-
-    // FIXME
-    // this assertion might go away, maybe on failure's to expand a macro?
-    rust_assert (!fragment.get_nodes ().empty ());
-    fragment.get_nodes ().at (0).accept_vis (*this);
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
   }
 
   void visit (AST::TupleIndexExpr &expr) override
diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h
index f17b2226a40..ce7234ca1a1 100644
--- a/gcc/rust/resolve/rust-ast-resolve-implitem.h
+++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h
@@ -49,6 +49,13 @@ public:
     item->accept_vis (resolver);
   }
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::TypeAlias &type) override
   {
     auto decl
@@ -137,6 +144,13 @@ public:
     item->accept_vis (resolver);
   };
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::TraitItemFunc &function) override
   {
     auto decl = ResolveTraitItemFunctionToCanonicalPath::resolve (function);
@@ -240,6 +254,13 @@ public:
     item->accept_vis (resolver);
   };
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::ExternalFunctionItem &function) override
   {
     auto decl = CanonicalPath::new_seg (function.get_node_id (),
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index 5d32c0022d0..48f93e53487 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -45,6 +45,13 @@ public:
     item->accept_vis (resolver);
   };
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::TraitItemType &type) override
   {
     auto decl = ResolveTraitItemTypeToCanonicalPath::resolve (type);
@@ -227,6 +234,13 @@ public:
     item->accept_vis (resolver);
   };
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::TypeAlias &alias) override
   {
     auto talias = CanonicalPath::new_seg (alias.get_node_id (),
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index 3afed532afa..7521739b884 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -44,6 +44,14 @@ public:
     stmt->accept_vis (resolver);
   };
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::ExprStmtWithBlock &stmt) override
   {
     ResolveExpr::go (stmt.get_expr ().get (), stmt.get_node_id (), prefix,
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 7aba67fe7e7..39d6818427a 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -43,6 +43,13 @@ public:
     item->accept_vis (resolver);
   };
 
+  void visit (AST::MacroInvocationSemi &invoc) override
+  {
+    AST::ASTFragment &fragment = invoc.get_fragment ();
+    for (auto &node : fragment.get_nodes ())
+      node.accept_vis (*this);
+  }
+
   void visit (AST::Module &module) override
   {
     auto mod
diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h
index 0bcc6c81064..53daa42dadf 100644
--- a/gcc/rust/typecheck/rust-tycheck-dump.h
+++ b/gcc/rust/typecheck/rust-tycheck-dump.h
@@ -57,6 +57,12 @@ public:
       += indent () + "union " + type_string (union_decl.get_mappings ()) + "\n";
   }
 
+  void visit (HIR::TupleStruct &struct_decl) override
+  {
+    dump += indent () + "struct" + type_string (struct_decl.get_mappings ())
+	    + "\n";
+  }
+
   void visit (HIR::ImplBlock &impl_block) override
   {
     dump += indent () + "impl "
diff --git a/gcc/testsuite/rust/execute/torture/macros6.rs b/gcc/testsuite/rust/execute/torture/macros6.rs
new file mode 100644
index 00000000000..652a765d5a8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros6.rs
@@ -0,0 +1,12 @@
+macro_rules! Test {
+    ($a:ident, $b:ty) => {
+        struct $a($b);
+    };
+}
+
+Test!(Foo, i32);
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.0 - 123
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-08 12:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 12:08 [gcc/devel/rust/master] Semicolon based macro invocation Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).