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

https://gcc.gnu.org/g:73532817fd6f5aa4f59953f4111217a75135a78b

commit 73532817fd6f5aa4f59953f4111217a75135a78b
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Tue Mar 29 10:12:48 2022 +0200

    macros: Allow transcribing of zero items
    
    When expanding AST fragments containing multiple nodes, we must be aware
    that some cases allow expanding zero or more nodes. Any macro
    transcription that gets parsed as many nodes (ie any transcriber function that calls `parse_many`) needs to be able to parse zero of those nodes and still get expanded properly (basically, removed).
    
    Previously, this would cause a failure to lower the macro invocation which would remain as a child instead of getting stripped/erased.
    
    Co-authored-by: philberty <philip.herron@embecosm.com>

Diff:
---
 gcc/rust/ast/rust-ast.h                |  3 +--
 gcc/rust/ast/rust-macro.h              |  2 +-
 gcc/rust/expand/rust-macro-builtins.cc |  2 +-
 gcc/rust/expand/rust-macro-expand.cc   | 38 +++++++++++++++++-----------------
 gcc/rust/expand/rust-macro-expand.h    |  4 ++--
 gcc/testsuite/rust/compile/macro41.rs  | 13 ++++++++++++
 6 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 5817a0e8f84..785af818729 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1871,13 +1871,12 @@ public:
     return *this;
   }
 
-  static ASTFragment create_empty () { return ASTFragment ({}); }
   static ASTFragment create_error () { return ASTFragment ({}, true); }
 
   std::vector<SingleASTNode> &get_nodes () { return nodes; }
   bool is_error () const { return fragment_is_error; }
 
-  bool should_expand () const { return !is_error () && !nodes.empty (); }
+  bool should_expand () const { return !is_error (); }
 
   std::unique_ptr<Expr> take_expression_fragment ()
   {
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 1d922836c04..5ab82c4df7d 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -469,7 +469,7 @@ class MacroRulesDefinition : public MacroItem
   static ASTFragment dummy_builtin (Location, MacroInvocData &)
   {
     gcc_unreachable ();
-    return ASTFragment::create_empty ();
+    return ASTFragment::create_error ();
   }
 
   /* NOTE: in rustc, macro definitions are considered (and parsed as) a type
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 14f60d202cc..f9b8e302d09 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -141,7 +141,7 @@ MacroBuiltin::assert (Location invoc_locus, AST::MacroInvocData &invoc)
 {
   rust_debug ("assert!() called");
 
-  return AST::ASTFragment::create_empty ();
+  return AST::ASTFragment::create_error ();
 }
 
 AST::ASTFragment
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 852e61920f2..20bbbc07ffb 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -195,7 +195,7 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
   bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
   rust_assert (ok);
 
-  auto fragment = AST::ASTFragment::create_empty ();
+  auto fragment = AST::ASTFragment::create_error ();
 
   if (rules_def->is_builtin ())
     fragment
@@ -236,7 +236,7 @@ MacroExpander::expand_invoc_semi (AST::MacroInvocation &invoc)
   bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
   rust_assert (ok);
 
-  auto fragment = AST::ASTFragment::create_empty ();
+  auto fragment = AST::ASTFragment::create_error ();
 
   if (rules_def->is_builtin ())
     fragment
@@ -781,7 +781,7 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
 /**
  * Helper function to refactor calling a parsing function 0 or more times
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
 	    std::function<AST::SingleASTNode ()> parse_fn)
 {
@@ -795,7 +795,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
       nodes.emplace_back (std::move (node));
     }
 
-  return nodes;
+  return AST::ASTFragment (std::move (nodes));
 }
 
 /**
@@ -804,7 +804,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
  * @param parser Parser to extract items from
  * @param delimiter Id of the token on which parsing should stop
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
 {
   return parse_many (parser, delimiter, [&parser] () {
@@ -819,7 +819,7 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
  * @param parser Parser to extract items from
  * @param delimiter Id of the token on which parsing should stop
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
 {
   return parse_many (parser, delimiter, [&parser] () {
@@ -834,7 +834,7 @@ transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
  * @param parser Parser to extract items from
  * @param delimiter Id of the token on which parsing should stop
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
 			     TokenId &delimiter)
 {
@@ -850,7 +850,7 @@ transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
  * @param parser Parser to extract items from
  * @param delimiter Id of the token on which parsing should stop
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
 {
   return parse_many (parser, delimiter, [&parser] () {
@@ -865,7 +865,7 @@ transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
  * @param parser Parser to extract items from
  * @param delimiter Id of the token on which parsing should stop
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
 				  TokenId &delimiter)
 {
@@ -881,7 +881,7 @@ transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
  * @param parser Parser to extract statements from
  * @param delimiter Id of the token on which parsing should stop
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
 {
   auto restrictions = ParseRestrictions ();
@@ -901,12 +901,12 @@ transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
  *
  * @param parser Parser to extract statements from
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_expression (Parser<MacroInvocLexer> &parser)
 {
   auto expr = parser.parse_expr ();
 
-  return {AST::SingleASTNode (std::move (expr))};
+  return AST::ASTFragment ({std::move (expr)});
 }
 
 /**
@@ -914,15 +914,15 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
  *
  * @param parser Parser to extract statements from
  */
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_type (Parser<MacroInvocLexer> &parser)
 {
-  auto expr = parser.parse_type ();
+  auto type = parser.parse_type ();
 
-  return {AST::SingleASTNode (std::move (expr))};
+  return AST::ASTFragment ({std::move (type)});
 }
 
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
 			 AST::DelimType delimiter, TokenId last_token_id)
 {
@@ -932,7 +932,7 @@ transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
     return transcribe_expression (parser);
 } // namespace Rust
 
