@@ -2522,6 +2522,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2522
2522
let whitelist = tcx. target_features_whitelist ( LOCAL_CRATE ) ;
2523
2523
2524
2524
let mut inline_span = None ;
2525
+ let mut link_ordinal_span = None ;
2525
2526
for attr in attrs. iter ( ) {
2526
2527
if attr. check_name ( sym:: cold) {
2527
2528
codegen_fn_attrs. flags |= CodegenFnAttrFlags :: COLD ;
@@ -2603,6 +2604,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2603
2604
}
2604
2605
} else if attr. check_name ( sym:: link_name) {
2605
2606
codegen_fn_attrs. link_name = attr. value_str ( ) ;
2607
+ } else if attr. check_name ( sym:: link_ordinal) {
2608
+ link_ordinal_span = Some ( attr. span ) ;
2609
+ if let ordinal @ Some ( _) = check_link_ordinal ( tcx, attr) {
2610
+ codegen_fn_attrs. link_ordinal = ordinal;
2611
+ }
2606
2612
}
2607
2613
}
2608
2614
@@ -2680,6 +2686,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2680
2686
// purpose functions as they wouldn't have the right target features
2681
2687
// enabled. For that reason we also forbid #[inline(always)] as it can't be
2682
2688
// respected.
2689
+
2683
2690
if codegen_fn_attrs. target_features . len ( ) > 0 {
2684
2691
if codegen_fn_attrs. inline == InlineAttr :: Always {
2685
2692
if let Some ( span) = inline_span {
@@ -2704,6 +2711,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2704
2711
codegen_fn_attrs. export_name = Some ( name) ;
2705
2712
codegen_fn_attrs. link_name = Some ( name) ;
2706
2713
}
2714
+ check_link_name_xor_ordinal ( tcx, & codegen_fn_attrs, link_ordinal_span) ;
2707
2715
2708
2716
// Internal symbols to the standard library all have no_mangle semantics in
2709
2717
// that they have defined symbol names present in the function name. This
@@ -2714,3 +2722,48 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2714
2722
2715
2723
codegen_fn_attrs
2716
2724
}
2725
+
2726
+ fn check_link_ordinal ( tcx : TyCtxt < ' _ > , attr : & ast:: Attribute ) -> Option < usize > {
2727
+ use syntax:: ast:: { Lit , LitIntType , LitKind } ;
2728
+ let meta_item_list = attr. meta_item_list ( ) ;
2729
+ let meta_item_list: Option < & [ ast:: NestedMetaItem ] > = meta_item_list. as_ref ( ) . map ( Vec :: as_ref) ;
2730
+ let sole_meta_list = match meta_item_list {
2731
+ Some ( [ item] ) => item. literal ( ) ,
2732
+ _ => None ,
2733
+ } ;
2734
+ if let Some ( Lit { node : LitKind :: Int ( ordinal, LitIntType :: Unsuffixed ) , .. } ) = sole_meta_list {
2735
+ if * ordinal <= std:: usize:: MAX as u128 {
2736
+ Some ( * ordinal as usize )
2737
+ } else {
2738
+ let msg = format ! (
2739
+ "ordinal value in `link_ordinal` is too large: `{}`" ,
2740
+ & ordinal
2741
+ ) ;
2742
+ tcx. sess . struct_span_err ( attr. span , & msg)
2743
+ . note ( "the value may not exceed `std::usize::MAX`" )
2744
+ . emit ( ) ;
2745
+ None
2746
+ }
2747
+ } else {
2748
+ tcx. sess . struct_span_err ( attr. span , "illegal ordinal format in `link_ordinal`" )
2749
+ . note ( "an unsuffixed integer value, e.g., `1`, is expected" )
2750
+ . emit ( ) ;
2751
+ None
2752
+ }
2753
+ }
2754
+
2755
+ fn check_link_name_xor_ordinal (
2756
+ tcx : TyCtxt < ' _ > ,
2757
+ codegen_fn_attrs : & CodegenFnAttrs ,
2758
+ inline_span : Option < Span > ,
2759
+ ) {
2760
+ if codegen_fn_attrs. link_name . is_none ( ) || codegen_fn_attrs. link_ordinal . is_none ( ) {
2761
+ return ;
2762
+ }
2763
+ let msg = "cannot use `#[link_name]` with `#[link_ordinal]`" ;
2764
+ if let Some ( span) = inline_span {
2765
+ tcx. sess . span_err ( span, msg) ;
2766
+ } else {
2767
+ tcx. sess . err ( msg) ;
2768
+ }
2769
+ }
0 commit comments