From: Pierre-Emmanuel Patry Date: Sun, 21 May 2023 16:13:34 +0000 (+0200) Subject: gccrs: expand: Add derive proc macro draft X-Git-Tag: basepoints/gcc-15~2480 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ac118445077fca5153730740d7233b055821746;p=thirdparty%2Fgcc.git gccrs: expand: Add derive proc macro draft Add a first draft for derive proc macros based on the attribute expander code. Convert the result back to a parsable entity and parse it. The procedural macro expander was beginning to require almost all functionalities already provided by the macro expander, hence the merge. gcc/rust/ChangeLog: * ast/rust-ast-collector.h: Update enum name to match definition. * expand/rust-expand-visitor.cc (ExpandVisitor::expand_derive): Add call to expander. (ExpandVisitor::expand_outer_attribute): Change call to macro expander. (ExpandVisitor::expand_inner_attribute): Likewise. * expand/rust-expand-visitor.h: Remove const attribute to match visitor declaration. Attach result to the AST. Add condition for item erasure. * expand/rust-proc-macro.h: Add token collector and expansion call. Add lexers and parsers for each proc macro type and uses them to parse macro output. * expand/rust-macro-expand.h (struct MacroExpander): Add functions. * expand/rust-proc-macro.cc (ProcMacroExpander::import_proc_macros): Moved from here... * expand/rust-macro-expand.cc (MacroExpander::import_proc_macros): ... to here. Unify procedural macro parsing under one function. Add a flag to determine whether it originate from a derive macro. (MacroExpander::parse_procmacro_output): Parse macro output to statements. Store an error on parsing failure. * Make-lang.in: Add const_TokenPtr specific lexer. * expand/rust-proc-macro-invoc-lexer.cc: New file. * expand/rust-proc-macro-invoc-lexer.h: New file. * rust-session-manager.cc (Session::expansion): Remove ProcMacroExpander declaration. * ast/rust-ast-fragment.cc (Fragment::Fragment): Add overwrite flag. (Fragment::should_overwrite): Add a getter to determine whether the fragment shall overwrite it's parent or be appended after. * ast/rust-ast-fragment.h: Add flag to declaration. Signed-off-by: Pierre-Emmanuel Patry --- diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 2f1807912fc3..939fa6419b27 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -93,6 +93,7 @@ GRS_OBJS = \ rust/rust-derive-copy.o \ rust/rust-proc-macro.o \ rust/rust-macro-invoc-lexer.o \ + rust/rust-proc-macro-invoc-lexer.o \ rust/rust-macro-substitute-ctx.o \ rust/rust-macro-builtins.o \ rust/rust-hir.o \ diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index 91e49ca14962..feb6c47f4e98 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -231,7 +231,7 @@ public: void visit (EnumItemTuple &item); void visit (EnumItemStruct &item); void visit (EnumItemDiscriminant &item); - void visit (Enum &enum_item); + void visit (Enum &enumeration); void visit (Union &union_item); void visit (ConstantItem &const_item); void visit (StaticItem &static_item); diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc index 22d2e6307488..e5d0ccef9d4d 100644 --- a/gcc/rust/ast/rust-ast-fragment.cc +++ b/gcc/rust/ast/rust-ast-fragment.cc @@ -23,7 +23,8 @@ namespace AST { Fragment::Fragment (FragmentKind kind, std::vector nodes, std::vector> tokens) - : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens)) + : kind (kind), nodes (std::move (nodes)), tokens (std::move (tokens)), + overwrite (true) {} Fragment::Fragment (Fragment const &other) : kind (other.get_kind ()) @@ -46,6 +47,8 @@ Fragment::operator= (Fragment const &other) for (auto &t : other.tokens) tokens.emplace_back (t->clone_token ()); + overwrite = other.overwrite; + return *this; } @@ -56,14 +59,15 @@ Fragment::create_error () } Fragment::Fragment (std::vector nodes, - std::vector> tokens) + std::vector> tokens, + bool overwrite) : kind (FragmentKind::Complete), nodes (std::move (nodes)), - tokens (std::move (tokens)) + tokens (std::move (tokens)), overwrite (overwrite) {} Fragment::Fragment (std::vector nodes, std::unique_ptr token) - : kind (FragmentKind::Complete), nodes (std::move (nodes)) + : kind (FragmentKind::Complete), nodes (std::move (nodes)), overwrite (true) { tokens.emplace_back (std::move (token)); } @@ -98,6 +102,12 @@ Fragment::should_expand () const return !is_error (); } +bool +Fragment::should_overwrite () const +{ + return overwrite; +} + bool Fragment::is_expression_fragment () const { diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h index e74632ae0556..fe1895f920cb 100644 --- a/gcc/rust/ast/rust-ast-fragment.h +++ b/gcc/rust/ast/rust-ast-fragment.h @@ -64,7 +64,8 @@ public: * Create a complete AST fragment */ Fragment (std::vector nodes, - std::vector> tokens); + std::vector> tokens, + bool overwrite = true); /** * Create a complete AST fragment made of a single token @@ -78,6 +79,7 @@ public: bool is_error () const; bool should_expand () const; + bool should_overwrite () const; bool is_expression_fragment () const; bool is_type_fragment () const; @@ -109,6 +111,12 @@ private: */ std::vector> tokens; + /** + * Whether the fragment should overwrite the original content. In most case + * it should overwrite it, but not with derive procedural macros. + */ + bool overwrite; + /** * We need to make a special case for Expression and Type fragments as only * one Node will be extracted from the `nodes` vector diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 04a899f14970..cb6c29933540 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -1553,7 +1553,7 @@ void ExpandVisitor::expand_outer_attribute (T &item, AST::SimplePath &path) { // FIXME: Retrieve path from segments + local use statements instead of string - proc_expander.expand_attribute_proc_macro (item, path); + expander.expand_attribute_proc_macro (item, path); } template @@ -1588,7 +1588,7 @@ void ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path) { // FIXME: Retrieve path from segments + local use statements instead of string - proc_expander.expand_attribute_proc_macro (item, path); + expander.expand_attribute_proc_macro (item, path); } template @@ -1621,15 +1621,15 @@ ExpandVisitor::visit_inner_attrs (T &item) template void -ExpandVisitor::expand_derive (const T &item, - std::unique_ptr &trait) +ExpandVisitor::expand_derive (T &item, std::unique_ptr trait) { - // FIXME: Implement expansion for that particular trait + auto trait_name = trait->as_string (); + expander.expand_derive_proc_macro (item, trait_name); } template void -ExpandVisitor::expand_derive (const T &item, AST::DelimTokenTree &attr) +ExpandVisitor::expand_derive (T &item, AST::DelimTokenTree &attr) { // Item is const because even though the tokenstream might be modified, it // should appear as the same input for every derive proc macro. @@ -1640,7 +1640,7 @@ ExpandVisitor::expand_derive (const T &item, AST::DelimTokenTree &attr) for (auto it = trees.begin () + 1; it < trees.end () - 1; it += 2 /* Increment + skip comma */) { - expand_derive (item, *it); + expand_derive (item, std::move (*it)); } } } diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index fd72d0b6771a..0dd5c9a21d19 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -40,9 +40,7 @@ is_builtin (AST::Attribute &attr); class ExpandVisitor : public AST::ASTVisitor { public: - ExpandVisitor (MacroExpander &expander, ProcMacroExpander &proc_expander) - : expander (expander), proc_expander (proc_expander) - {} + ExpandVisitor (MacroExpander &expander) : expander (expander) {} /* Expand all of the macro invocations currently contained in a crate */ void go (AST::Crate &crate); @@ -129,6 +127,8 @@ public: value->accept_vis (*this); auto final_fragment = expander.take_expanded_fragment (); + auto proc_macro_fragment + = expander.take_expanded_proc_macro_fragment (); // FIXME: Is that correct? It seems *extremely* dodgy if (final_fragment.should_expand ()) @@ -144,6 +144,22 @@ public: } } } + else if (proc_macro_fragment.should_expand ()) + { + if (proc_macro_fragment.should_overwrite ()) + it = values.erase (it); + else + it++; + for (auto &node : proc_macro_fragment.get_nodes ()) + { + auto new_node = extractor (node); + if (new_node != nullptr) + { + it = values.insert (it, std::move (new_node)); + it++; + } + } + } else { ++it; @@ -368,16 +384,14 @@ public: template void visit_inner_attrs (T &item); template - void expand_derive (const T &item, std::unique_ptr &trait); + void expand_derive (T &item, std::unique_ptr trait); - template - void expand_derive (const T &item, AST::DelimTokenTree &attr); + template void expand_derive (T &item, AST::DelimTokenTree &attr); template void visit_attrs_with_derive (T &item); private: MacroExpander &expander; - ProcMacroExpander &proc_expander; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 7229a09f2fe5..cb9f81669099 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -24,6 +24,8 @@ #include "rust-parse.h" #include "rust-cfg-strip.h" #include "rust-early-name-resolver.h" +#include "rust-session-manager.h" +#include "rust-proc-macro.h" namespace Rust { @@ -1049,4 +1051,92 @@ MacroExpander::transcribe_rule ( return fragment; } + +// TODO: Move to early name resolver ? +void +MacroExpander::import_proc_macros (std::string extern_crate) +{ + auto path = session.extern_crates.find (extern_crate); + if (path == session.extern_crates.end ()) + { + // Extern crate path is not available. + // FIXME: Emit error + rust_error_at (Location (), "Cannot find requested proc macro crate"); + gcc_unreachable (); + } + auto macros = load_macros (path->second); + + std::string prefix = extern_crate + "::"; + for (auto ¯o : macros) + { + switch (macro.tag) + { + case ProcMacro::CUSTOM_DERIVE: + rust_debug ("Found one derive proc macro."); + mappings->insert_derive_proc_macro ( + std::make_pair (extern_crate, + macro.payload.custom_derive.trait_name), + macro.payload.custom_derive); + break; + case ProcMacro::ATTR: + rust_debug ("Found one attribute proc macro."); + mappings->insert_attribute_proc_macro ( + std::make_pair (extern_crate, macro.payload.attribute.name), + macro.payload.attribute); + break; + case ProcMacro::BANG: + rust_debug ("Found one bang proc macro."); + mappings->insert_bang_proc_macro ( + std::make_pair (extern_crate, macro.payload.bang.name), + macro.payload.bang); + break; + default: + gcc_unreachable (); + } + } +} + +void +MacroExpander::parse_procmacro_output (ProcMacro::TokenStream ts, bool derive) +{ + ProcMacroInvocLexer lex (convert (ts)); + Parser parser (lex); + + std::vector nodes; + switch (peek_context ()) + { + case ContextType::ITEM: + while (lex.peek_token ()->get_id () != END_OF_FILE) + { + auto result = parser.parse_item (false); + if (result == nullptr) + break; + nodes.push_back ({std::move (result)}); + } + break; + case ContextType::BLOCK: + while (lex.peek_token ()->get_id () != END_OF_FILE) + { + auto result = parser.parse_stmt (); + if (result == nullptr) + break; + nodes.push_back ({std::move (result)}); + } + break; + case ContextType::TRAIT: + case ContextType::IMPL: + case ContextType::TRAIT_IMPL: + case ContextType::EXTERN: + case ContextType::TYPE: + default: + gcc_unreachable (); + } + + if (parser.has_errors ()) + set_expanded_proc_macro_fragment (AST::Fragment::create_error ()); + else + set_expanded_proc_macro_fragment ( + {nodes, std::vector> (), !derive}); +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index a24ec4f682c0..588b1c8461e6 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -28,6 +28,11 @@ #include "rust-early-name-resolver.h" #include "rust-name-resolver.h" #include "rust-macro-invoc-lexer.h" +#include "rust-proc-macro-invoc-lexer.h" +#include "rust-token-converter.h" +#include "rust-ast-collector.h" +#include "rust-system.h" +#include "libproc_macro/proc_macro.h" // Provides objects and method prototypes for macro expansion @@ -231,6 +236,7 @@ struct MacroExpander : cfg (cfg), crate (crate), session (session), sub_stack (SubstitutionScope ()), expanded_fragment (AST::Fragment::create_error ()), + expanded_proc_macro_fragment (AST::Fragment::create_error ()), has_changed_flag (false), resolver (Resolver::Resolver::get ()), mappings (Analysis::Mappings::get ()) {} @@ -332,6 +338,126 @@ struct MacroExpander return fragment; } + void set_expanded_proc_macro_fragment (AST::Fragment &&fragment) + { + if (!fragment.is_error ()) + has_changed_flag = true; + + expanded_proc_macro_fragment = std::move (fragment); + } + + AST::Fragment take_expanded_proc_macro_fragment () + { + auto fragment = std::move (expanded_proc_macro_fragment); + expanded_proc_macro_fragment = AST::Fragment::create_error (); + + return fragment; + } + + void import_proc_macros (std::string extern_crate); + + template + void expand_derive_proc_macro (T &item, std::string &trait_name) + { + ProcMacro::CustomDerive macro; + + // FIXME: Resolve crate name + std::string crate = ""; + std::string name = trait_name; + + if (!mappings->lookup_derive_proc_macro (std::make_pair (crate, name), + macro)) + { + // FIXME: Resolve this path segment instead of taking it directly. + import_proc_macros (crate); + if (!mappings->lookup_derive_proc_macro (std::make_pair (crate, name), + macro)) + { + rust_error_at (Location (), "procedural macro %s not found", + name.c_str ()); + rust_assert (false); + } + } + + std::vector tokens; + AST::TokenCollector collector (tokens); + + collector.visit (item); + + auto c = collector.collect_tokens (); + std::vector vec (c.cbegin (), c.cend ()); + + parse_procmacro_output (macro.macro (convert (vec)), true); + } + + template + void expand_bang_proc_macro (T &item, AST::SimplePath &path) + { + ProcMacro::Bang macro; + + std::string crate = path.get_segments ()[0].get_segment_name (); + std::string name = path.get_segments ()[1].get_segment_name (); + if (!mappings->lookup_bang_proc_macro (std::make_pair (crate, name), macro)) + { + // FIXME: Resolve this path segment instead of taking it directly. + import_proc_macros (crate); + + if (!mappings->lookup_bang_proc_macro (std::make_pair (crate, name), + macro)) + { + rust_error_at (Location (), "procedural macro %s not found", + name.c_str ()); + rust_assert (false); + } + } + + std::vector tokens; + AST::TokenCollector collector (tokens); + + collector.visit (item); + + auto c = collector.collect_tokens (); + std::vector vec (c.cbegin (), c.cend ()); + + parse_procmacro_output (macro.macro (convert (vec)), false); + } + + template + void expand_attribute_proc_macro (T &item, AST::SimplePath &path) + { + ProcMacro::Attribute macro; + + std::string crate = path.get_segments ()[0].get_segment_name (); + std::string name = path.get_segments ()[1].get_segment_name (); + if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name), + macro)) + { + // FIXME: Resolve this path segment instead of taking it directly. + import_proc_macros (crate); + if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, + name), + macro)) + { + rust_error_at (Location (), "procedural macro %s not found", + name.c_str ()); + rust_assert (false); + } + } + + std::vector tokens; + AST::TokenCollector collector (tokens); + + collector.visit (item); + + auto c = collector.collect_tokens (); + std::vector vec (c.cbegin (), c.cend ()); + + // FIXME: Handle attributes + parse_procmacro_output ( + macro.macro (ProcMacro::TokenStream::make_tokenstream (), convert (vec)), + false); + } + /** * Has the MacroExpander expanded a macro since its state was last reset? */ @@ -347,11 +473,14 @@ struct MacroExpander AST::MacroInvocation *get_last_invocation () { return last_invoc; } private: + void parse_procmacro_output (ProcMacro::TokenStream ts, bool derive); + AST::Crate &crate; Session &session; SubstitutionScope sub_stack; std::vector context; AST::Fragment expanded_fragment; + AST::Fragment expanded_proc_macro_fragment; bool has_changed_flag; AST::MacroRulesDefinition *last_def; diff --git a/gcc/rust/expand/rust-proc-macro-invoc-lexer.cc b/gcc/rust/expand/rust-proc-macro-invoc-lexer.cc new file mode 100644 index 000000000000..f365549bdc1c --- /dev/null +++ b/gcc/rust/expand/rust-proc-macro-invoc-lexer.cc @@ -0,0 +1,57 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-proc-macro-invoc-lexer.h" +#include "rust-token.h" + +namespace Rust { + +const_TokenPtr +ProcMacroInvocLexer::peek_token (int n) +{ + if ((offs + n) >= token_stream.size ()) + return Token::make (END_OF_FILE, Location ()); + + return token_stream.at (offs + n); +} + +// Advances current token to n + 1 tokens ahead of current position. +void +ProcMacroInvocLexer::skip_token (int n) +{ + offs += (n + 1); +} + +void +ProcMacroInvocLexer::split_current_token (TokenId new_left, TokenId new_right) +{ + auto ¤t_token = token_stream.at (offs); + auto current_pos = token_stream.begin () + offs; + + auto l_tok = Token::make (new_left, current_token->get_locus ()); + auto r_tok = Token::make (new_right, current_token->get_locus ()); + + token_stream.erase (current_pos); + + // `insert` inserts before the specified position, so we insert the right one + // then the left + token_stream.insert (current_pos, l_tok); + token_stream.insert (current_pos, r_tok); +} + +} // namespace Rust diff --git a/gcc/rust/expand/rust-proc-macro-invoc-lexer.h b/gcc/rust/expand/rust-proc-macro-invoc-lexer.h new file mode 100644 index 000000000000..7c047efb1f16 --- /dev/null +++ b/gcc/rust/expand/rust-proc-macro-invoc-lexer.h @@ -0,0 +1,64 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_PROC_MACRO_INVOC_LEXER_H +#define RUST_PROC_MACRO_INVOC_LEXER_H + +#include "rust-lex.h" + +namespace Rust { +class ProcMacroInvocLexer +{ +public: + ProcMacroInvocLexer (std::vector stream) + : offs (0), token_stream (std::move (stream)) + {} + + // Returns token n tokens ahead of current position. + const_TokenPtr peek_token (int n); + + // Peeks the current token. + const_TokenPtr peek_token () { return peek_token (0); } + + // Advances current token to n + 1 tokens ahead of current position. + void skip_token (int n); + + // Skips the current token. + void skip_token () { skip_token (0); } + + // Splits the current token into two. Intended for use with nested generics + // closes (i.e. T> where >> is wrongly lexed as one token). Note that + // this will only work with "simple" tokens like punctuation. + void split_current_token (TokenId new_left, TokenId new_right); + + std::string get_filename () const + { + // FIXME + gcc_unreachable (); + return "FIXME"; + } + + size_t get_offs () const { return offs; } + +private: + size_t offs; + std::vector token_stream; +}; +} // namespace Rust + +#endif /* ! RUST_PROC_MACRO_INVOC_LEXER_H */ diff --git a/gcc/rust/expand/rust-proc-macro.cc b/gcc/rust/expand/rust-proc-macro.cc index a53a5d87ab97..22744cb547d2 100644 --- a/gcc/rust/expand/rust-proc-macro.cc +++ b/gcc/rust/expand/rust-proc-macro.cc @@ -61,47 +61,4 @@ load_macros (std::string path) array->macros + array->length); } -void -ProcMacroExpander::import_proc_macros (std::string extern_crate) -{ - auto path = session.extern_crates.find (extern_crate); - if (path == session.extern_crates.end ()) - { - // Extern crate path is not available. - // FIXME: Emit error - rust_error_at (Location (), "Cannot find requested proc macro crate"); - gcc_unreachable (); - } - auto macros = load_macros (path->second); - - std::string prefix = extern_crate + "::"; - for (auto ¯o : macros) - { - switch (macro.tag) - { - case ProcMacro::CUSTOM_DERIVE: - rust_debug ("Found one derive proc macro."); - mappings->insert_derive_proc_macro ( - std::make_pair (extern_crate, - macro.payload.custom_derive.trait_name), - macro.payload.custom_derive); - break; - case ProcMacro::ATTR: - rust_debug ("Found one attribute proc macro."); - mappings->insert_attribute_proc_macro ( - std::make_pair (extern_crate, macro.payload.attribute.name), - macro.payload.attribute); - break; - case ProcMacro::BANG: - rust_debug ("Found one bang proc macro."); - mappings->insert_bang_proc_macro ( - std::make_pair (extern_crate, macro.payload.bang.name), - macro.payload.bang); - break; - default: - gcc_unreachable (); - } - } -} - } // namespace Rust diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h index 244d274773c3..7e9d7ecb609e 100644 --- a/gcc/rust/expand/rust-proc-macro.h +++ b/gcc/rust/expand/rust-proc-macro.h @@ -17,97 +17,17 @@ #ifndef RUST_PROC_MACRO_H #define RUST_PROC_MACRO_H -#include -#include "rust-hir-map.h" -#include "rust-name-resolver.h" -#include "rust-session-manager.h" -#include "rust-ast.h" -#include "rust-ast-collector.h" -#include "rust-token-converter.h" #include "libproc_macro/proc_macro.h" namespace Rust { - /** - * Load a procedural macro library and return a pointer to it's entrypoint. + * Load a procedural macro library and collect its entrypoints. * * @param The path to the shared object file to load. */ const std::vector load_macros (std::string path); -class ProcMacroExpander -{ -public: - ProcMacroExpander (Session &session) - : session (session), has_changed_flag (false), - resolver (Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()) - - {} - - ~ProcMacroExpander () = default; - - void import_proc_macros (std::string extern_crate); - - template - void expand_derive_proc_macro (T &item, std::string &trait_name) - {} - - template - void expand_bang_proc_macro (T &item, AST::SimplePath &path) - {} - - template - void expand_attribute_proc_macro (T &item, AST::SimplePath &path) - { - ProcMacro::Attribute macro; - - std::string crate = path.get_segments ()[0].get_segment_name (); - std::string name = path.get_segments ()[1].get_segment_name (); - if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name), - macro)) - { - // FIXME: Resolve this path segment instead of taking it directly. - import_proc_macros (crate); - } - - if (!mappings->lookup_attribute_proc_macro (std::make_pair (crate, name), - macro)) - { - rust_error_at (Location (), "procedural macro %s not found", - name.c_str ()); - rust_assert (false); - } - // FIXME: Attach result back to the ast - std::vector tokens; - AST::TokenCollector collector (tokens); - - collector.visit (item); - - std::vector vec; - for (auto i : collector.collect_tokens ()) - { - vec.push_back (std::const_pointer_cast (i)); - } - - // FIXME: Handle attributes - macro.macro (ProcMacro::TokenStream::make_tokenstream (), convert (vec)); - } - - bool has_changed () const { return has_changed_flag; } - - void reset_changed_state () { has_changed_flag = false; } - -private: - Session &session; - bool has_changed_flag; - -public: - Resolver::Resolver *resolver; - Analysis::Mappings *mappings; -}; - } // namespace Rust #endif /* ! RUST_PROC_MACRO_H */ diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 401d70590c46..c7bbe89b281c 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -867,13 +867,12 @@ Session::expansion (AST::Crate &crate) /* expand by calling cxtctxt object's monotonic_expander's expand_crate * method. */ MacroExpander expander (crate, cfg, *this); - ProcMacroExpander proc_expander (*this); while (!fixed_point_reached && iterations < cfg.recursion_limit) { CfgStrip ().go (crate); Resolver::EarlyNameResolver ().go (crate); - ExpandVisitor (expander, proc_expander).go (crate); + ExpandVisitor (expander).go (crate); fixed_point_reached = !expander.has_changed (); expander.reset_changed_state ();