gccrs: expansion: Only add fragments if the matcher succeeded
gcc/rust/ChangeLog: * expand/rust-macro-expand.cc (MacroExpander::match_n_matches): Do not insert fragments and substack fragments if the matcher failed. gcc/testsuite/ChangeLog: * rust/compile/macros/mbe/macro-issue3708.rs: New test.
This commit is contained in:
parent
76477f9655
commit
cb23182fa2
2 changed files with 88 additions and 7 deletions
|
@ -621,9 +621,10 @@ 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;
|
||||
|
||||
|
@ -650,15 +651,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
|
||||
|
|
80
gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
Normal file
80
gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
|
||||
|
||||
macro_rules! impl_fn_for_zst {
|
||||
($(
|
||||
$( #[$attr: meta] )*
|
||||
struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
|
||||
|$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
|
||||
$body: block;
|
||||
)+) => {
|
||||
$(
|
||||
$( #[$attr] )*
|
||||
struct $Name;
|
||||
|
||||
impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
|
||||
#[inline]
|
||||
extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
|
||||
#[inline]
|
||||
extern "rust-call" fn call_mut(
|
||||
&mut self,
|
||||
($( $arg, )*): ($( $ArgTy, )*)
|
||||
) -> $ReturnTy {
|
||||
Fn::call(&*self, ($( $arg, )*))
|
||||
}
|
||||
}
|
||||
|
||||
impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
|
||||
type Output = $ReturnTy;
|
||||
|
||||
#[inline]
|
||||
extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
|
||||
Fn::call(&self, ($( $arg, )*))
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[lang = "fn"]
|
||||
pub trait Fn<Args>: FnMut<Args> {
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn_mut"]
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
pub trait FnMut<Args>: FnOnce<Args> {
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn_once"]
|
||||
pub trait FnOnce<Args> {
|
||||
/// The returned type after the call operator is used.
|
||||
#[lang = "fn_once_output"]
|
||||
#[stable(feature = "fn_once_output", since = "1.12.0")]
|
||||
type Output;
|
||||
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
impl_fn_for_zst! {
|
||||
#[derive(Copy)]
|
||||
struct LinesAnyMap impl<'a> Fn = |line: &'a str| -> () {
|
||||
};
|
||||
}
|
Loading…
Add table
Reference in a new issue