public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Implement declarative macro 2.0 parser Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
@ 2023-01-12 7:44 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-01-12 7:44 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:9e5769cf45cfc703e807e51b3ad301e123b05b55
commit 9e5769cf45cfc703e807e51b3ad301e123b05b55
Author: Raiki Tamura <tamaron1203@gmail.com>
Date: Mon Dec 19 01:48:54 2022 +0900
Implement declarative macro 2.0 parser
Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
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<Attribute> outer_attrs;
Identifier rule_name;
// MacroRulesDef rules_def;
@@ -460,6 +468,7 @@ class MacroRulesDefinition : public MacroItem
std::function<Fragment (Location, MacroInvocData &)> 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<MacroRule> rules,
- std::vector<Attribute> outer_attrs, Location locus)
- : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
+ std::vector<Attribute> 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<Fragment (Location, MacroInvocData &)> associated_transcriber)
- : outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
+ std::function<Fragment (Location, MacroInvocData &)> associated_transcriber,
+ MacroKind kind, Visibility vis)
+ : VisItem (std::move (vis), std::vector<Attribute> ()),
+ outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
delim_type (delim_type), rules (std::vector<MacroRule> ()),
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<MacroRulesDefinition>
+ mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
+ std::vector<Attribute> outer_attrs, Location locus)
+ {
+ return Rust::make_unique<MacroRulesDefinition> (
+ MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
+ AST::MacroRulesDefinition::MacroKind::MBE,
+ AST::Visibility::create_error ()));
+ }
+
+ static std::unique_ptr<MacroRulesDefinition>
+ decl_macro (Identifier rule_name, std::vector<MacroRule> rules,
+ std::vector<Attribute> outer_attrs, Location locus,
+ Visibility vis)
+ {
+ return Rust::make_unique<MacroRulesDefinition> (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<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs)
return nullptr;
}
-// Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition).
-template <typename ManagedTokenSource>
-std::unique_ptr<AST::MacroItem>
-Parser<ManagedTokenSource>::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 <typename ManagedTokenSource>
std::unique_ptr<AST::MacroRulesDefinition>
@@ -1503,16 +1464,16 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
{
// as this is the end, allow recovery (probably) - may change
return std::unique_ptr<AST::MacroRulesDefinition> (
- 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<AST::MacroRulesDefinition> (
- 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<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs)
}
}
+// Parses a declarative macro 2.0 definition.
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::MacroRulesDefinition>
+Parser<ManagedTokenSource>::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 %<macro%>");
+ 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<AST::MacroRule> macro_rules;
+ macro_rules.push_back (macro_rule);
+
+ return std::unique_ptr<AST::MacroRulesDefinition> (
+ 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<AST::MacroRule> 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> (
+ 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 <typename ManagedTokenSource>
std::unique_ptr<AST::MacroInvocation>
@@ -5995,6 +6115,7 @@ Parser<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::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<ManagedTokenSource>::parse_stmt_or_expr_without_block ()
else if (t->get_str () == "macro_rules")
{
// macro_rules! macro item
- std::unique_ptr<AST::MacroItem> item (
- parse_macro_item (std::move (outer_attrs)));
+ std::unique_ptr<AST::Item> 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<AST::MacroRulesDefinition>
parse_macro_rules_def (AST::AttrVec outer_attrs);
+ std::unique_ptr<AST::MacroRulesDefinition>
+ parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs);
std::unique_ptr<AST::MacroInvocation>
parse_macro_invocation_semi (AST::AttrVec outer_attrs);
std::unique_ptr<AST::MacroInvocation>
@@ -209,7 +211,6 @@ private:
// Top-level item-related
std::unique_ptr<AST::VisItem> parse_vis_item (AST::AttrVec outer_attrs);
- std::unique_ptr<AST::MacroItem> parse_macro_item (AST::AttrVec outer_attrs);
// VisItem subclass-related
std::unique_ptr<AST::Module> 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
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-01-12 7:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-12 7:44 [gcc/devel/rust/master] Implement declarative macro 2.0 parser Signed-off-by: Raiki Tamura <tamaron1203@gmail.com> Thomas Schwinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).