aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-03-23 16:50:47 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2022-03-24 13:07:22 +0100
commitd859ab0146cd0002afc640d406997efb12a50d98 (patch)
treec59410d587bc2d9226b3bab9b3d8e50df076b319 /gcc
parent8283724bc24efc0c11960947f2d4e99bc20b3765 (diff)
downloadgcc-d859ab0146cd0002afc640d406997efb12a50d98.zip
gcc-d859ab0146cd0002afc640d406997efb12a50d98.tar.gz
gcc-d859ab0146cd0002afc640d406997efb12a50d98.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/parse/rust-parse.cc53
-rw-r--r--gcc/testsuite/rust/compile/macro-issue1053-2.rs5
-rw-r--r--gcc/testsuite/rust/compile/macro-issue1053.rs3
-rw-r--r--gcc/testsuite/rust/compile/macro28.rs2
4 files changed, 36 insertions, 27 deletions
diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc
index 0153b37..50d2efe 100644
--- a/gcc/rust/parse/rust-parse.cc
+++ b/gcc/rust/parse/rust-parse.cc
@@ -100,6 +100,30 @@ contains (std::vector<T> &vec, T elm)
return std::find (vec.begin (), vec.end (), elm) != vec.end ();
}
+/**
+ * Avoid UB by calling .front() and .back() on empty containers...
+ */
+
+template <typename T>
+static T *
+get_back_ptr (std::vector<std::unique_ptr<T>> &values)
+{
+ if (values.empty ())
+ return nullptr;
+
+ return values.back ().get ();
+}
+
+template <typename T>
+static T *
+get_front_ptr (std::vector<std::unique_ptr<T>> &values)
+{
+ if (values.empty ())
+ return nullptr;
+
+ return values.front ().get ();
+}
+
static bool
peculiar_fragment_match_compatible_fragment (
const AST::MacroFragSpec &last_spec, const AST::MacroFragSpec &spec,
@@ -196,8 +220,9 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
case AST::MacroMatch::Repetition: {
auto repetition = static_cast<AST::MacroMatchRepetition *> (&match);
auto &matches = repetition->get_matches ();
- if (!matches.empty ())
- error_locus = matches.front ()->get_match_locus ();
+ auto first_frag = get_front_ptr (matches);
+ if (first_frag)
+ return peculiar_fragment_match_compatible (last_match, *first_frag);
break;
}
case AST::MacroMatch::Matcher: {
@@ -231,30 +256,6 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
return false;
}
-/**
- * Avoid UB by calling .front() and .back() on empty containers...
- */
-
-template <typename T>
-static T *
-get_back_ptr (std::vector<std::unique_ptr<T>> &values)
-{
- if (values.empty ())
- return nullptr;
-
- return values.back ().get ();
-}
-
-template <typename T>
-static T *
-get_front_ptr (std::vector<std::unique_ptr<T>> &values)
-{
- if (values.empty ())
- return nullptr;
-
- return values.front ().get ();
-}
-
bool
is_match_compatible (AST::MacroMatch &last_match, AST::MacroMatch &match)
{
diff --git a/gcc/testsuite/rust/compile/macro-issue1053-2.rs b/gcc/testsuite/rust/compile/macro-issue1053-2.rs
new file mode 100644
index 0000000..3145990
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1053-2.rs
@@ -0,0 +1,5 @@
+macro_rules! m {
+ ($e:expr $(forbidden)*) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
+ // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-1 }
+ // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/macro-issue1053.rs b/gcc/testsuite/rust/compile/macro-issue1053.rs
new file mode 100644
index 0000000..1e96849
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro-issue1053.rs
@@ -0,0 +1,3 @@
+macro_rules! m {
+ ($e:expr $(,)*) => {{}};
+}
diff --git a/gcc/testsuite/rust/compile/macro28.rs b/gcc/testsuite/rust/compile/macro28.rs
index 3d83c08..8002f28 100644
--- a/gcc/testsuite/rust/compile/macro28.rs
+++ b/gcc/testsuite/rust/compile/macro28.rs
@@ -1,6 +1,6 @@
macro_rules! m {
($a:expr $(tok $es:expr)*) => {
- // { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
+ // { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
$a