From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id A93AA385B539; Thu, 12 Jan 2023 07:44:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A93AA385B539 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1673509479; bh=mfT3vpWYWm+13/IXiBS1FhypQ9qjXNkr2fHMJV0Cpxg=; h=From:To:Subject:Date:From; b=uHT/fj2BiJsuSGQNX1dPrxDGXlwd9RyeDxfQW4tfjEjXLrjW3/+oAPPFhoKLIUEnn PhydrGrxQWYs3VC2ENyJzGnJGd3IM1h44jFQ1Q8QXZHQSHZeLPypRyy2pPm5ZD8iZC d8UVCnWU7b/vFAMx80JQLd2xmQnzs5/hTCuotRwc= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Implement declarative macro 2.0 parser Signed-off-by: Raiki Tamura X-Act-Checkin: gcc X-Git-Author: Raiki Tamura X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 0152926ab36ba52153f3f457f6f3bb02bb274073 X-Git-Newrev: 9e5769cf45cfc703e807e51b3ad301e123b05b55 Message-Id: <20230112074439.A93AA385B539@sourceware.org> Date: Thu, 12 Jan 2023 07:44:39 +0000 (GMT) List-Id: https://gcc.gnu.org/g:9e5769cf45cfc703e807e51b3ad301e123b05b55 commit 9e5769cf45cfc703e807e51b3ad301e123b05b55 Author: Raiki Tamura Date: Mon Dec 19 01:48:54 2022 +0900 Implement declarative macro 2.0 parser Signed-off-by: Raiki Tamura Diff: --- gcc/rust/ast/rust-ast-full-decls.h | 1 - gcc/rust/ast/rust-ast-full-test.cc | 1 + gcc/rust/ast/rust-ast.h | 5 - gcc/rust/ast/rust-item.h | 2 - gcc/rust/ast/rust-macro.h | 65 ++++-- gcc/rust/lex/rust-token.h | 2 +- gcc/rust/parse/rust-parse-impl.h | 229 +++++++++++++++++----- gcc/rust/parse/rust-parse.h | 3 +- gcc/testsuite/rust/compile/decl_macro1.rs | 2 + gcc/testsuite/rust/compile/decl_macro2.rs | 2 + gcc/testsuite/rust/compile/decl_macro3.rs | 4 + gcc/testsuite/rust/compile/decl_macro4.rs | 5 + gcc/testsuite/rust/compile/decl_macro5.rs | 5 + gcc/testsuite/rust/compile/decl_macro6.rs | 5 + gcc/testsuite/rust/compile/decl_macro7.rs | 4 + gcc/testsuite/rust/execute/torture/decl_macro1.rs | 8 + gcc/testsuite/rust/execute/torture/decl_macro2.rs | 8 + gcc/testsuite/rust/execute/torture/decl_macro3.rs | 15 ++ gcc/testsuite/rust/execute/torture/decl_macro4.rs | 15 ++ 19 files changed, 301 insertions(+), 80 deletions(-) diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 47f332193cc..0927adb3bc2 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -51,7 +51,6 @@ class Lifetime; class GenericParam; class LifetimeParam; class ConstGenericParam; -class MacroItem; class TraitItem; class InherentImplItem; class TraitImplItem; diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index c4df7308350..c98df5106ef 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -1284,6 +1284,7 @@ MacroRulesDefinition::as_string () const // get outer attrs str += append_attributes (outer_attrs, OUTER); + // TODO: deal with macro_2_0 str += "macro_rules!"; str += rule_name; diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index fc7af58eed5..1539e78f01b 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1350,11 +1350,6 @@ protected: } }; -// A macro item AST node - abstract base class -class MacroItem : public Item -{ -}; - // Item used in trait declarations - abstract base class class TraitItem { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index b91aec0d3af..206887c01e6 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -4391,8 +4391,6 @@ protected: } }; -// Replaced with forward decls - defined in "rust-macro.h" -class MacroItem; class MacroRulesDefinition; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index fe95ce13312..52c7efb5d1b 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -23,13 +23,11 @@ #include "rust-ast.h" #include "rust-ast-fragment.h" #include "rust-location.h" +#include "rust-item.h" +#include "rust-make-unique.h" namespace Rust { namespace AST { - -// Decls as definitions moved to rust-ast.h -class MacroItem; - class MacroFragSpec { public: @@ -446,8 +444,18 @@ public: }; // A macro rules definition item AST node -class MacroRulesDefinition : public MacroItem +class MacroRulesDefinition : public VisItem { +public: + enum MacroKind + { + // Macro by Example (legacy macro rules) + MBE, + // Declarative macros 2.0 + DeclMacro, + }; + +private: std::vector outer_attrs; Identifier rule_name; // MacroRulesDef rules_def; @@ -460,6 +468,7 @@ class MacroRulesDefinition : public MacroItem std::function associated_transcriber; // Since we can't compare std::functions, we need to use an extra boolean bool is_builtin_rule; + MacroKind kind; /** * Default function to use as an associated transcriber. This function should @@ -479,27 +488,51 @@ class MacroRulesDefinition : public MacroItem * I am not aware of the implications of this decision. The rustc spec does * mention that using the same parser for macro definitions and invocations * is "extremely self-referential and non-intuitive". */ - -public: - std::string as_string () const override; - MacroRulesDefinition (Identifier rule_name, DelimType delim_type, std::vector rules, - std::vector outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)), + std::vector outer_attrs, Location locus, + MacroKind kind, Visibility vis) + : VisItem (std::move (vis), outer_attrs), + outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)), delim_type (delim_type), rules (std::move (rules)), locus (locus), - associated_transcriber (dummy_builtin), is_builtin_rule (false) + associated_transcriber (dummy_builtin), is_builtin_rule (false), + kind (kind) {} MacroRulesDefinition ( Identifier builtin_name, DelimType delim_type, - std::function associated_transcriber) - : outer_attrs (std::vector ()), rule_name (builtin_name), + std::function associated_transcriber, + MacroKind kind, Visibility vis) + : VisItem (std::move (vis), std::vector ()), + outer_attrs (std::vector ()), rule_name (builtin_name), delim_type (delim_type), rules (std::vector ()), locus (Location ()), associated_transcriber (associated_transcriber), - is_builtin_rule (true) + is_builtin_rule (true), kind (kind) {} +public: + std::string as_string () const override; + + static std::unique_ptr + mbe (Identifier rule_name, DelimType delim_type, std::vector rules, + std::vector outer_attrs, Location locus) + { + return Rust::make_unique ( + MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus, + AST::MacroRulesDefinition::MacroKind::MBE, + AST::Visibility::create_error ())); + } + + static std::unique_ptr + decl_macro (Identifier rule_name, std::vector rules, + std::vector outer_attrs, Location locus, + Visibility vis) + { + return Rust::make_unique (MacroRulesDefinition ( + rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus, + AST::MacroRulesDefinition::MacroKind::DeclMacro, vis)); + } + void accept_vis (ASTVisitor &vis) override; // Invalid if rule name is empty, so base stripping on that. @@ -549,7 +582,7 @@ protected: * compile time */ class MacroInvocation : public TypeNoBounds, public Pattern, - public MacroItem, + public Item, public TraitItem, public TraitImplItem, public InherentImplItem, diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 8f5be33a804..0ff208c4599 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -172,7 +172,7 @@ enum PrimitiveCoreType RS_TOKEN_KEYWORD (IN, "in") \ RS_TOKEN_KEYWORD (LET, "let") \ RS_TOKEN_KEYWORD (LOOP, "loop") \ - RS_TOKEN_KEYWORD (MACRO, "macro") /* unused */ \ + RS_TOKEN_KEYWORD (MACRO, "macro") \ RS_TOKEN_KEYWORD (MATCH_TOK, "match") \ RS_TOKEN_KEYWORD (MOD, "mod") \ RS_TOKEN_KEYWORD (MOVE, "move") \ diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 864fb86ce06..5f0ee02d52f 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1023,11 +1023,6 @@ Parser::parse_item (bool called_from_statement) // parse outer attributes for item AST::AttrVec outer_attrs = parse_outer_attributes (); - - // TODO: decide how to deal with VisItem vs MacroItem dichotomy - /* best current solution: catch all keywords that would imply a VisItem in a - * switch and have MacroItem as a last resort */ - const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -1055,6 +1050,7 @@ Parser::parse_item (bool called_from_statement) case STATIC_TOK: case TRAIT: case IMPL: + case MACRO: /* TODO: implement union keyword but not really because of * context-dependence crappy hack way to parse a union written below to * separate it from the good code. */ @@ -1069,7 +1065,7 @@ Parser::parse_item (bool called_from_statement) case CRATE: case DOLLAR_SIGN: // almost certainly macro invocation semi - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); break; // crappy hack to do union "keyword" case IDENTIFIER: @@ -1083,19 +1079,18 @@ Parser::parse_item (bool called_from_statement) else if (t->get_str () == "macro_rules") { // macro_rules! macro item - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_rules_def (std::move (outer_attrs)); } else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION || lexer.peek_token (1)->get_id () == EXCLAM) { /* path (probably) or macro invocation, so probably a macro invocation * semi */ - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); } gcc_fallthrough (); default: // otherwise unrecognised - // return parse_macro_item(std::move(outer_attrs)); add_error (Error (t->get_locus (), "unrecognised token %qs for start of %s", t->get_token_description (), @@ -1326,6 +1321,8 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) lexer.skip_token (1); // TODO: is this right thing to do? return nullptr; } + case MACRO: + return parse_decl_macro_def (std::move (vis), std::move (outer_attrs)); default: // otherwise vis item clearly doesn't exist, which is not an error // has a catch-all post-switch return to allow other breaks to occur @@ -1334,42 +1331,6 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) return nullptr; } -// Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition). -template -std::unique_ptr -Parser::parse_macro_item (AST::AttrVec outer_attrs) -{ - const_TokenPtr t = lexer.peek_token (); - - /* dodgy way of detecting macro due to weird context-dependence thing. - * probably can be improved */ - // TODO: ensure that string compare works properly - if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules") - { - return parse_macro_rules_def (std::move (outer_attrs)); - } - else - { - // DEBUG: TODO: remove - rust_debug ( - "DEBUG - parse_macro_item called and token is not macro_rules"); - if (t->get_id () == IDENTIFIER) - { - rust_debug ("just add to last error: token is not macro_rules and is " - "instead '%s'", - t->get_str ().c_str ()); - } - else - { - rust_debug ("just add to last error: token is not macro_rules and is " - "not an identifier either - it is '%s'", - t->get_token_description ()); - } - - return parse_macro_invocation_semi (std::move (outer_attrs)); - } -} - // Parses a macro rules definition syntax extension whatever thing. template std::unique_ptr @@ -1503,16 +1464,16 @@ Parser::parse_macro_rules_def (AST::AttrVec outer_attrs) { // as this is the end, allow recovery (probably) - may change return std::unique_ptr ( - new AST::MacroRulesDefinition ( + AST::MacroRulesDefinition::mbe ( std::move (rule_name), delim_type, std::move (macro_rules), std::move (outer_attrs), macro_locus)); } } return std::unique_ptr ( - new AST::MacroRulesDefinition (std::move (rule_name), delim_type, - std::move (macro_rules), - std::move (outer_attrs), macro_locus)); + AST::MacroRulesDefinition::mbe (std::move (rule_name), delim_type, + std::move (macro_rules), + std::move (outer_attrs), macro_locus)); } else { @@ -1532,6 +1493,165 @@ Parser::parse_macro_rules_def (AST::AttrVec outer_attrs) } } +// Parses a declarative macro 2.0 definition. +template +std::unique_ptr +Parser::parse_decl_macro_def (AST::Visibility vis, + AST::AttrVec outer_attrs) +{ + // ensure that first token is identifier saying "macro" + const_TokenPtr t = lexer.peek_token (); + if (t->get_id () != MACRO) + { + Error error ( + t->get_locus (), + "declarative macro definition does not start with %"); + add_error (std::move (error)); + + // skip after somewhere? + return nullptr; + } + lexer.skip_token (); + Location macro_locus = t->get_locus (); + + // parse macro name + const_TokenPtr ident_tok = expect_token (IDENTIFIER); + if (ident_tok == nullptr) + { + return nullptr; + } + Identifier rule_name = ident_tok->get_str (); + + t = lexer.peek_token (); + if (t->get_id () == LEFT_PAREN) + { + // single definiton of macro rule + // e.g. `macro foo($e:expr) {}` + + // parse macro matcher + Location locus = lexer.peek_token ()->get_locus (); + AST::MacroMatcher matcher = parse_macro_matcher (); + if (matcher.is_error ()) + return nullptr; + + // check delimiter of macro matcher + if (matcher.get_delim_type () != AST::DelimType::PARENS) + { + Error error (locus, "only parenthesis can be used for a macro " + "matcher in declarative macro definition"); + add_error (std::move (error)); + return nullptr; + } + + Location transcriber_loc = lexer.peek_token ()->get_locus (); + AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree (); + AST::MacroTranscriber transcriber (delim_tok_tree, transcriber_loc); + + if (transcriber.get_token_tree ().get_delim_type () + != AST::DelimType::CURLY) + { + Error error (transcriber_loc, + "only braces can be used for a macro transcriber " + "in declarative macro definition"); + add_error (std::move (error)); + return nullptr; + } + + AST::MacroRule macro_rule + = AST::MacroRule (std::move (matcher), std::move (transcriber), locus); + std::vector macro_rules; + macro_rules.push_back (macro_rule); + + return std::unique_ptr ( + AST::MacroRulesDefinition::decl_macro (std::move (rule_name), + macro_rules, + std::move (outer_attrs), + macro_locus, vis)); + } + else if (t->get_id () == LEFT_CURLY) + { + // multiple definitions of macro rule separated by comma + // e.g. `macro foo { () => {}, ($e:expr) => {}, }` + + // parse left curly + const_TokenPtr left_curly = expect_token (LEFT_CURLY); + if (left_curly == nullptr) + { + return nullptr; + } + + // parse actual macro rules + std::vector macro_rules; + + // must be at least one macro rule, so parse it + AST::MacroRule initial_rule = parse_macro_rule (); + if (initial_rule.is_error ()) + { + Error error ( + lexer.peek_token ()->get_locus (), + "required first macro rule in declarative macro definition " + "could not be parsed"); + add_error (std::move (error)); + + // skip after somewhere? + return nullptr; + } + macro_rules.push_back (std::move (initial_rule)); + + t = lexer.peek_token (); + // parse macro rules + while (t->get_id () == COMMA) + { + // skip comma + lexer.skip_token (); + + // don't parse if end of macro rules + if (token_id_matches_delims (lexer.peek_token ()->get_id (), + AST::CURLY)) + { + break; + } + + // try to parse next rule + AST::MacroRule rule = parse_macro_rule (); + if (rule.is_error ()) + { + Error error ( + lexer.peek_token ()->get_locus (), + "failed to parse macro rule in declarative macro definition"); + add_error (std::move (error)); + + return nullptr; + } + + macro_rules.push_back (std::move (rule)); + + t = lexer.peek_token (); + } + + // parse right curly + const_TokenPtr right_curly = expect_token (RIGHT_CURLY); + if (right_curly == nullptr) + { + return nullptr; + } + + return std::unique_ptr ( + AST::MacroRulesDefinition::decl_macro (std::move (rule_name), + std::move (macro_rules), + std::move (outer_attrs), + macro_locus, vis)); + } + else + { + add_error (Error (t->get_locus (), + "unexpected token %qs - expecting delimiters " + "(for a declarative macro definiton)", + t->get_token_description ())); + return nullptr; + } +} + // Parses a semi-coloned (except for full block) macro invocation item. template std::unique_ptr @@ -5995,6 +6115,7 @@ Parser::parse_stmt (ParseRestrictions restrictions) case STATIC_TOK: case TRAIT: case IMPL: + case MACRO: /* TODO: implement union keyword but not really because of * context-dependence crappy hack way to parse a union written below to * separate it from the good code. */ @@ -6010,7 +6131,7 @@ Parser::parse_stmt (ParseRestrictions restrictions) case CRATE: case DOLLAR_SIGN: // almost certainly macro invocation semi - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); break; // crappy hack to do union "keyword" case IDENTIFIER: @@ -6023,7 +6144,7 @@ Parser::parse_stmt (ParseRestrictions restrictions) else if (t->get_str () == "macro_rules") { // macro_rules! macro item - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_rules_def (std::move (outer_attrs)); } else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION || lexer.peek_token (1)->get_id () == EXCLAM) @@ -6031,7 +6152,7 @@ Parser::parse_stmt (ParseRestrictions restrictions) // FIXME: ensure doesn't take any expressions by mistake /* path (probably) or macro invocation, so probably a macro * invocation semi */ - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); } gcc_fallthrough (); // TODO: find out how to disable gcc "implicit fallthrough" warning @@ -11685,8 +11806,8 @@ Parser::parse_stmt_or_expr_without_block () else if (t->get_str () == "macro_rules") { // macro_rules! macro item - std::unique_ptr item ( - parse_macro_item (std::move (outer_attrs))); + std::unique_ptr item ( + parse_macro_rules_def (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 8449181b12f..5c0fcc3f174 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -197,6 +197,8 @@ private: AST::DelimTokenTree parse_delim_token_tree (); std::unique_ptr parse_macro_rules_def (AST::AttrVec outer_attrs); + std::unique_ptr + parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr parse_macro_invocation_semi (AST::AttrVec outer_attrs); std::unique_ptr @@ -209,7 +211,6 @@ private: // Top-level item-related std::unique_ptr parse_vis_item (AST::AttrVec outer_attrs); - std::unique_ptr parse_macro_item (AST::AttrVec outer_attrs); // VisItem subclass-related std::unique_ptr parse_module (AST::Visibility vis, diff --git a/gcc/testsuite/rust/compile/decl_macro1.rs b/gcc/testsuite/rust/compile/decl_macro1.rs new file mode 100644 index 00000000000..4a81a71e500 --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro1.rs @@ -0,0 +1,2 @@ +#![feature(decl_macro)] +macro m() {} diff --git a/gcc/testsuite/rust/compile/decl_macro2.rs b/gcc/testsuite/rust/compile/decl_macro2.rs new file mode 100644 index 00000000000..cbe19b0c14b --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro2.rs @@ -0,0 +1,2 @@ +#![feature(decl_macro)] +pub macro m($e: expr) { $e + $e } diff --git a/gcc/testsuite/rust/compile/decl_macro3.rs b/gcc/testsuite/rust/compile/decl_macro3.rs new file mode 100644 index 00000000000..d48da7835f9 --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro3.rs @@ -0,0 +1,4 @@ +#![feature(decl_macro)] +macro foo { + () => {} +} diff --git a/gcc/testsuite/rust/compile/decl_macro4.rs b/gcc/testsuite/rust/compile/decl_macro4.rs new file mode 100644 index 00000000000..b8576cf0dd8 --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro4.rs @@ -0,0 +1,5 @@ +#![feature(decl_macro)] +macro foo { + () => { 0 }, + ($n: expr) => { $n + 1 }, +} \ No newline at end of file diff --git a/gcc/testsuite/rust/compile/decl_macro5.rs b/gcc/testsuite/rust/compile/decl_macro5.rs new file mode 100644 index 00000000000..b4ea20ffa74 --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro5.rs @@ -0,0 +1,5 @@ +#![feature(decl_macro)] +macro foo { + () => [], + ($h: expr, $(t: expr),*) => ($h), +} diff --git a/gcc/testsuite/rust/compile/decl_macro6.rs b/gcc/testsuite/rust/compile/decl_macro6.rs new file mode 100644 index 00000000000..5c5e7002a98 --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro6.rs @@ -0,0 +1,5 @@ +#![feature(decl_macro)] +macro m {} +// { dg-error "unexpected token .\}. - expecting delimiters .for a macro matcher." "" { target *-*-* } .-1 } +// { dg-error "required first macro rule in declarative macro definition could not be parsed" "" { target *-*-* } .-2 } +// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } diff --git a/gcc/testsuite/rust/compile/decl_macro7.rs b/gcc/testsuite/rust/compile/decl_macro7.rs new file mode 100644 index 00000000000..7327fb56782 --- /dev/null +++ b/gcc/testsuite/rust/compile/decl_macro7.rs @@ -0,0 +1,4 @@ +#![feature(decl_macro)] +pub macro hello() [ "Hello" ] +// { dg-error "only braces can be used for a macro transcriber in declarative macro definition" "" { target *-*-* } .-1 } +// { dg-error "failed to parse item in crate" } \ No newline at end of file diff --git a/gcc/testsuite/rust/execute/torture/decl_macro1.rs b/gcc/testsuite/rust/execute/torture/decl_macro1.rs new file mode 100644 index 00000000000..accc8b1db8e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/decl_macro1.rs @@ -0,0 +1,8 @@ +#![feature(decl_macro)] +macro one() { + 1 +} + +fn main() -> i32 { + one!() - 1 +} diff --git a/gcc/testsuite/rust/execute/torture/decl_macro2.rs b/gcc/testsuite/rust/execute/torture/decl_macro2.rs new file mode 100644 index 00000000000..f42b96262fe --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/decl_macro2.rs @@ -0,0 +1,8 @@ +#![feature(decl_macro)] +macro one { + () => { 1 } +} + +fn main() -> i32 { + one!() - 1 +} diff --git a/gcc/testsuite/rust/execute/torture/decl_macro3.rs b/gcc/testsuite/rust/execute/torture/decl_macro3.rs new file mode 100644 index 00000000000..fa2cf793cf2 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/decl_macro3.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] +macro add { + ($e:expr) => { + $e + }, + ($h:expr, $($t:expr),*) => { + $h + add!($($t),*) + }, +} + +fn main() -> i32 { + let a = add!(1, 2, 3); + + a - 6 +} diff --git a/gcc/testsuite/rust/execute/torture/decl_macro4.rs b/gcc/testsuite/rust/execute/torture/decl_macro4.rs new file mode 100644 index 00000000000..e700e63161d --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/decl_macro4.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] +pub macro add { + ($e:expr) => { + $e + }, + ($h:expr, $($t:expr),*) => { + $h + add!($($t),*) + }, +} + +fn main() -> i32 { + let a = add!(1, 2, 3); + + a - 6 +}