@@ -3,11 +3,10 @@ use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_nam
3
3
use rustc_data_structures:: fx:: FxHashMap ;
4
4
use rustc_errors:: codes:: * ;
5
5
use rustc_errors:: { DiagMessage , SubdiagMessage , struct_span_code_err} ;
6
- use rustc_hir as hir;
7
6
use rustc_hir:: def:: DefKind ;
8
7
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
9
8
use rustc_hir:: weak_lang_items:: WEAK_LANG_ITEMS ;
10
- use rustc_hir:: { LangItem , lang_items} ;
9
+ use rustc_hir:: { self as hir , HirId , LangItem , lang_items} ;
11
10
use rustc_middle:: middle:: codegen_fn_attrs:: {
12
11
CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
13
12
} ;
@@ -78,6 +77,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
78
77
let mut inline_span = None ;
79
78
let mut link_ordinal_span = None ;
80
79
let mut no_sanitize_span = None ;
80
+ let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState :: default ( ) ;
81
81
82
82
for attr in attrs. iter ( ) {
83
83
// 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 {
116
116
sym:: naked => codegen_fn_attrs. flags |= CodegenFnAttrFlags :: NAKED ,
117
117
sym:: no_mangle => {
118
118
if tcx. opt_item_name ( did. to_def_id ( ) ) . is_some ( ) {
119
- codegen_fn_attrs. flags |= CodegenFnAttrFlags :: NO_MANGLE
119
+ codegen_fn_attrs. flags |= CodegenFnAttrFlags :: NO_MANGLE ;
120
+ mixed_export_name_no_mangle_lint_state. track_no_mangle (
121
+ attr. span ,
122
+ tcx. local_def_id_to_hir_id ( did) ,
123
+ rustc_ast_pretty:: pprust:: attribute_to_string ( attr) ,
124
+ ) ;
120
125
} else {
121
126
tcx. dcx ( )
122
127
. struct_span_err (
@@ -240,6 +245,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
240
245
. emit ( ) ;
241
246
}
242
247
codegen_fn_attrs. export_name = Some ( s) ;
248
+ mixed_export_name_no_mangle_lint_state. track_export_name ( attr. span ) ;
243
249
}
244
250
}
245
251
sym:: target_feature => {
@@ -513,6 +519,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
513
519
}
514
520
}
515
521
522
+ mixed_export_name_no_mangle_lint_state. lint_if_mixed ( tcx) ;
523
+
516
524
codegen_fn_attrs. inline = attrs. iter ( ) . fold ( InlineAttr :: None , |ia, attr| {
517
525
if !attr. has_name ( sym:: inline) {
518
526
return ia;
@@ -779,6 +787,49 @@ fn check_link_name_xor_ordinal(
779
787
}
780
788
}
781
789
790
+ #[ derive( Default ) ]
791
+ struct MixedExportNameAndNoMangleState {
792
+ export_name : Option < Span > ,
793
+ hir_id : Option < HirId > ,
794
+ no_mangle : Option < Span > ,
795
+ no_mangle_attr_name : Option < String > ,
796
+ }
797
+
798
+ impl MixedExportNameAndNoMangleState {
799
+ fn track_export_name ( & mut self , span : Span ) {
800
+ self . export_name = Some ( span) ;
801
+ }
802
+
803
+ fn track_no_mangle ( & mut self , span : Span , hir_id : HirId , attr_name : String ) {
804
+ self . no_mangle = Some ( span) ;
805
+ self . hir_id = Some ( hir_id) ;
806
+ self . no_mangle_attr_name = Some ( attr_name) ;
807
+ }
808
+
809
+ /// Emit diagnostics if the lint condition is met.
810
+ fn lint_if_mixed ( self , tcx : TyCtxt < ' _ > ) {
811
+ if let Self {
812
+ export_name : Some ( export_name) ,
813
+ no_mangle : Some ( no_mangle) ,
814
+ hir_id : Some ( hir_id) ,
815
+ no_mangle_attr_name : Some ( no_mangle_attr_name) ,
816
+ } = self
817
+ {
818
+ tcx. emit_node_span_lint (
819
+ lint:: builtin:: UNUSED_ATTRIBUTES ,
820
+ hir_id,
821
+ no_mangle,
822
+ errors:: MixedExportNameAndNoMangle {
823
+ no_mangle,
824
+ no_mangle_attr : no_mangle_attr_name,
825
+ export_name,
826
+ removal_span : no_mangle,
827
+ } ,
828
+ ) ;
829
+ }
830
+ }
831
+ }
832
+
782
833
pub ( crate ) fn provide ( providers : & mut Providers ) {
783
834
* providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..* providers } ;
784
835
}
0 commit comments