@@ -43,6 +43,7 @@ use rustc_session::lint::builtin::{
4343use rustc_session:: parse:: feature_err;
4444use rustc_span:: edition:: Edition ;
4545use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , sym} ;
46+ use rustc_target:: spec:: BinaryFormat ;
4647use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
4748use rustc_trait_selection:: infer:: { TyCtxtInferExt , ValuePairs } ;
4849use rustc_trait_selection:: traits:: ObligationCtxt ;
@@ -199,6 +200,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
199200 Attribute :: Parsed ( AttributeKind :: Link ( _, attr_span) ) => {
200201 self . check_link ( hir_id, * attr_span, span, target)
201202 } ,
203+ Attribute :: Parsed ( AttributeKind :: LinkSection { span : _, name, name_span } ) => {
204+ self . check_link_section ( * name, * name_span)
205+ } ,
202206 Attribute :: Parsed ( AttributeKind :: MacroExport { span, .. } ) => {
203207 self . check_macro_export ( hir_id, * span, target)
204208 } ,
@@ -249,7 +253,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
249253 | AttributeKind :: Lang ( ..)
250254 | AttributeKind :: LinkName { .. }
251255 | AttributeKind :: LinkOrdinal { .. }
252- | AttributeKind :: LinkSection { .. }
253256 | AttributeKind :: Linkage ( ..)
254257 | AttributeKind :: MacroEscape ( .. )
255258 | AttributeKind :: MacroUse { .. }
@@ -1196,6 +1199,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
11961199 ) ;
11971200 }
11981201
1202+ /// Checks if `#[link_section]` has a valid argument.
1203+ fn check_link_section ( & self , name : Symbol , name_span : Span ) {
1204+ // We (currently) only validate macho section specifiers.
1205+ match self . tcx . sess . target . binary_format {
1206+ BinaryFormat :: MachO => match Self :: check_link_section_macho ( name) {
1207+ Ok ( ( ) ) => { }
1208+ Err ( reason) => {
1209+ let err = errors:: InvalidMachoSection { name_span, reason } ;
1210+ self . tcx . dcx ( ) . emit_err ( err) ;
1211+ }
1212+ } ,
1213+ BinaryFormat :: Coff | BinaryFormat :: Elf | BinaryFormat :: Wasm | BinaryFormat :: Xcoff => { }
1214+ }
1215+ }
1216+
1217+ fn check_link_section_macho ( name : Symbol ) -> Result < ( ) , errors:: InvalidMachoSectionReason > {
1218+ use errors:: InvalidMachoSectionReason as Reason ;
1219+
1220+ let mut parts = name. as_str ( ) . split ( ',' ) . map ( |s| s. trim ( ) ) ;
1221+
1222+ // The segment can be empty.
1223+ let _segment = parts. next ( ) ;
1224+
1225+ // But the section is required.
1226+ let section = match parts. next ( ) {
1227+ None | Some ( "" ) => return Err ( Reason :: MissingSection ) ,
1228+ Some ( section) => section,
1229+ } ;
1230+
1231+ if section. len ( ) > 16 {
1232+ return Err ( Reason :: SectionTooLong { section : section. to_string ( ) } ) ;
1233+ }
1234+
1235+ // LLVM also checks the other components of the section specifier, but that logic is hard to
1236+ // keep in sync. We skip it here for now, assuming that if you got that far you'll be able
1237+ // to interpret the LLVM errors.
1238+
1239+ Ok ( ( ) )
1240+ }
1241+
11991242 /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
12001243 fn check_rustc_legacy_const_generics (
12011244 & self ,
0 commit comments