Rollup merge of #131558 - sassman:feat/warnin-for-no-mangle-together-with-export-name, r=Urgau
Lint on combining `#[no_mangle]` and `#[export_name]` This is my very first contribution to the compiler, even though I read the [chapter about lints](https://rustc-dev-guide.rust-lang.org/diagnostics.html) I'm not very certain that this ~~new lint is done right as a builtin lint~~ PR is right. I appreciate any guidance on how to improve the code. - Add test for issue #47446 - ~~Implement the new lint `mixed_export_name_and_no_mangle` as a builtin lint (not sure if that is the right way to go)~~ Extend `unused_attributes` lint - Add suggestion how to fix it <details> <summary>Old proposed new lint</summary> > The `mixed_export_name_and_no_mangle` lint detects usage of both `#[export_name]` and `#[no_mangle]` on the same item which results on `#[no_mangle]` being ignored. > > *warn-by-default* > > ### Example > > ```rust > #[no_mangle] // ignored > #[export_name = "foo"] // takes precedences > pub fn bar() {} > ``` > > ### Explanation > > The compiler will not respect the `#[no_mangle]` attribute when generating the symbol name for the function, as the `#[export_name]` attribute takes precedence. This can lead to confusion and is unnecessary. </details>
This commit is contained in:
commit
94d780d647
9 changed files with 143 additions and 5 deletions
|
@ -3,11 +3,10 @@ use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_nam
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
||||
use rustc_hir::{LangItem, lang_items};
|
||||
use rustc_hir::{self as hir, HirId, LangItem, lang_items};
|
||||
use rustc_middle::middle::codegen_fn_attrs::{
|
||||
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
|
||||
};
|
||||
|
@ -78,6 +77,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
let mut inline_span = None;
|
||||
let mut link_ordinal_span = None;
|
||||
let mut no_sanitize_span = None;
|
||||
let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState::default();
|
||||
|
||||
for attr in attrs.iter() {
|
||||
// In some cases, attribute are only valid on functions, but it's the `check_attr`
|
||||
|
@ -116,7 +116,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
sym::naked => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
|
||||
sym::no_mangle => {
|
||||
if tcx.opt_item_name(did.to_def_id()).is_some() {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
||||
mixed_export_name_no_mangle_lint_state.track_no_mangle(
|
||||
attr.span,
|
||||
tcx.local_def_id_to_hir_id(did),
|
||||
attr,
|
||||
);
|
||||
} else {
|
||||
tcx.dcx()
|
||||
.struct_span_err(
|
||||
|
@ -240,6 +245,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.export_name = Some(s);
|
||||
mixed_export_name_no_mangle_lint_state.track_export_name(attr.span);
|
||||
}
|
||||
}
|
||||
sym::target_feature => {
|
||||
|
@ -513,6 +519,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
}
|
||||
}
|
||||
|
||||
mixed_export_name_no_mangle_lint_state.lint_if_mixed(tcx);
|
||||
|
||||
codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
|
||||
if !attr.has_name(sym::inline) {
|
||||
return ia;
|
||||
|
@ -779,6 +787,49 @@ fn check_link_name_xor_ordinal(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct MixedExportNameAndNoMangleState<'a> {
|
||||
export_name: Option<Span>,
|
||||
hir_id: Option<HirId>,
|
||||
no_mangle: Option<Span>,
|
||||
no_mangle_attr: Option<&'a ast::Attribute>,
|
||||
}
|
||||
|
||||
impl<'a> MixedExportNameAndNoMangleState<'a> {
|
||||
fn track_export_name(&mut self, span: Span) {
|
||||
self.export_name = Some(span);
|
||||
}
|
||||
|
||||
fn track_no_mangle(&mut self, span: Span, hir_id: HirId, attr_name: &'a ast::Attribute) {
|
||||
self.no_mangle = Some(span);
|
||||
self.hir_id = Some(hir_id);
|
||||
self.no_mangle_attr = Some(attr_name);
|
||||
}
|
||||
|
||||
/// Emit diagnostics if the lint condition is met.
|
||||
fn lint_if_mixed(self, tcx: TyCtxt<'_>) {
|
||||
if let Self {
|
||||
export_name: Some(export_name),
|
||||
no_mangle: Some(no_mangle),
|
||||
hir_id: Some(hir_id),
|
||||
no_mangle_attr: Some(no_mangle_attr),
|
||||
} = self
|
||||
{
|
||||
tcx.emit_node_span_lint(
|
||||
lint::builtin::UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
no_mangle,
|
||||
errors::MixedExportNameAndNoMangle {
|
||||
no_mangle,
|
||||
no_mangle_attr: rustc_ast_pretty::pprust::attribute_to_string(no_mangle_attr),
|
||||
export_name,
|
||||
removal_span: no_mangle,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_errors::codes::*;
|
|||
use rustc_errors::{
|
||||
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
@ -1114,3 +1114,15 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_
|
|||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_aix_strip_not_used)]
|
||||
pub(crate) struct AixStripNotUsed;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(codegen_ssa_mixed_export_name_and_no_mangle)]
|
||||
pub(crate) struct MixedExportNameAndNoMangle {
|
||||
#[label]
|
||||
pub no_mangle: Span,
|
||||
pub no_mangle_attr: String,
|
||||
#[note]
|
||||
pub export_name: Span,
|
||||
#[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
|
||||
pub removal_span: Span,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue