diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4504589040f..0c01d9afec4 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -40,7 +40,14 @@ MacroExpander::expand_decl_macro (location_t invoc_locus, { // ensure that both invocation and rules are in a valid state rust_assert (!invoc.is_marked_for_strip ()); - rust_assert (!rules_def.is_marked_for_strip ()); + /* Note: We can't safely check if rules_def is marked for strip here because + * rules_def might be a dangling pointer to a deleted macro definition. + * This can happen when a macro definition has an invalid attribute (such as + * #[x] where x is not an attribute macro), causing the item to be deleted + * during attribute processing, but the pointer in in the invocation map still + * exists. + */ + // rust_assert (!rules_def.is_marked_for_strip ()); rust_assert (rules_def.get_macro_rules ().size () > 0); /* probably something here about parsing invoc and rules def token trees to @@ -314,6 +321,9 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, auto rdef = rules_def.value (); + if (!rdef) + return; + // We store the last expanded invocation and macro definition for error // reporting in case the recursion limit is reached last_invoc = *invoc.clone_macro_invocation_impl (); diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 0012969eb12..7e9b5a61f05 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -911,6 +911,10 @@ Mappings::insert_macro_invocation (AST::MacroInvocation &invoc, auto it = macroInvocations.find (invoc.get_macro_node_id ()); rust_assert (it == macroInvocations.end ()); + // Don't insert null pointers into the map as it could segfault later + if (!def) + return; + macroInvocations[invoc.get_macro_node_id ()] = def; } diff --git a/gcc/testsuite/rust/compile/issue-4187-1.rs b/gcc/testsuite/rust/compile/issue-4187-1.rs new file mode 100644 index 00000000000..4d2347652e5 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4187-1.rs @@ -0,0 +1,29 @@ +macro x( + $macro_name:ident, + $macro2_name:ident, + $type_name:ident, + $field_name:ident, + $const_name:ident +) { + pub struct $type_name {} + + pub const $const_name: $type_name = $type_name {}; + + #[x] + // { dg-error "macro not found" "" { target *-*-* } .-1 } + macro_rules! $macro_name { + () => {}; + } + + pub macro $type_name { + (Copy $e:expr) => {}, + () => {;}, + + } +} + +x!(test_fields, test_fields2, x, field, MY_CONST); + +pub fn check_fields_local() { + test_fields!(check_fields); // { dg-error "Failed to match any rule within macro" } +} diff --git a/gcc/testsuite/rust/compile/issue-4187-2.rs b/gcc/testsuite/rust/compile/issue-4187-2.rs new file mode 100644 index 00000000000..06d5e7e8598 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4187-2.rs @@ -0,0 +1,32 @@ +macro x( + $macro_name:ident, + $macro2_name:ident, + $type_name:ident, + $field_name:ident, + $const_name:ident +) { + pub struct $type_name {} + + pub const $const_name: $type_name = $type_name {}; + + #[x] + // { dg-error "macro not found" "" { target *-*-* } .-1 } + macro_rules! $macro_name { + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + }}; + } + + pub macro $type_name { + (Copy $e:expr) => {}, + (check_fields) => {test_fields!(check_fields);}, + + } +} + +x!(test_fields, test_fields2, x, field, MY_CONST); + +pub fn check_fields_local() { + test_fields!(check_fields); // { dg-error "Failed to match any rule within macro" } + test_fields2!(check_fields); // { dg-error "could not resolve macro invocation" } +}