diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 59 | ||||
-rw-r--r-- | gcc/rust/expand/rust-attribute-visitor.cc | 219 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 16 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/macro40.rs | 48 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/macros28.rs | 13 |
6 files changed, 344 insertions, 12 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index a22c2d1..5817a0e 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1515,6 +1515,7 @@ public: TRAIT, IMPL, TRAIT_IMPL, + TYPE, }; private: @@ -1528,6 +1529,7 @@ private: std::unique_ptr<TraitItem> trait_item; std::unique_ptr<InherentImplItem> impl_item; std::unique_ptr<TraitImplItem> trait_impl_item; + std::unique_ptr<Type> type; public: SingleASTNode (std::unique_ptr<Expr> expr) @@ -1558,6 +1560,10 @@ public: : kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item)) {} + SingleASTNode (std::unique_ptr<Type> type) + : kind (TYPE), type (std::move (type)) + {} + SingleASTNode (SingleASTNode const &other) { kind = other.kind; @@ -1590,6 +1596,10 @@ public: case TRAIT_IMPL: trait_impl_item = other.trait_impl_item->clone_trait_impl_item (); break; + + case TYPE: + type = other.type->clone_type (); + break; } } @@ -1625,6 +1635,10 @@ public: case TRAIT_IMPL: trait_impl_item = other.trait_impl_item->clone_trait_impl_item (); break; + + case TYPE: + type = other.type->clone_type (); + break; } return *this; } @@ -1699,6 +1713,12 @@ public: return std::move (trait_impl_item); } + std::unique_ptr<Type> take_type () + { + rust_assert (!is_error ()); + return std::move (type); + } + void accept_vis (ASTVisitor &vis) { switch (kind) @@ -1730,6 +1750,10 @@ public: case TRAIT_IMPL: trait_impl_item->accept_vis (vis); break; + + case TYPE: + type->accept_vis (vis); + break; } } @@ -1751,6 +1775,8 @@ public: return impl_item == nullptr; case TRAIT_IMPL: return trait_impl_item == nullptr; + case TYPE: + return type == nullptr; } gcc_unreachable (); @@ -1774,7 +1800,9 @@ public: case IMPL: return "Impl Item: " + impl_item->as_string (); case TRAIT_IMPL: - return "Trait Impl Item: " + impl_item->as_string (); + return "Trait Impl Item: " + trait_impl_item->as_string (); + case TYPE: + return "Type: " + type->as_string (); } gcc_unreachable (); @@ -1799,6 +1827,18 @@ private: std::vector<SingleASTNode> nodes; bool fragment_is_error; + /** + * We need to make a special case for Expression and Type fragments as only + * one Node will be extracted from the `nodes` vector + */ + + bool is_single_fragment () const { return nodes.size () == 1; } + + bool is_single_fragment_kind (SingleASTNode::NodeType kind) const + { + return is_single_fragment () && nodes[0].get_kind () == kind; + } + public: ASTFragment (std::vector<SingleASTNode> nodes, bool fragment_is_error = false) : nodes (std::move (nodes)), fragment_is_error (fragment_is_error) @@ -1839,21 +1879,16 @@ public: bool should_expand () const { return !is_error () && !nodes.empty (); } - /** - * We need to make a special case for Expression fragments as only one - * Node will be extracted from the `nodes` vector - */ - - bool is_expression_fragment () const + std::unique_ptr<Expr> take_expression_fragment () { - return nodes.size () == 1 - && nodes[0].get_kind () == SingleASTNode::NodeType::EXPRESSION; + rust_assert (is_single_fragment_kind (SingleASTNode::NodeType::EXPRESSION)); + return nodes[0].take_expr (); } - std::unique_ptr<Expr> take_expression_fragment () + std::unique_ptr<Type> take_type_fragment () { - rust_assert (is_expression_fragment ()); - return nodes[0].take_expr (); + rust_assert (is_single_fragment_kind (SingleASTNode::NodeType::TYPE)); + return nodes[0].take_type (); } void accept_vis (ASTVisitor &vis) diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc index 8f2a6c7..859ae7e 100644 --- a/gcc/rust/expand/rust-attribute-visitor.cc +++ b/gcc/rust/expand/rust-attribute-visitor.cc @@ -35,13 +35,22 @@ AttrVisitor::expand_struct_fields (std::vector<AST::StructField> &fields) continue; } + expander.push_context (MacroExpander::ContextType::TYPE); + // expand sub-types of type, but can't strip type itself auto &type = field.get_field_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + // if nothing else happens, increment ++it; } @@ -77,6 +86,8 @@ AttrVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields) void AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> ¶ms) { + expander.push_context (MacroExpander::ContextType::TYPE); + for (auto it = params.begin (); it != params.end ();) { auto ¶m = *it; @@ -98,6 +109,11 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> ¶ms) auto &type = param.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -105,27 +121,40 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> ¶ms) // increment ++it; } + + expander.pop_context (); } void AttrVisitor::expand_generic_args (AST::GenericArgs &args) { // lifetime args can't be expanded + // FIXME: Can we have macro invocations for lifetimes? + + expander.push_context (MacroExpander::ContextType::TYPE); // expand type args - strip sub-types only for (auto &type : args.get_type_args ()) { type->accept_vis (*this); + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); } + expander.pop_context (); + + // FIXME: Can we have macro invocations in generic type bindings? // expand binding args - strip sub-types only for (auto &binding : args.get_binding_args ()) { auto &type = binding.get_type (); type->accept_vis (*this); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -135,8 +164,17 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args) void AttrVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = path_type.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + + expander.pop_context (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -174,11 +212,19 @@ AttrVisitor::AttrVisitor::expand_closure_params ( if (param.has_type_given ()) { + expander.push_context (MacroExpander::ContextType::TYPE); auto &type = param.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } // increment if found nothing else so far @@ -191,11 +237,19 @@ AttrVisitor::expand_self_param (AST::SelfParam &self_param) { if (self_param.has_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); auto &type = self_param.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } /* TODO: maybe check for invariants being violated - e.g. both type and * lifetime? */ @@ -222,11 +276,20 @@ AttrVisitor::expand_trait_function_decl (AST::TraitFunctionDecl &decl) if (decl.has_return_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &return_type = decl.get_return_type (); return_type->accept_vis (*this); + + auto r_fragment = expander.take_expanded_fragment (*this); + if (r_fragment.should_expand ()) + return_type = r_fragment.take_type_fragment (); + if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } if (decl.has_where_clause ()) @@ -251,11 +314,20 @@ AttrVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl) if (decl.has_return_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &return_type = decl.get_return_type (); return_type->accept_vis (*this); + + auto r_fragment = expander.take_expanded_fragment (*this); + if (r_fragment.should_expand ()) + return_type = r_fragment.take_type_fragment (); + if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } if (decl.has_where_clause ()) @@ -368,11 +440,20 @@ AttrVisitor::visit (AST::TypePathSegmentFunction &segment) if (type_path_function.has_return_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &return_type = type_path_function.get_return_type (); return_type->accept_vis (*this); + + auto r_fragment = expander.take_expanded_fragment (*this); + if (r_fragment.should_expand ()) + return_type = r_fragment.take_type_fragment (); + if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } } void @@ -1176,12 +1257,21 @@ AttrVisitor::visit (AST::ClosureExprInnerTyped &expr) * allowed by spec */ expand_closure_params (expr.get_params ()); + expander.push_context (MacroExpander::ContextType::TYPE); + // can't strip return type, but can strip sub-types auto &type = expr.get_return_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + // can't strip expression itself, but can strip sub-expressions auto &definition_block = expr.get_definition_block (); definition_block->accept_vis (*this); @@ -1928,11 +2018,19 @@ AttrVisitor::visit (AST::TypeParam ¶m) if (param.has_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); auto &type = param.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } } void @@ -1945,11 +2043,20 @@ AttrVisitor::visit (AST::TypeBoundWhereClauseItem &item) { // for lifetimes shouldn't require + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = item.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + // don't strip directly, only components of bounds for (auto &bound : item.get_type_param_bounds ()) bound->accept_vis (*this); @@ -1980,11 +2087,20 @@ AttrVisitor::visit (AST::Method &method) if (method.has_return_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &return_type = method.get_return_type (); return_type->accept_vis (*this); + + auto r_fragment = expander.take_expanded_fragment (*this); + if (r_fragment.should_expand ()) + return_type = r_fragment.take_type_fragment (); + if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } if (method.has_where_clause ()) @@ -2093,11 +2209,20 @@ AttrVisitor::visit (AST::Function &function) if (function.has_return_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &return_type = function.get_return_type (); return_type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + return_type = t_fragment.take_type_fragment (); + if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } if (function.has_where_clause ()) @@ -2297,12 +2422,21 @@ AttrVisitor::visit (AST::ConstantItem &const_item) return; } + expander.push_context (MacroExpander::ContextType::TYPE); + // strip any sub-types auto &type = const_item.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ @@ -2324,12 +2458,21 @@ AttrVisitor::visit (AST::StaticItem &static_item) return; } + expander.push_context (MacroExpander::ContextType::TYPE); + // strip any sub-types auto &type = static_item.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ @@ -2403,12 +2546,21 @@ AttrVisitor::visit (AST::TraitItemConst &item) return; } + expander.push_context (MacroExpander::ContextType::TYPE); + // strip any sub-types auto &type = item.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped */ @@ -2502,11 +2654,20 @@ AttrVisitor::visit (AST::InherentImpl &impl) for (auto ¶m : impl.get_generic_params ()) param->accept_vis (*this); + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = impl.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); @@ -2539,11 +2700,20 @@ AttrVisitor::visit (AST::TraitImpl &impl) for (auto ¶m : impl.get_generic_params ()) param->accept_vis (*this); + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = impl.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + auto &trait_path = impl.get_trait_path (); visit (trait_path); if (trait_path.is_marked_for_strip ()) @@ -2571,10 +2741,19 @@ AttrVisitor::visit (AST::ExternalStaticItem &item) return; } + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = item.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } void AttrVisitor::visit (AST::ExternalFunctionItem &item) @@ -2606,12 +2785,21 @@ AttrVisitor::visit (AST::ExternalFunctionItem &item) continue; } + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = param.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + // increment if nothing else happens ++it; } @@ -2624,16 +2812,26 @@ AttrVisitor::visit (AST::ExternalFunctionItem &item) if (item.has_return_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &return_type = item.get_return_type (); return_type->accept_vis (*this); + + auto r_fragment = expander.take_expanded_fragment (*this); + if (r_fragment.should_expand ()) + return_type = r_fragment.take_type_fragment (); + if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } if (item.has_where_clause ()) expand_where_clause (item.get_where_clause ()); } + void AttrVisitor::visit (AST::ExternBlock &block) { @@ -2991,11 +3189,20 @@ AttrVisitor::visit (AST::LetStmt &stmt) // similar for type if (stmt.has_type ()) { + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = stmt.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + + expander.pop_context (); } /* strip any internal sub-expressions - expression itself isn't @@ -3190,12 +3397,21 @@ AttrVisitor::visit (AST::BareFunctionType &type) continue; } + expander.push_context (MacroExpander::ContextType::TYPE); + auto &type = param.get_type (); type->accept_vis (*this); + + auto t_fragment = expander.take_expanded_fragment (*this); + if (t_fragment.should_expand ()) + type = t_fragment.take_type_fragment (); + if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); + expander.pop_context (); + // increment if nothing else happens ++it; } @@ -3205,6 +3421,9 @@ AttrVisitor::visit (AST::BareFunctionType &type) if (type.has_return_type ()) { + // FIXME: Can we have type expansion in this position? + // In that case, we need to handle AST::TypeNoBounds on top of just + // AST::Types auto &return_type = type.get_return_type (); return_type->accept_vis (*this); if (return_type->is_marked_for_strip ()) diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 2620fea..852e619 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -909,6 +909,19 @@ transcribe_expression (Parser<MacroInvocLexer> &parser) return {AST::SingleASTNode (std::move (expr))}; } +/** + * Transcribe one type from a macro invocation + * + * @param parser Parser to extract statements from + */ +static std::vector<AST::SingleASTNode> +transcribe_type (Parser<MacroInvocLexer> &parser) +{ + auto expr = parser.parse_type (); + + 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) @@ -957,6 +970,9 @@ transcribe_context (MacroExpander::ContextType ctx, case MacroExpander::ContextType::EXTERN: return transcribe_many_ext (parser, last_token_id); break; + case MacroExpander::ContextType::TYPE: + return transcribe_type (parser); + break; default: return transcribe_on_delimiter (parser, semicolon, delimiter, last_token_id); diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index f08525f..3cac617 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -188,6 +188,7 @@ struct MacroExpander ITEM, BLOCK, EXTERN, + TYPE, TRAIT, IMPL, TRAIT_IMPL, diff --git a/gcc/testsuite/rust/compile/macro40.rs b/gcc/testsuite/rust/compile/macro40.rs new file mode 100644 index 0000000..7151f3a --- /dev/null +++ b/gcc/testsuite/rust/compile/macro40.rs @@ -0,0 +1,48 @@ +// { dg-additional-options "-w" } + +macro_rules! t { + () => { + i32 + }; +} + +macro_rules! s { + () => { + *const i8 + }; +} + +extern "C" { + fn printf(s: s!(), ...); +} + +fn square(arg: t!()) -> t!() { + let input: t!() = arg; + + input * input +} + +trait Trait { + fn f() -> t!(); + fn g(arg: t!()); +} + +struct Wrapper { + inner: t!(), +} + +impl Trait for Wrapper { + fn f() -> t!() { + 1 + } + + fn g(arg: t!()) {} +} + +fn id<T>(arg: T) -> T { + arg +} + +fn main() { + id::<t!()>(15); +} diff --git a/gcc/testsuite/rust/execute/torture/macros28.rs b/gcc/testsuite/rust/execute/torture/macros28.rs new file mode 100644 index 0000000..b011f92 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/macros28.rs @@ -0,0 +1,13 @@ +macro_rules! t { + () => { + i32 + }; +} + +fn id<T>(arg: T) -> T { + arg +} + +fn main() -> i32 { + id::<t!()>(15) - 15 +} |