aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-03-31 09:56:35 +0000
committerGitHub <noreply@github.com>2022-03-31 09:56:35 +0000
commit9011184f38a04f81ba3194b826bec3f30a11c07b (patch)
treed85ff3be8c56dfb9d27c64a856b3523e197b41f6
parentf9c1a14dab4c47c774f9c7661afc4bb2176eb9bb (diff)
parent73532817fd6f5aa4f59953f4111217a75135a78b (diff)
downloadgcc-9011184f38a04f81ba3194b826bec3f30a11c07b.zip
gcc-9011184f38a04f81ba3194b826bec3f30a11c07b.tar.gz
gcc-9011184f38a04f81ba3194b826bec3f30a11c07b.tar.bz2
Merge #1071
1071: Allow transcribing of zero nodes in certain cases r=CohenArthur a=CohenArthur 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: Arthur Cohen <arthur.cohen@embecosm.com>
-rw-r--r--gcc/rust/ast/rust-ast.h3
-rw-r--r--gcc/rust/ast/rust-macro.h2
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc2
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc38
-rw-r--r--gcc/rust/expand/rust-macro-expand.h4
-rw-r--r--gcc/testsuite/rust/compile/macro41.rs13
6 files changed, 37 insertions, 25 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 5817a0e..785af81 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 1d92283..5ab82c4 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 14f60d2..f9b8e30 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 852e619..20bbbc0 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 3cac617..f3ca7fc8 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 0000000..3824422
--- /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! {};
+}