aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast.h170
-rw-r--r--gcc/rust/ast/rust-macro.h129
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc127
-rw-r--r--gcc/rust/expand/rust-macro-expand.h25
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.h20
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h10
-rw-r--r--gcc/rust/hir/rust-ast-lower-stmt.h10
-rw-r--r--gcc/rust/parse/rust-parse-impl.h20
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h7
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-implitem.h21
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h14
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h8
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h7
-rw-r--r--gcc/rust/typecheck/rust-tycheck-dump.h6
-rw-r--r--gcc/testsuite/rust/execute/torture/macros6.rs12
15 files changed, 430 insertions, 156 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 3e7faf5..e72937e 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 1e95ebe..b5370d8 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 bce5246..dcfec7c 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 0f13f9e..d8a2d50 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 c9dfd1b..3d10b70 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 d4b5910..30bd896 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 ede72bd..b25246a 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 2ea42c7..784e6d1 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 4ccb72b..bb1cbb0 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 f17b222..ce7234c 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 5d32c00..48f93e5 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 3afed53..7521739 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 7aba67f..39d6818 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 0bcc6c8..53daa42 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 0000000..652a765
--- /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
+}