aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast.h147
-rw-r--r--gcc/rust/ast/rust-macro.h6
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.cc60
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.h57
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc158
-rw-r--r--gcc/rust/expand/rust-macro-expand.h4
-rw-r--r--gcc/rust/parse/rust-parse-impl.h7
-rw-r--r--gcc/rust/parse/rust-parse.h8
-rw-r--r--gcc/testsuite/rust/compile/macro20.rs16
-rw-r--r--gcc/testsuite/rust/compile/macro21.rs9
-rw-r--r--gcc/testsuite/rust/compile/macro22.rs10
-rw-r--r--gcc/testsuite/rust/compile/macro23.rs25
-rw-r--r--gcc/testsuite/rust/execute/torture/macros23.rs19
13 files changed, 432 insertions, 94 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 3b96534..a22c2d1 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1511,18 +1511,51 @@ public:
EXPRESSION,
ITEM,
STMT,
+ EXTERN,
+ TRAIT,
+ IMPL,
+ TRAIT_IMPL,
};
+private:
+ NodeType kind;
+
+ // FIXME make this a union
+ std::unique_ptr<Expr> expr;
+ std::unique_ptr<Item> item;
+ std::unique_ptr<Stmt> stmt;
+ std::unique_ptr<ExternalItem> external_item;
+ std::unique_ptr<TraitItem> trait_item;
+ std::unique_ptr<InherentImplItem> impl_item;
+ std::unique_ptr<TraitImplItem> trait_impl_item;
+
+public:
SingleASTNode (std::unique_ptr<Expr> expr)
- : kind (EXPRESSION), expr (std::move (expr)), item (nullptr), stmt (nullptr)
+ : kind (EXPRESSION), expr (std::move (expr))
{}
SingleASTNode (std::unique_ptr<Item> item)
- : kind (ITEM), expr (nullptr), item (std::move (item)), stmt (nullptr)
+ : kind (ITEM), item (std::move (item))
{}
SingleASTNode (std::unique_ptr<Stmt> stmt)
- : kind (STMT), expr (nullptr), item (nullptr), stmt (std::move (stmt))
+ : kind (STMT), stmt (std::move (stmt))
+ {}
+
+ SingleASTNode (std::unique_ptr<ExternalItem> item)
+ : kind (EXTERN), external_item (std::move (item))
+ {}
+
+ SingleASTNode (std::unique_ptr<TraitItem> item)
+ : kind (TRAIT), trait_item (std::move (item))
+ {}
+
+ SingleASTNode (std::unique_ptr<InherentImplItem> item)
+ : kind (IMPL), impl_item (std::move (item))
+ {}
+
+ SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item)
+ : kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item))
{}
SingleASTNode (SingleASTNode const &other)
@@ -1541,6 +1574,22 @@ public:
case STMT:
stmt = other.stmt->clone_stmt ();
break;
+
+ case EXTERN:
+ external_item = other.external_item->clone_external_item ();
+ break;
+
+ case TRAIT:
+ trait_item = other.trait_item->clone_trait_item ();
+ break;
+
+ case IMPL:
+ impl_item = other.impl_item->clone_inherent_impl_item ();
+ break;
+
+ case TRAIT_IMPL:
+ trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
+ break;
}
}
@@ -1560,6 +1609,22 @@ public:
case STMT:
stmt = other.stmt->clone_stmt ();
break;
+
+ case EXTERN:
+ external_item = other.external_item->clone_external_item ();
+ break;
+
+ case TRAIT:
+ trait_item = other.trait_item->clone_trait_item ();
+ break;
+
+ case IMPL:
+ impl_item = other.impl_item->clone_inherent_impl_item ();
+ break;
+
+ case TRAIT_IMPL:
+ trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
+ break;
}
return *this;
}
@@ -1569,7 +1634,7 @@ public:
NodeType get_kind () const { return kind; }
- std::unique_ptr<Expr> &get_inner ()
+ std::unique_ptr<Expr> &get_expr ()
{
rust_assert (kind == EXPRESSION);
return expr;
@@ -1610,6 +1675,30 @@ public:
return std::move (item);
}
+ std::unique_ptr<TraitItem> take_trait_item ()
+ {
+ rust_assert (!is_error ());
+ return std::move (trait_item);
+ }
+
+ std::unique_ptr<ExternalItem> take_external_item ()
+ {
+ rust_assert (!is_error ());
+ return std::move (external_item);
+ }
+
+ std::unique_ptr<InherentImplItem> take_impl_item ()
+ {
+ rust_assert (!is_error ());
+ return std::move (impl_item);
+ }
+
+ std::unique_ptr<TraitImplItem> take_trait_impl_item ()
+ {
+ rust_assert (!is_error ());
+ return std::move (trait_impl_item);
+ }
+
void accept_vis (ASTVisitor &vis)
{
switch (kind)
@@ -1625,6 +1714,22 @@ public:
case STMT:
stmt->accept_vis (vis);
break;
+
+ case EXTERN:
+ external_item->accept_vis (vis);
+ break;
+
+ case TRAIT:
+ trait_item->accept_vis (vis);
+ break;
+
+ case IMPL:
+ impl_item->accept_vis (vis);
+ break;
+
+ case TRAIT_IMPL:
+ trait_impl_item->accept_vis (vis);
+ break;
}
}
@@ -1638,9 +1743,18 @@ public:
return item == nullptr;
case STMT:
return stmt == nullptr;
- default:
- return true;
+ case EXTERN:
+ return external_item == nullptr;
+ case TRAIT:
+ return trait_item == nullptr;
+ case IMPL:
+ return impl_item == nullptr;
+ case TRAIT_IMPL:
+ return trait_impl_item == nullptr;
}
+
+ gcc_unreachable ();
+ return true;
}
std::string as_string ()
@@ -1653,18 +1767,19 @@ public:
return "Item: " + item->as_string ();
case STMT:
return "Stmt: " + stmt->as_string ();
- default:
- return "";
+ case EXTERN:
+ return "External Item: " + external_item->as_string ();
+ case TRAIT:
+ return "Trait Item: " + trait_item->as_string ();
+ case IMPL:
+ return "Impl Item: " + impl_item->as_string ();
+ case TRAIT_IMPL:
+ return "Trait Impl Item: " + impl_item->as_string ();
}
- }
-private:
- NodeType kind;
-
- // FIXME make this a union
- std::unique_ptr<Expr> expr;
- std::unique_ptr<Item> item;
- std::unique_ptr<Stmt> stmt;
+ gcc_unreachable ();
+ return "";
+ }
};
/* Basically, a "fragment" that can be incorporated into the AST, created as
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 1c5d102..5ecd5d7 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -460,6 +460,7 @@ class MacroInvocation : public TypeNoBounds,
public TraitItem,
public TraitImplItem,
public InherentImplItem,
+ public ExternalItem,
public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
@@ -537,6 +538,11 @@ protected:
return clone_macro_invocation_impl ();
}
+ MacroInvocation *clone_external_item_impl () const final override
+ {
+ return clone_macro_invocation_impl ();
+ }
+
/*virtual*/ MacroInvocation *clone_macro_invocation_impl () const
{
return new MacroInvocation (*this);
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index 255e9ba..3de6608 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -1114,8 +1114,6 @@ AttrVisitor::visit (AST::ClosureExprInner &expr)
void
AttrVisitor::visit (AST::BlockExpr &expr)
{
- 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 ()))
@@ -1135,31 +1133,13 @@ AttrVisitor::visit (AST::BlockExpr &expr)
return;
}
- // strip all statements
- auto &stmts = expr.get_statements ();
- for (auto it = stmts.begin (); it != stmts.end ();)
- {
- auto &stmt = *it;
-
- stmt->accept_vis (*this);
+ std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor
+ = [] (AST::SingleASTNode node) { return node.take_stmt (); };
- auto fragment = expander.take_expanded_fragment (*this);
- if (fragment.should_expand ())
- {
- // Remove the current expanded invocation
- it = stmts.erase (it);
- for (auto &node : fragment.get_nodes ())
- {
- it = stmts.insert (it, node.take_stmt ());
- it++;
- }
- }
+ expand_macro_children (MacroExpander::BLOCK, expr.get_statements (),
+ extractor);
- else if (stmt->is_marked_for_strip ())
- it = stmts.erase (it);
- else
- it++;
- }
+ expander.push_context (MacroExpander::BLOCK);
// strip tail expression if exists - can actually fully remove it
if (expr.has_tail_expr ())
@@ -2489,8 +2469,11 @@ AttrVisitor::visit (AST::Trait &trait)
if (trait.has_where_clause ())
expand_where_clause (trait.get_where_clause ());
- // strip trait items if required
- expand_pointer_allow_strip (trait.get_trait_items ());
+ std::function<std::unique_ptr<AST::TraitItem> (AST::SingleASTNode)> extractor
+ = [] (AST::SingleASTNode node) { return node.take_trait_item (); };
+
+ expand_macro_children (MacroExpander::TRAIT, trait.get_trait_items (),
+ extractor);
}
void
AttrVisitor::visit (AST::InherentImpl &impl)
@@ -2523,8 +2506,11 @@ AttrVisitor::visit (AST::InherentImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- // strip inherent impl items if required
- expand_pointer_allow_strip (impl.get_impl_items ());
+ std::function<std::unique_ptr<AST::InherentImplItem> (AST::SingleASTNode)>
+ extractor = [] (AST::SingleASTNode node) { return node.take_impl_item (); };
+
+ expand_macro_children (MacroExpander::IMPL, impl.get_impl_items (),
+ extractor);
}
void
AttrVisitor::visit (AST::TraitImpl &impl)
@@ -2563,8 +2549,12 @@ AttrVisitor::visit (AST::TraitImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- // strip trait impl items if required
- expand_pointer_allow_strip (impl.get_impl_items ());
+ std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)>
+ extractor
+ = [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); };
+
+ expand_macro_children (MacroExpander::TRAIT_IMPL, impl.get_impl_items (),
+ extractor);
}
void
AttrVisitor::visit (AST::ExternalStaticItem &item)
@@ -2659,8 +2649,12 @@ AttrVisitor::visit (AST::ExternBlock &block)
return;
}
- // strip external items if required
- expand_pointer_allow_strip (block.get_extern_items ());
+ std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
+ extractor
+ = [] (AST::SingleASTNode node) { return node.take_external_item (); };
+
+ expand_macro_children (MacroExpander::EXTERN, block.get_extern_items (),
+ extractor);
}
// I don't think it would be possible to strip macros without expansion
diff --git a/gcc/rust/expand/rust-attribute-visitor.h b/gcc/rust/expand/rust-attribute-visitor.h
index f6327d6..6da6583 100644
--- a/gcc/rust/expand/rust-attribute-visitor.h
+++ b/gcc/rust/expand/rust-attribute-visitor.h
@@ -40,8 +40,24 @@ public:
void expand_trait_function_decl (AST::TraitFunctionDecl &decl);
void expand_trait_method_decl (AST::TraitMethodDecl &decl);
- template <typename T> void expand_pointer_allow_strip (T &values)
+ /**
+ * Expand a set of values, erasing them if they are marked for strip, and
+ * replacing them with expanded macro nodes if necessary.
+ * This function is slightly different from `expand_pointer_allow_strip` as
+ * it can only be called in certain expansion contexts - where macro
+ * invocations are allowed.
+ *
+ * @param ctx Context to use for macro expansion
+ * @param values Iterable reference over values to replace or erase
+ * @param extractor Function to call when replacing values with the content
+ * of an expanded AST node
+ */
+ template <typename T, typename U>
+ void expand_macro_children (MacroExpander::ContextType ctx, T &values,
+ std::function<U (AST::SingleASTNode)> extractor)
{
+ expander.push_context (ctx);
+
for (auto it = values.begin (); it != values.end ();)
{
auto &value = *it;
@@ -49,10 +65,45 @@ public:
// mark for stripping if required
value->accept_vis (*this);
+ auto fragment = expander.take_expanded_fragment (*this);
+ if (fragment.should_expand ())
+ {
+ it = values.erase (it);
+ for (auto &node : fragment.get_nodes ())
+ {
+ it = values.insert (it, extractor (node));
+ it++;
+ }
+ }
+ else if (value->is_marked_for_strip ())
+ {
+ it = values.erase (it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ expander.pop_context ();
+ }
+
+ template <typename T> void expand_pointer_allow_strip (T &values)
+ {
+ for (auto it = values.begin (); it != values.end ();)
+ {
+ auto &value = *it;
+
+ // mark for stripping if required
+ value->accept_vis (*this);
if (value->is_marked_for_strip ())
- it = values.erase (it);
+ {
+ it = values.erase (it);
+ }
else
- ++it;
+ {
+ ++it;
+ }
}
}
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 3389f20..3bdb8c6 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -786,7 +786,6 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
std::function<AST::SingleASTNode ()> parse_fn)
{
std::vector<AST::SingleASTNode> nodes;
-
while (true)
{
if (parser.peek_current_token ()->get_id () == delimiter)
@@ -815,6 +814,68 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
}
/**
+ * Transcribe 0 or more external items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_external_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
+ * Transcribe 0 or more trait items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
+ TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_trait_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
+ * Transcribe 0 or more impl items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_inherent_impl_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
+ * Transcribe 0 or more trait impl items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
+ TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_trait_impl_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
* Transcribe 0 or more statements from a macro invocation
*
* @param parser Parser to extract statements from
@@ -845,6 +906,60 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
return {AST::SingleASTNode (std::move (expr))};
}
+static std::vector<AST::SingleASTNode>
+transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
+ AST::DelimType delimiter, TokenId last_token_id)
+{
+ if (semicolon || delimiter == AST::DelimType::CURLY)
+ return transcribe_many_stmts (parser, last_token_id);
+ else
+ return transcribe_expression (parser);
+} // namespace Rust
+
+static std::vector<AST::SingleASTNode>
+transcribe_context (MacroExpander::ContextType ctx,
+ Parser<MacroInvocLexer> &parser, bool semicolon,
+ AST::DelimType delimiter, TokenId last_token_id)
+{
+ // The flow-chart in order to choose a parsing function is as follows:
+ //
+ // [switch special context]
+ // -- Item --> parser.parse_item();
+ // -- Trait --> parser.parse_trait_item();
+ // -- Impl --> parser.parse_impl_item();
+ // -- Extern --> parser.parse_extern_item();
+ // -- None --> [has semicolon?]
+ // -- Yes --> parser.parse_stmt();
+ // -- No --> [switch invocation.delimiter()]
+ // -- { } --> parser.parse_stmt();
+ // -- _ --> parser.parse_expr(); // once!
+
+ // If there is a semicolon OR we are expanding a MacroInvocationSemi, then
+ // we can parse multiple items. Otherwise, parse *one* expression
+
+ switch (ctx)
+ {
+ case MacroExpander::ContextType::ITEM:
+ return transcribe_many_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::TRAIT:
+ return transcribe_many_trait_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::IMPL:
+ return transcribe_many_impl_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::TRAIT_IMPL:
+ return transcribe_many_trait_impl_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::EXTERN:
+ return transcribe_many_ext (parser, last_token_id);
+ break;
+ default:
+ return transcribe_on_delimiter (parser, semicolon, delimiter,
+ last_token_id);
+ }
+}
+
AST::ASTFragment
MacroExpander::transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
@@ -864,18 +979,15 @@ MacroExpander::transcribe_rule (
std::vector<std::unique_ptr<AST::Token>> substituted_tokens
= substitute_context.substitute_tokens ();
+ // handy for debugging
+ // for (auto &tok : substituted_tokens)
+ // rust_debug ("[tok] %s", tok->as_string ().c_str ());
+
// parse it to an ASTFragment
MacroInvocLexer lex (std::move (substituted_tokens));
Parser<MacroInvocLexer> parser (std::move (lex));
- // handy for debugging
- // for (auto &tok : substituted_tokens)
- // {
- // rust_debug ("tok: [%s]", tok->as_string ().c_str ());
- // }
-
auto last_token_id = TokenId::RIGHT_CURLY;
- std::vector<AST::SingleASTNode> nodes;
// this is used so we can check that we delimit the stream correctly.
switch (transcribe_tree.get_delim_type ())
@@ -905,33 +1017,9 @@ MacroExpander::transcribe_rule (
// as a statement (either via ExpressionStatement or
// MacroInvocationWithSemi)
- // The flow-chart in order to choose a parsing function is as follows:
- //
- // [is in item context?]
- // -- Yes --> parser.parse_item();
- // -- No --> [has semicolon?]
- // -- Yes --> parser.parse_stmt();
- // -- No --> [switch invocation.delimiter()]
- // -- { } --> parser.parse_stmt();
- // -- _ --> parser.parse_expr();
-
- // If there is a semicolon OR we are expanding a MacroInvocationSemi, then
- // we can parse multiple items. Otherwise, parse *one* expression
-
- if (ctx == ContextType::ITEM)
- nodes = transcribe_many_items (parser, last_token_id);
- else if (semicolon)
- nodes = transcribe_many_stmts (parser, last_token_id);
- else
- switch (invoc_token_tree.get_delim_type ())
- {
- case AST::CURLY:
- nodes = transcribe_many_stmts (parser, last_token_id);
- break;
- default:
- nodes = transcribe_expression (parser);
- break;
- }
+ auto nodes
+ = transcribe_context (ctx, parser, semicolon,
+ invoc_token_tree.get_delim_type (), last_token_id);
// emit any errors
if (parser.has_errors ())
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 0d0282e..f08525f 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -187,6 +187,10 @@ struct MacroExpander
{
ITEM,
BLOCK,
+ EXTERN,
+ TRAIT,
+ IMPL,
+ TRAIT_IMPL,
};
ExpansionCfg cfg;
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 0bbd8fb..82e7e24 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5251,12 +5251,11 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
switch (t->get_id ())
{
case IDENTIFIER:
+ // FIXME: Arthur: Do we need to some lookahead here?
+ return parse_macro_invocation_semi (outer_attrs);
case SUPER:
case SELF:
case CRATE:
- case DOLLAR_SIGN:
- // these seem to be SimplePath tokens, so this is a macro invocation semi
- return parse_macro_invocation_semi (std::move (outer_attrs));
case PUB: {
// visibility, so not a macro invocation semi - must be constant,
// function, or method
@@ -5813,6 +5812,8 @@ Parser<ManagedTokenSource>::parse_external_item ()
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
+ case IDENTIFIER:
+ return parse_macro_invocation_semi (outer_attrs);
case STATIC_TOK: {
// parse extern static item
lexer.skip_token ();
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 5fcb305..5880616 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -135,6 +135,10 @@ public:
*/
std::unique_ptr<AST::Stmt> parse_stmt (bool allow_no_semi = false);
std::unique_ptr<AST::Type> parse_type ();
+ std::unique_ptr<AST::ExternalItem> parse_external_item ();
+ std::unique_ptr<AST::TraitItem> parse_trait_item ();
+ std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
+ std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
AST::PathInExpression parse_path_in_expression ();
std::vector<std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params ();
AST::Visibility parse_visibility ();
@@ -285,7 +289,6 @@ private:
AST::AttrVec outer_attrs);
std::unique_ptr<AST::Trait> parse_trait (AST::Visibility vis,
AST::AttrVec outer_attrs);
- std::unique_ptr<AST::TraitItem> parse_trait_item ();
std::unique_ptr<AST::TraitItemType>
parse_trait_type (AST::AttrVec outer_attrs);
std::unique_ptr<AST::TraitItemConst>
@@ -293,17 +296,14 @@ private:
AST::SelfParam parse_self_param ();
std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis,
AST::AttrVec outer_attrs);
- std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item ();
std::unique_ptr<AST::InherentImplItem>
parse_inherent_impl_function_or_method (AST::Visibility vis,
AST::AttrVec outer_attrs);
- std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item ();
std::unique_ptr<AST::TraitImplItem>
parse_trait_impl_function_or_method (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::ExternBlock>
parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs);
- std::unique_ptr<AST::ExternalItem> parse_external_item ();
AST::NamedFunctionParam parse_named_function_param (AST::AttrVec outer_attrs
= AST::AttrVec ());
AST::Method parse_method ();
diff --git a/gcc/testsuite/rust/compile/macro20.rs b/gcc/testsuite/rust/compile/macro20.rs
new file mode 100644
index 0000000..9f3cbca
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro20.rs
@@ -0,0 +1,16 @@
+macro_rules! define_trait {
+ ($assoc:ident, $i:item) => {
+ type $assoc;
+
+ $i
+ };
+}
+
+trait DefinedThroughMacros {
+ define_trait!(
+ Inner,
+ fn takes_inner(i: Self::Inner) -> Self::Inner {
+ i
+ }
+ );
+}
diff --git a/gcc/testsuite/rust/compile/macro21.rs b/gcc/testsuite/rust/compile/macro21.rs
new file mode 100644
index 0000000..9a1d773
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro21.rs
@@ -0,0 +1,9 @@
+macro_rules! c_fn {
+ {$name:ident ($($arg_name:ident $arg_ty:ty),*) -> $ret_ty:ty} => {
+ fn $name($($arg_name: $arg_ty)*) -> $ret_ty;
+ };
+}
+
+extern "C" {
+ c_fn! {puts (s *const i8) -> i64}
+}
diff --git a/gcc/testsuite/rust/compile/macro22.rs b/gcc/testsuite/rust/compile/macro22.rs
new file mode 100644
index 0000000..bdc4bad
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro22.rs
@@ -0,0 +1,10 @@
+macro_rules! print {
+ () => {
+ fn puts(s: *const i8);
+ fn printf(fmt: *const i8, ...);
+ };
+}
+
+extern "C" {
+ print! {}
+}
diff --git a/gcc/testsuite/rust/compile/macro23.rs b/gcc/testsuite/rust/compile/macro23.rs
new file mode 100644
index 0000000..afaca9b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro23.rs
@@ -0,0 +1,25 @@
+macro_rules! maybe_impl {
+ ($left:ident, $right:ident, $l_fn:ident, $r_fn:ident) => {
+ fn $l_fn(value: T) -> Maybe<T> {
+ Maybe::$left(value)
+ }
+
+ fn $r_fn() -> Maybe<T> {
+ Maybe::$right
+ }
+ };
+}
+
+enum Maybe<T> {
+ Just(T),
+ Nothing,
+}
+
+impl<T> Maybe<T> {
+ maybe_impl!(Just, Nothing, just, nothing);
+}
+
+fn main() {
+ let _ = Maybe::just(14);
+ let _: Maybe<i32> = Maybe::nothing();
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros23.rs b/gcc/testsuite/rust/execute/torture/macros23.rs
new file mode 100644
index 0000000..846352d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros23.rs
@@ -0,0 +1,19 @@
+trait Valuable {
+ const VALUE: i32;
+}
+
+struct Something;
+
+macro_rules! implement {
+ () => {
+ const VALUE: i32 = 18;
+ };
+}
+
+impl Valuable for Something {
+ implement!();
+}
+
+fn main() -> i32 {
+ Something::VALUE - 18
+}