-static std::vector<AST::SingleASTNode>
+static AST::ASTFragment
 transcribe_context (MacroExpander::ContextType ctx,
 		    Parser<MacroInvocLexer> &parser, bool semicolon,
 		    AST::DelimType delimiter, TokenId last_token_id)
@@ -1049,7 +1049,7 @@ MacroExpander::transcribe_rule (
   //   as a statement (either via ExpressionStatement or
   //   MacroInvocationWithSemi)
 
-  auto nodes
+  auto fragment
     = transcribe_context (ctx, parser, semicolon,
 			  invoc_token_tree.get_delim_type (), last_token_id);
 
@@ -1072,6 +1072,6 @@ MacroExpander::transcribe_rule (
 		     "tokens here and after are unparsed");
     }
 
-  return AST::ASTFragment (std::move (nodes));
+  return fragment;
 }
 } // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 3cac61739a6..f3ca7fc876a 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -200,7 +200,7 @@ struct MacroExpander
   MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session)
     : cfg (cfg), crate (crate), session (session),
       sub_stack (SubstitutionScope ()),
-      expanded_fragment (AST::ASTFragment::create_empty ()),
+      expanded_fragment (AST::ASTFragment::create_error ()),
       resolver (Resolver::Resolver::get ()),
       mappings (Analysis::Mappings::get ())
   {}
@@ -295,7 +295,7 @@ struct MacroExpander
   AST::ASTFragment take_expanded_fragment (AST::ASTVisitor &vis)
   {
     AST::ASTFragment old_fragment = std::move (expanded_fragment);
-    expanded_fragment = AST::ASTFragment::create_empty ();
+    expanded_fragment = AST::ASTFragment::create_error ();
 
     for (auto &node : old_fragment.get_nodes ())
       {
diff --git a/gcc/testsuite/rust/compile/macro41.rs b/gcc/testsuite/rust/compile/macro41.rs
new file mode 100644
index 00000000000..38244222924
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro41.rs
@@ -0,0 +1,13 @@
+macro_rules! empty {
+    ($($t:tt)*) => {};
+}
+
+empty! {nothing}
+empty! {struct OuterItem;}
+empty! {}
+
+fn main() {
+    empty! {as statement};
+    empty! {any child item};
+    empty! {};
+}


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

only message in thread, other threads:[~2022-06-08 12:25 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:25 [gcc/devel/rust/master] macros: Allow transcribing of zero items 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).