diff options
| author | bors <bors@rust-lang.org> | 2022-12-26 09:06:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-12-26 09:06:51 +0000 |
| commit | f206533fd40378da6e2a07567e8d7592edd13ee4 (patch) | |
| tree | fef7f402534df2e2db69c49dadcae2c6e287c3a7 /compiler/rustc_codegen_ssa | |
| parent | 797b5f0f8e9ab6d02a6a1464b04dea75a7a4cde4 (diff) | |
| parent | 47b642677715caa8e5699ecb397e34125f3256e8 (diff) | |
| download | rust-f206533fd40378da6e2a07567e8d7592edd13ee4.tar.gz rust-f206533fd40378da6e2a07567e8d7592edd13ee4.zip | |
Auto merge of #105605 - inquisitivecrystal:attr-validation, r=cjgillot
Don't perform invalid checks in `codegen_attrs` The attributes `#[track_caller]` and `#[cmse_nonsecure_entry]` are only valid on functions. When validating one of these attributes, codegen_attrs previously called `fn_sig`, [which can only be used on functions](https://github.com/rust-lang/rust/pull/105201), on the item the attribute was attached to, assuming that the item was a function without checking. This led to [ICEs in situations where the attribute was incorrectly used on non-functions](https://github.com/rust-lang/rust/issues/105594). With this change, we skip calling `fn_sig` if the item the attribute is attached to must be a function but isn't, because `check_attr` will reject such cases without codegen_attrs's intervention. As a side note, some of the attributes in codegen_attrs are only valid on functions, but that property isn't actually checked. I'm planning to fix that in a follow up PR since it's a behavior change that will need to be validated rather than an obvious bugfix. Thankfully, all the attributes like that I've found so far are unstable. Fixes #105594. r? `@cjgillot`
Diffstat (limited to 'compiler/rustc_codegen_ssa')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index c7f2e1966c1..b0fa7745667 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -2,6 +2,7 @@ use rustc_ast::{ast, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -60,6 +61,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); + // In some cases, attribute are only valid on functions, but it's the `check_attr` + // pass that check that they aren't used anywhere else, rather this module. + // In these cases, we bail from performing further checks that are only meaningful for + // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also + // report a delayed bug, just in case `check_attr` isn't doing its job. + let validate_fn_only_attr = |attr_sp| -> bool { + let def_kind = tcx.def_kind(did); + if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind { + true + } else { + tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions"); + false + } + }; + let mut inline_span = None; let mut link_ordinal_span = None; let mut no_sanitize_span = None; @@ -197,7 +213,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } } else if attr.has_name(sym::cmse_nonsecure_entry) { - if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) { + if validate_fn_only_attr(attr.span) + && !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) + { struct_span_err!( tcx.sess, attr.span, @@ -214,7 +232,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.has_name(sym::track_caller) { - if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust { + if !tcx.is_closure(did.to_def_id()) + && validate_fn_only_attr(attr.span) + && tcx.fn_sig(did).abi() != abi::Abi::Rust + { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); } |
