From: Owen Avery <[email protected]>
This is imperfect, as invalid macro definitions should be detected
regardless of whether a macro is used or not.
gcc/rust/ChangeLog:
* expand/rust-macro-expand.cc
(MacroExpander::expand_decl_macro): Prevent excess errors.
(MacroExpander::match_matcher): Detect duplicate metavariable
names.
* expand/rust-macro-expand.h (MacroExpander::MacroExpander):
Initialize field had_duplicate_error.
(MacroExpander::had_duplicate_error): New field.
gcc/testsuite/ChangeLog:
* rust/compile/macros/mbe/macro-duplicate-binding.rs: New test.
Signed-off-by: Owen Avery <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/d12d295e2fa83df08362e0467e64f6dc12e22779
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4405
gcc/rust/expand/rust-macro-expand.cc | 27 ++++++++++++++++---
gcc/rust/expand/rust-macro-expand.h | 6 ++++-
.../macros/mbe/macro-duplicate-binding.rs | 7 +++++
3 files changed, 36 insertions(+), 4 deletions(-)
create mode 100644
gcc/testsuite/rust/compile/macros/mbe/macro-duplicate-binding.rs
diff --git a/gcc/rust/expand/rust-macro-expand.cc
b/gcc/rust/expand/rust-macro-expand.cc
index 3848328ce..aeea4c780 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -112,9 +112,13 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
if (matched_rule == nullptr)
{
- rich_location r (line_table, invoc_locus);
- r.add_range (rules_def.get_locus ());
- rust_error_at (r, "Failed to match any rule within macro");
+ if (!had_duplicate_error)
+ {
+ rich_location r (line_table, invoc_locus);
+ r.add_range (rules_def.get_locus ());
+ rust_error_at (r, "Failed to match any rule within macro");
+ }
+ had_duplicate_error = false;
return AST::Fragment::create_error ();
}
@@ -535,6 +539,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer>
&parser,
const MacroInvocLexer &source = parser.get_token_source ();
+ std::unordered_map<std::string, location_t> duplicate_check;
+
for (auto &match : matcher.get_matches ())
{
size_t offs_begin = source.get_offs ();
@@ -548,6 +554,21 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer>
&parser,
if (!match_fragment (parser, *fragment))
return false;
+ auto duplicate_result = duplicate_check.insert (
+ std::make_pair (fragment->get_ident ().as_string (),
+ fragment->get_ident ().get_locus ()));
+
+ if (!duplicate_result.second)
+ {
+ // TODO: add range labels?
+ rich_location r (line_table,
+ fragment->get_ident ().get_locus ());
+ r.add_range (duplicate_result.first->second);
+ rust_error_at (r, "duplicate matcher binding");
+ had_duplicate_error = true;
+ return false;
+ }
+
// matched fragment get the offset in the token stream
size_t offs_end = source.get_offs ();
sub_stack.insert_metavar (
diff --git a/gcc/rust/expand/rust-macro-expand.h
b/gcc/rust/expand/rust-macro-expand.h
index 7c8389aaf..cda4292cd 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -300,7 +300,8 @@ struct MacroExpander
: cfg (cfg), crate (crate), session (session),
sub_stack (SubstitutionScope ()),
expanded_fragment (AST::Fragment::create_error ()),
- has_changed_flag (false), resolver (Resolver::Resolver::get ()),
+ has_changed_flag (false), had_duplicate_error (false),
+ resolver (Resolver::Resolver::get ()),
mappings (Analysis::Mappings::get ())
{}
@@ -512,6 +513,9 @@ private:
tl::optional<AST::MacroRulesDefinition &> last_def;
tl::optional<AST::MacroInvocation &> last_invoc;
+ // used to avoid emitting excess errors
+ bool had_duplicate_error;
+
public:
Resolver::Resolver *resolver;
Analysis::Mappings &mappings;
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-duplicate-binding.rs
b/gcc/testsuite/rust/compile/macros/mbe/macro-duplicate-binding.rs
new file mode 100644
index 000000000..96276e9ed
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro-duplicate-binding.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+ ($a:ident, $a:ident) => {0} // { dg-error "duplicate matcher binding" }
+}
+
+fn main() {
+ foo!(a, b);
+}
base-commit: b940d2c51ba04f6c224642e777aacf4b2931be6b
--
2.52.0