Skip to content

Commit d859ab0

Browse files
committed
macros: Allow repetitions of tokens in follow-set in follow-set
When checking if a follow-up is valid, we previously always returned false when comparing with MacroMatchRepetitions. This is however invalid, as we should be comparing with the first match of the repetition to be sure.
1 parent 8283724 commit d859ab0

File tree

4 files changed

+36
-27
lines changed

4 files changed

+36
-27
lines changed

gcc/rust/parse/rust-parse.cc

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ contains (std::vector<T> &vec, T elm)
100100
return std::find (vec.begin (), vec.end (), elm) != vec.end ();
101101
}
102102

103+
/**
104+
* Avoid UB by calling .front() and .back() on empty containers...
105+
*/
106+
107+
template <typename T>
108+
static T *
109+
get_back_ptr (std::vector<std::unique_ptr<T>> &values)
110+
{
111+
if (values.empty ())
112+
return nullptr;
113+
114+
return values.back ().get ();
115+
}
116+
117+
template <typename T>
118+
static T *
119+
get_front_ptr (std::vector<std::unique_ptr<T>> &values)
120+
{
121+
if (values.empty ())
122+
return nullptr;
123+
124+
return values.front ().get ();
125+
}
126+
103127
static bool
104128
peculiar_fragment_match_compatible_fragment (
105129
const AST::MacroFragSpec &last_spec, const AST::MacroFragSpec &spec,
@@ -196,8 +220,9 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
196220
case AST::MacroMatch::Repetition: {
197221
auto repetition = static_cast<AST::MacroMatchRepetition *> (&match);
198222
auto &matches = repetition->get_matches ();
199-
if (!matches.empty ())
200-
error_locus = matches.front ()->get_match_locus ();
223+
auto first_frag = get_front_ptr (matches);
224+
if (first_frag)
225+
return peculiar_fragment_match_compatible (last_match, *first_frag);
201226
break;
202227
}
203228
case AST::MacroMatch::Matcher: {
@@ -231,30 +256,6 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
231256
return false;
232257
}
233258

234-
/**
235-
* Avoid UB by calling .front() and .back() on empty containers...
236-
*/
237-
238-
template <typename T>
239-
static T *
240-
get_back_ptr (std::vector<std::unique_ptr<T>> &values)
241-
{
242-
if (values.empty ())
243-
return nullptr;
244-
245-
return values.back ().get ();
246-
}
247-
248-
template <typename T>
249-
static T *
250-
get_front_ptr (std::vector<std::unique_ptr<T>> &values)
251-
{
252-
if (values.empty ())
253-
return nullptr;
254-
255-
return values.front ().get ();
256-
}
257-
258259
bool
259260
is_match_compatible (AST::MacroMatch &last_match, AST::MacroMatch &match)
260261
{
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
macro_rules! m {
2+
($e:expr $(forbidden)*) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
3+
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-1 }
4+
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
macro_rules! m {
2+
($e:expr $(,)*) => {{}};
3+
}

gcc/testsuite/rust/compile/macro28.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
macro_rules! m {
22
($a:expr $(tok $es:expr)*) => {
3-
// { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
3+
// { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
44
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
55
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
66
$a

0 commit comments

Comments
 (0)