diff options
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.cc')
| -rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 144 |
1 files changed, 107 insertions, 37 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index e86bfcb..b47e43a 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -19,15 +19,16 @@ #include "rust-macro-expand.h" #include "optional.h" #include "rust-ast-fragment.h" +#include "rust-macro-builtins.h" #include "rust-macro-substitute-ctx.h" #include "rust-ast-full.h" #include "rust-ast-visitor.h" #include "rust-diagnostics.h" +#include "rust-macro.h" #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" +#include "rust-token-tree-desugar.h" namespace Rust { @@ -78,7 +79,10 @@ MacroExpander::expand_decl_macro (location_t invoc_locus, * trees. */ - AST::DelimTokenTree &invoc_token_tree = invoc.get_delim_tok_tree (); + AST::DelimTokenTree &invoc_token_tree_sugar = invoc.get_delim_tok_tree (); + + // We must first desugar doc comments into proper attributes + auto invoc_token_tree = AST::TokenTreeDesugar ().go (invoc_token_tree_sugar); // find matching arm AST::MacroRule *matched_rule = nullptr; @@ -119,7 +123,7 @@ MacroExpander::expand_decl_macro (location_t invoc_locus, for (auto &ent : matched_fragments) matched_fragments_ptr.emplace (ent.first, ent.second.get ()); - return transcribe_rule (*matched_rule, invoc_token_tree, + return transcribe_rule (rules_def, *matched_rule, invoc_token_tree, matched_fragments_ptr, semicolon, peek_context ()); } @@ -283,6 +287,26 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, // lookup the rules auto rules_def = mappings.lookup_macro_invocation (invoc); + // We special case the `offset_of!()` macro if the flag is here and manually + // resolve to the builtin transcriber we have specified + auto assume_builtin_offset_of + = flag_assume_builtin_offset_of + && (invoc.get_invoc_data ().get_path ().as_string () == "offset_of") + && !rules_def; + + // TODO: This is *massive hack* which should be removed as we progress to + // Rust 1.71 when offset_of gets added to core + if (assume_builtin_offset_of) + { + fragment = MacroBuiltin::offset_of_handler (invoc.get_locus (), + invoc_data, semicolon) + .value_or (AST::Fragment::create_empty ()); + + set_expanded_fragment (std::move (fragment)); + + return; + } + // If there's no rule associated with the invocation, we can simply return // early. The early name resolver will have already emitted an error. if (!rules_def) @@ -426,7 +450,8 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser, parser.parse_visibility (); break; - case AST::MacroFragSpec::STMT: { + case AST::MacroFragSpec::STMT: + { auto restrictions = ParseRestrictions (); restrictions.consume_semi = false; parser.parse_stmt (restrictions); @@ -476,19 +501,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, // this is used so we can check that we delimit the stream correctly. switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!check_delim (AST::DelimType::PARENS)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!check_delim (AST::DelimType::SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!check_delim (AST::DelimType::CURLY)) return false; } @@ -506,7 +534,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); if (!match_fragment (parser, *fragment)) @@ -520,14 +549,16 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast<AST::Token *> (match.get ()); if (!match_token (parser, *tok)) return false; } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast<AST::MacroMatchRepetition *> (match.get ()); if (!match_repetition (parser, *rep)) @@ -535,7 +566,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast<AST::MacroMatcher *> (match.get ()); expansion_depth++; @@ -552,19 +584,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!parser.skip_token (RIGHT_PAREN)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!parser.skip_token (RIGHT_SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!parser.skip_token (RIGHT_CURLY)) return false; } @@ -613,7 +648,8 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, size_t offs_begin = source.get_offs (); switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); valid_current_match = match_fragment (parser, *fragment); @@ -621,26 +657,30 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, // matched fragment get the offset in the token stream size_t offs_end = source.get_offs (); - sub_stack.insert_metavar ( - MatchedFragment (fragment->get_ident ().as_string (), - offs_begin, offs_end)); + if (valid_current_match) + sub_stack.insert_metavar ( + MatchedFragment (fragment->get_ident ().as_string (), + offs_begin, offs_end)); } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast<AST::Token *> (match.get ()); valid_current_match = match_token (parser, *tok); } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast<AST::MacroMatchRepetition *> (match.get ()); valid_current_match = match_repetition (parser, *rep); } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast<AST::MacroMatcher *> (match.get ()); valid_current_match = match_matcher (parser, *m, true); @@ -650,15 +690,15 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, } auto old_stack = sub_stack.pop (); - // nest metavars into repetitions - for (auto &ent : old_stack) - sub_stack.append_fragment (ent.first, std::move (ent.second)); - // If we've encountered an error once, stop trying to match more // repetitions if (!valid_current_match) break; + // nest metavars into repetitions + for (auto &ent : old_stack) + sub_stack.append_fragment (ent.first, std::move (ent.second)); + match_amount++; // Break early if we notice there's too many expressions already @@ -920,8 +960,11 @@ transcribe_expression (Parser<MacroInvocLexer> &parser) auto &lexer = parser.get_token_source (); auto start = lexer.get_offs (); - auto expr = parser.parse_expr (); - if (expr == nullptr) + auto attrs = parser.parse_outer_attributes (); + auto expr = parser.parse_expr (std::move (attrs)); + for (auto error : parser.get_errors ()) + error.emit (); + if (!expr) return AST::Fragment::create_error (); // FIXME: make this an error for some edititons @@ -952,12 +995,38 @@ transcribe_type (Parser<MacroInvocLexer> &parser) auto type = parser.parse_type (true); for (auto err : parser.get_errors ()) err.emit (); + if (!type) + return AST::Fragment::create_error (); auto end = lexer.get_offs (); return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end)); } +/** + * Transcribe one pattern from a macro invocation + * + * @param parser Parser to extract statements from + */ +static AST::Fragment +transcribe_pattern (Parser<MacroInvocLexer> &parser) +{ + auto &lexer = parser.get_token_source (); + auto start = lexer.get_offs (); + + auto pattern = parser.parse_pattern (); + for (auto err : parser.get_errors ()) + err.emit (); + + if (!pattern) + return AST::Fragment::create_error (); + + auto end = lexer.get_offs (); + + return AST::Fragment ({std::move (pattern)}, + lexer.get_token_slice (start, end)); +} + static AST::Fragment transcribe_context (MacroExpander::ContextType ctx, Parser<MacroInvocLexer> &parser, bool semicolon, @@ -970,6 +1039,7 @@ transcribe_context (MacroExpander::ContextType ctx, // -- Trait --> parser.parse_trait_item(); // -- Impl --> parser.parse_impl_item(); // -- Extern --> parser.parse_extern_item(); + // -- Pattern --> parser.parse_pattern(); // -- None --> [has semicolon?] // -- Yes --> parser.parse_stmt(); // -- No --> [switch invocation.delimiter()] @@ -998,6 +1068,8 @@ transcribe_context (MacroExpander::ContextType ctx, break; case MacroExpander::ContextType::TYPE: return transcribe_type (parser); + case MacroExpander::ContextType::PATTERN: + return transcribe_pattern (parser); break; case MacroExpander::ContextType::STMT: return transcribe_many_stmts (parser, last_token_id, semicolon); @@ -1024,7 +1096,8 @@ tokens_to_str (std::vector<std::unique_ptr<AST::Token>> &tokens) AST::Fragment MacroExpander::transcribe_rule ( - AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree, + AST::MacroRulesDefinition &definition, AST::MacroRule &match_rule, + AST::DelimTokenTree &invoc_token_tree, std::map<std::string, MatchedFragmentContainer *> &matched_fragments, AST::InvocKind invoc_kind, ContextType ctx) { @@ -1039,7 +1112,8 @@ MacroExpander::transcribe_rule ( auto macro_rule_tokens = transcribe_tree.to_token_stream (); auto substitute_context - = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments); + = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments, + definition, invoc_token_tree.get_locus ()); std::vector<std::unique_ptr<AST::Token>> substituted_tokens = substitute_context.substitute_tokens (); @@ -1086,11 +1160,7 @@ MacroExpander::transcribe_rule ( // emit any errors if (parser.has_errors ()) - { - for (auto &err : parser.get_errors ()) - rust_error_at (err.locus, "%s", err.message.c_str ()); - return AST::Fragment::create_error (); - } + return AST::Fragment::create_error (); // are all the tokens used? bool did_delimit = parser.skip_token (last_token_id); @@ -1123,7 +1193,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts) auto result = parser.parse_item (false); if (result == nullptr) break; - nodes.push_back ({std::move (result)}); + nodes.emplace_back (std::move (result)); } break; case ContextType::STMT: @@ -1132,7 +1202,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts) auto result = parser.parse_stmt (); if (result == nullptr) break; - nodes.push_back ({std::move (result)}); + nodes.emplace_back (std::move (result)); } break; case ContextType::TRAIT: |
