public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] macro: Allow the repetition of metavars when expanding repetitions
@ 2022-07-22 13:34 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-07-22 13:34 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:09855d5c0eb14a9b976a98ae4ec9ab012eebaa51
commit 09855d5c0eb14a9b976a98ae4ec9ab012eebaa51
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date: Wed Jul 20 13:49:53 2022 +0200
macro: Allow the repetition of metavars when expanding repetitions
When expanding repeating metavars, we have to allow the repetition of non-repeating metavars as well:
```
macro_rules! foo {
( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
$(
impl $Trait for $Ty {
fn bar() -> i32 {
14
}
}
)+
}
}
trait Foo {
fn bar() -> i32;
}
trait Bar {
fn bar() -> i32;
}
trait Baz {
fn bar() -> i32;
}
trait Qux {
fn bar() -> i32;
}
struct S;
foo!{(Foo, Bar, Baz, Qux) for S}
```
This is valid, as the $Ty metavar is not a repetition. However, this should fail to compile:
```
macro_rules! foo {
// note the repetition here now
( ( $( $Trait: ident ),+ ) for $($Ty: ident)+ ) => {
$(
impl $Trait for $Ty {
fn bar() -> i32 {
14
}
}
)+
}
}
trait Foo {
fn bar() -> i32;
}
trait Bar {
fn bar() -> i32;
}
trait Baz {
fn bar() -> i32;
}
trait Qux {
fn bar() -> i32;
}
struct S;
foo!{(Foo, Bar, Baz, Qux) for S}
```
Obviously, if we were to specify as many $Ty as $Trait then there would be no issue, but that behavior is already handled.
Diff:
---
gcc/rust/expand/rust-macro-expand.cc | 14 +++++--
gcc/rust/expand/rust-macro-expand.h | 56 +++++++++++++++++++------
gcc/rust/expand/rust-macro-substitute-ctx.cc | 7 +++-
gcc/testsuite/rust/compile/macro-issue1400-2.rs | 32 ++++++++++++++
gcc/testsuite/rust/compile/macro-issue1400.rs | 33 +++++++++++++++
5 files changed, 123 insertions(+), 19 deletions(-)
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 189d377ccc4..f96c28834dd 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -83,10 +83,15 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
if (did_match_rule)
{
+ // FIXME: ARTHUR: Comment
// Debugging
- // for (auto &kv : matched_fragments)
- // rust_debug ("[fragment]: %s (%ld)", kv.first.c_str (),
- // kv.second.get_fragments ().size ());
+ for (auto &kv : matched_fragments)
+ rust_debug ("[fragment]: %s (%ld - %s)", kv.first.c_str (),
+ kv.second.get_fragments ().size (),
+ kv.second.get_kind ()
+ == MatchedFragmentContainer::Kind::Repetition
+ ? "repetition"
+ : "metavar");
matched_rule = &rule;
break;
@@ -621,7 +626,8 @@ 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_fragment (
+ // FIXME: ARTHUR: Here we want to append?
+ sub_stack.append_fragment (
MatchedFragment (fragment->get_ident (), offs_begin,
offs_end));
}
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index a5825249f33..51d7516f1c5 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -76,8 +76,17 @@ struct MatchedFragment
class MatchedFragmentContainer
{
public:
- MatchedFragmentContainer (std::vector<MatchedFragment> fragments)
- : fragments (fragments)
+ // Does the container refer to a simple metavariable, different from a
+ // repetition repeated once
+ enum class Kind
+ {
+ MetaVar,
+ Repetition,
+ };
+
+ MatchedFragmentContainer (std::vector<MatchedFragment> fragments,
+ Kind kind = Kind::Repetition)
+ : fragments (fragments), kind (kind)
{}
/**
@@ -94,7 +103,7 @@ public:
*/
static MatchedFragmentContainer one (MatchedFragment fragment)
{
- return MatchedFragmentContainer ({fragment});
+ return MatchedFragmentContainer ({fragment}, Kind::MetaVar);
}
/**
@@ -103,6 +112,8 @@ public:
void add_fragment (MatchedFragment fragment)
{
fragments.emplace_back (fragment);
+
+ kind = Kind::Repetition;
}
size_t get_match_amount () const { return fragments.size (); }
@@ -112,20 +123,28 @@ public:
}
// const std::string &get_fragment_name () const { return fragment_name; }
- bool is_single_fragment () const { return get_match_amount () == 1; }
+ bool is_single_fragment () const
+ {
+ // FIXME: Is that valid?
+ return get_match_amount () == 1 && kind == Kind::MetaVar;
+ }
+
const MatchedFragment get_single_fragment () const
{
- rust_assert (get_match_amount () == 1);
+ rust_assert (is_single_fragment ());
return fragments[0];
}
+ const Kind &get_kind () const { return kind; }
+
private:
/**
* Fragments matched `match_amount` times. This can be an empty vector
* in case having zero matches is allowed (i.e ? or * operators)
*/
std::vector<MatchedFragment> fragments;
+ Kind kind;
};
class SubstitutionScope
@@ -156,15 +175,26 @@ public:
auto it = current_map.find (fragment.fragment_ident);
if (it == current_map.end ())
- {
- current_map.insert (
- {fragment.fragment_ident, MatchedFragmentContainer::one (fragment)});
- }
+ current_map.insert (
+ {fragment.fragment_ident, MatchedFragmentContainer::one (fragment)});
else
- {
- auto &frags = it->second;
- frags.add_fragment (fragment);
- }
+ gcc_unreachable ();
+ }
+
+ /**
+ * Append a new matched fragment to a repetition into the current substitution
+ * map
+ */
+ void append_fragment (MatchedFragment fragment)
+ {
+ auto ¤t_map = stack.back ();
+ auto it = current_map.find (fragment.fragment_ident);
+
+ if (it == current_map.end ())
+ current_map.insert (
+ {fragment.fragment_ident, MatchedFragmentContainer ({fragment})});
+ else
+ it->second.add_fragment (fragment);
}
void insert_matches (std::string key, MatchedFragmentContainer matches)
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index 6f16214a2d8..1031cea483d 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.cc
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc
@@ -74,7 +74,9 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start,
is_valid = false;
}
- size_t repeat_amount = it->second.get_match_amount ();
+ auto &fragment = it->second;
+
+ size_t repeat_amount = fragment.get_match_amount ();
if (!first_fragment_found)
{
first_fragment_found = true;
@@ -82,7 +84,8 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start,
}
else
{
- if (repeat_amount != expected_repetition_amount)
+ if (repeat_amount != expected_repetition_amount
+ && !fragment.is_single_fragment ())
{
rust_error_at (
frag_token->get_locus (),
diff --git a/gcc/testsuite/rust/compile/macro-issue1400-2.rs b/gcc/testsuite/rust/compile/macro-issue1400-2.rs
new file mode 100644
index 00000000000..ba7b61b0b16
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1400-2.rs
@@ -0,0 +1,32 @@
+macro_rules! foo {
+ ( ( $( $Trait: ident ),+ ) for $($Ty: ident)* ) => {
+ $(
+ impl $Trait for $Ty {
+ // { dg-error "different amount of matches used in merged repetitions: expected 4, got 1" "" { target *-*-* } .-1 }
+ fn bar() -> i32 {
+ 14
+ }
+ }
+ )+
+ }
+}
+
+trait Foo {
+ fn bar() -> i32;
+}
+
+trait Bar {
+ fn bar() -> i32;
+}
+
+trait Baz {
+ fn bar() -> i32;
+}
+
+trait Qux {
+ fn bar() -> i32;
+}
+
+struct S;
+
+foo! {(Foo, Bar, Baz, Qux) for S}
diff --git a/gcc/testsuite/rust/compile/macro-issue1400.rs b/gcc/testsuite/rust/compile/macro-issue1400.rs
new file mode 100644
index 00000000000..971bd778054
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1400.rs
@@ -0,0 +1,33 @@
+// { dg-additional-options "-w" }
+
+macro_rules! foo {
+ ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
+ $(
+ impl $Trait for $Ty {
+ fn bar() -> i32 {
+ 14
+ }
+ }
+ )+
+ }
+}
+
+trait Foo {
+ fn bar() -> i32;
+}
+
+trait Bar {
+ fn bar() -> i32;
+}
+
+trait Baz {
+ fn bar() -> i32;
+}
+
+trait Qux {
+ fn bar() -> i32;
+}
+
+struct S;
+
+foo! {(Foo, Bar, Baz, Qux) for S}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-07-22 13:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-22 13:34 [gcc/devel/rust/master] macro: Allow the repetition of metavars when expanding repetitions 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).