@@ -2560,6 +2560,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2560
2560
let whitelist = tcx. target_features_whitelist ( LOCAL_CRATE ) ;
2561
2561
2562
2562
let mut inline_span = None ;
2563
+ let mut link_ordinal_span = None ;
2563
2564
for attr in attrs. iter ( ) {
2564
2565
if attr. check_name ( sym:: cold) {
2565
2566
codegen_fn_attrs. flags |= CodegenFnAttrFlags :: COLD ;
@@ -2641,6 +2642,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2641
2642
}
2642
2643
} else if attr. check_name ( sym:: link_name) {
2643
2644
codegen_fn_attrs. link_name = attr. value_str ( ) ;
2645
+ } else if attr. check_name ( sym:: link_ordinal) {
2646
+ link_ordinal_span = Some ( attr. span ) ;
2647
+ if let ordinal @ Some ( _) = check_link_ordinal ( tcx, attr) {
2648
+ codegen_fn_attrs. link_ordinal = ordinal;
2649
+ }
2644
2650
}
2645
2651
}
2646
2652
@@ -2718,6 +2724,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2718
2724
// purpose functions as they wouldn't have the right target features
2719
2725
// enabled. For that reason we also forbid #[inline(always)] as it can't be
2720
2726
// respected.
2727
+
2721
2728
if codegen_fn_attrs. target_features . len ( ) > 0 {
2722
2729
if codegen_fn_attrs. inline == InlineAttr :: Always {
2723
2730
if let Some ( span) = inline_span {
@@ -2742,6 +2749,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2742
2749
codegen_fn_attrs. export_name = Some ( name) ;
2743
2750
codegen_fn_attrs. link_name = Some ( name) ;
2744
2751
}
2752
+ check_link_name_xor_ordinal ( tcx, & codegen_fn_attrs, link_ordinal_span) ;
2745
2753
2746
2754
// Internal symbols to the standard library all have no_mangle semantics in
2747
2755
// that they have defined symbol names present in the function name. This
@@ -2752,3 +2760,48 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2752
2760
2753
2761
codegen_fn_attrs
2754
2762
}
2763
+
2764
+ fn check_link_ordinal ( tcx : TyCtxt < ' _ > , attr : & ast:: Attribute ) -> Option < usize > {
2765
+ use syntax:: ast:: { Lit , LitIntType , LitKind } ;
2766
+ let meta_item_list = attr. meta_item_list ( ) ;
2767
+ let meta_item_list: Option < & [ ast:: NestedMetaItem ] > = meta_item_list. as_ref ( ) . map ( Vec :: as_ref) ;
2768
+ let sole_meta_list = match meta_item_list {
2769
+ Some ( [ item] ) => item. literal ( ) ,
2770
+ _ => None ,
2771
+ } ;
2772
+ if let Some ( Lit { kind : LitKind :: Int ( ordinal, LitIntType :: Unsuffixed ) , .. } ) = sole_meta_list {
2773
+ if * ordinal <= std:: usize:: MAX as u128 {
2774
+ Some ( * ordinal as usize )
2775
+ } else {
2776
+ let msg = format ! (
2777
+ "ordinal value in `link_ordinal` is too large: `{}`" ,
2778
+ & ordinal
2779
+ ) ;
2780
+ tcx. sess . struct_span_err ( attr. span , & msg)
2781
+ . note ( "the value may not exceed `std::usize::MAX`" )
2782
+ . emit ( ) ;
2783
+ None
2784
+ }
2785
+ } else {
2786
+ tcx. sess . struct_span_err ( attr. span , "illegal ordinal format in `link_ordinal`" )
2787
+ . note ( "an unsuffixed integer value, e.g., `1`, is expected" )
2788
+ . emit ( ) ;
2789
+ None
2790
+ }
2791
+ }
2792
+
2793
+ fn check_link_name_xor_ordinal (
2794
+ tcx : TyCtxt < ' _ > ,
2795
+ codegen_fn_attrs : & CodegenFnAttrs ,
2796
+ inline_span : Option < Span > ,
2797
+ ) {
2798
+ if codegen_fn_attrs. link_name . is_none ( ) || codegen_fn_attrs. link_ordinal . is_none ( ) {
2799
+ return ;
2800
+ }
2801
+ let msg = "cannot use `#[link_name]` with `#[link_ordinal]`" ;
2802
+ if let Some ( span) = inline_span {
2803
+ tcx. sess . span_err ( span, msg) ;
2804
+ } else {
2805
+ tcx. sess . err ( msg) ;
2806
+ }
2807
+ }
0 commit comments