@@ -2522,6 +2522,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
25222522 let whitelist = tcx. target_features_whitelist ( LOCAL_CRATE ) ;
25232523
25242524 let mut inline_span = None ;
2525+ let mut link_ordinal_span = None ;
25252526 for attr in attrs. iter ( ) {
25262527 if attr. check_name ( sym:: cold) {
25272528 codegen_fn_attrs. flags |= CodegenFnAttrFlags :: COLD ;
@@ -2603,6 +2604,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
26032604 }
26042605 } else if attr. check_name ( sym:: link_name) {
26052606 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+ }
26062612 }
26072613 }
26082614
@@ -2680,6 +2686,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
26802686 // purpose functions as they wouldn't have the right target features
26812687 // enabled. For that reason we also forbid #[inline(always)] as it can't be
26822688 // respected.
2689+
26832690 if codegen_fn_attrs. target_features . len ( ) > 0 {
26842691 if codegen_fn_attrs. inline == InlineAttr :: Always {
26852692 if let Some ( span) = inline_span {
@@ -2704,6 +2711,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
27042711 codegen_fn_attrs. export_name = Some ( name) ;
27052712 codegen_fn_attrs. link_name = Some ( name) ;
27062713 }
2714+ check_link_name_xor_ordinal ( tcx, & codegen_fn_attrs, link_ordinal_span) ;
27072715
27082716 // Internal symbols to the standard library all have no_mangle semantics in
27092717 // 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 {
27142722
27152723 codegen_fn_attrs
27162724}
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