1- use rustc_ast:: { entry:: EntryPointType , Attribute } ;
1+ use rustc_ast:: entry:: EntryPointType ;
22use rustc_errors:: struct_span_err;
33use rustc_hir:: def:: DefKind ;
44use rustc_hir:: def_id:: { DefId , LocalDefId , CRATE_DEF_ID , LOCAL_CRATE } ;
55use rustc_hir:: { ItemId , Node , CRATE_HIR_ID } ;
66use rustc_middle:: ty:: query:: Providers ;
77use rustc_middle:: ty:: { DefIdTree , TyCtxt } ;
8- use rustc_session:: config:: { CrateType , EntryFnType } ;
8+ use rustc_session:: config:: { sigpipe , CrateType , EntryFnType } ;
99use rustc_session:: parse:: feature_err;
1010use rustc_span:: symbol:: sym;
1111use rustc_span:: { Span , Symbol , DUMMY_SP } ;
@@ -71,14 +71,12 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
7171 }
7272}
7373
74- fn err_if_attr_found ( ctxt : & EntryContext < ' _ > , attrs : & [ Attribute ] , sym : Symbol ) {
74+ fn err_if_attr_found ( ctxt : & EntryContext < ' _ > , id : ItemId , sym : Symbol , details : & str ) {
75+ let attrs = ctxt. tcx . hir ( ) . attrs ( id. hir_id ( ) ) ;
7576 if let Some ( attr) = ctxt. tcx . sess . find_by_name ( attrs, sym) {
7677 ctxt. tcx
7778 . sess
78- . struct_span_err (
79- attr. span ,
80- & format ! ( "`{}` attribute can only be used on functions" , sym) ,
81- )
79+ . struct_span_err ( attr. span , & format ! ( "`{}` attribute {}" , sym, details) )
8280 . emit ( ) ;
8381 }
8482}
@@ -87,14 +85,16 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
8785 let at_root = ctxt. tcx . opt_local_parent ( id. def_id ) == Some ( CRATE_DEF_ID ) ;
8886
8987 match entry_point_type ( ctxt, id, at_root) {
90- EntryPointType :: None => ( ) ,
88+ EntryPointType :: None => {
89+ err_if_attr_found ( ctxt, id, sym:: unix_sigpipe, "can only be used on `fn main()`" ) ;
90+ }
9191 _ if !matches ! ( ctxt. tcx. def_kind( id. def_id) , DefKind :: Fn ) => {
92- let attrs = ctxt. tcx . hir ( ) . attrs ( id. hir_id ( ) ) ;
93- err_if_attr_found ( ctxt, attrs, sym:: start) ;
94- err_if_attr_found ( ctxt, attrs, sym:: rustc_main) ;
92+ err_if_attr_found ( ctxt, id, sym:: start, "can only be used on functions" ) ;
93+ err_if_attr_found ( ctxt, id, sym:: rustc_main, "can only be used on functions" ) ;
9594 }
9695 EntryPointType :: MainNamed => ( ) ,
9796 EntryPointType :: OtherMain => {
97+ err_if_attr_found ( ctxt, id, sym:: unix_sigpipe, "can only be used on root `fn main()`" ) ;
9898 ctxt. non_main_fns . push ( ctxt. tcx . def_span ( id. def_id ) ) ;
9999 }
100100 EntryPointType :: RustcMainAttr => {
@@ -116,6 +116,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
116116 }
117117 }
118118 EntryPointType :: Start => {
119+ err_if_attr_found ( ctxt, id, sym:: unix_sigpipe, "can only be used on `fn main()`" ) ;
119120 if ctxt. start_fn . is_none ( ) {
120121 ctxt. start_fn = Some ( ( id. def_id , ctxt. tcx . def_span ( id. def_id . to_def_id ( ) ) ) ) ;
121122 } else {
@@ -136,8 +137,9 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
136137fn configure_main ( tcx : TyCtxt < ' _ > , visitor : & EntryContext < ' _ > ) -> Option < ( DefId , EntryFnType ) > {
137138 if let Some ( ( def_id, _) ) = visitor. start_fn {
138139 Some ( ( def_id. to_def_id ( ) , EntryFnType :: Start ) )
139- } else if let Some ( ( def_id, _) ) = visitor. attr_main_fn {
140- Some ( ( def_id. to_def_id ( ) , EntryFnType :: Main ) )
140+ } else if let Some ( ( local_def_id, _) ) = visitor. attr_main_fn {
141+ let def_id = local_def_id. to_def_id ( ) ;
142+ Some ( ( def_id, EntryFnType :: Main { sigpipe : sigpipe ( tcx, def_id) } ) )
141143 } else {
142144 if let Some ( main_def) = tcx. resolutions ( ( ) ) . main_def && let Some ( def_id) = main_def. opt_fn_def_id ( ) {
143145 // non-local main imports are handled below
@@ -161,13 +163,39 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
161163 )
162164 . emit ( ) ;
163165 }
164- return Some ( ( def_id, EntryFnType :: Main ) ) ;
166+ return Some ( ( def_id, EntryFnType :: Main { sigpipe : sigpipe ( tcx , def_id ) } ) ) ;
165167 }
166168 no_main_err ( tcx, visitor) ;
167169 None
168170 }
169171}
170172
173+ fn sigpipe ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> u8 {
174+ if let Some ( attr) = tcx. get_attr ( def_id, sym:: unix_sigpipe) {
175+ match ( attr. value_str ( ) , attr. meta_item_list ( ) ) {
176+ ( Some ( sym:: inherit) , None ) => sigpipe:: INHERIT ,
177+ ( Some ( sym:: sig_ign) , None ) => sigpipe:: SIG_IGN ,
178+ ( Some ( sym:: sig_dfl) , None ) => sigpipe:: SIG_DFL ,
179+ ( _, Some ( _) ) => {
180+ // Keep going so that `fn emit_malformed_attribute()` can print
181+ // an excellent error message
182+ sigpipe:: DEFAULT
183+ }
184+ _ => {
185+ tcx. sess
186+ . struct_span_err (
187+ attr. span ,
188+ "valid values for `#[unix_sigpipe = \" ...\" ]` are `inherit`, `sig_ign`, or `sig_dfl`" ,
189+ )
190+ . emit ( ) ;
191+ sigpipe:: DEFAULT
192+ }
193+ }
194+ } else {
195+ sigpipe:: DEFAULT
196+ }
197+ }
198+
171199fn no_main_err ( tcx : TyCtxt < ' _ > , visitor : & EntryContext < ' _ > ) {
172200 let sp = tcx. def_span ( CRATE_DEF_ID ) ;
173201 if * tcx. sess . parse_sess . reached_eof . borrow ( ) {
0 commit comments