aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand/rust-macro-expand.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.cc')
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc144
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: