11//! Checks validity of naked functions.
22
33use rustc_ast:: InlineAsmOptions ;
4- use rustc_errors:: { struct_span_err, Applicability } ;
54use rustc_hir as hir;
65use rustc_hir:: def:: DefKind ;
76use rustc_hir:: def_id:: LocalDefId ;
@@ -14,6 +13,12 @@ use rustc_span::symbol::sym;
1413use rustc_span:: Span ;
1514use rustc_target:: spec:: abi:: Abi ;
1615
16+ use crate :: errors:: {
17+ CannotInlineNakedFunction , NakedFunctionsAsmBlock , NakedFunctionsAsmOptions ,
18+ NakedFunctionsMustUseNoreturn , NakedFunctionsOperands , NoPatterns , ParamsNotAllowed ,
19+ UndefinedNakedFunctionAbi ,
20+ } ;
21+
1722pub ( crate ) fn provide ( providers : & mut Providers ) {
1823 * providers = Providers { check_mod_naked_functions, ..* providers } ;
1924}
@@ -56,7 +61,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
5661fn check_inline ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) {
5762 let attrs = tcx. get_attrs ( def_id. to_def_id ( ) , sym:: inline) ;
5863 for attr in attrs {
59- tcx. sess . struct_span_err ( attr . span , "naked functions cannot be inlined" ) . emit ( ) ;
64+ tcx. sess . emit_err ( CannotInlineNakedFunction { span : attr . span } ) ;
6065 }
6166}
6267
@@ -65,12 +70,11 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
6570 if abi == Abi :: Rust {
6671 let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
6772 let span = tcx. def_span ( def_id) ;
68- tcx. struct_span_lint_hir (
73+ tcx. emit_spanned_lint (
6974 UNDEFINED_NAKED_FUNCTION_ABI ,
7075 hir_id,
7176 span,
72- "Rust ABI is unsupported in naked functions" ,
73- |lint| lint,
77+ UndefinedNakedFunctionAbi ,
7478 ) ;
7579 }
7680}
@@ -82,12 +86,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
8286 hir:: PatKind :: Wild
8387 | hir:: PatKind :: Binding ( hir:: BindingAnnotation :: NONE , _, _, None ) => { }
8488 _ => {
85- tcx. sess
86- . struct_span_err (
87- param. pat . span ,
88- "patterns not allowed in naked function parameters" ,
89- )
90- . emit ( ) ;
89+ tcx. sess . emit_err ( NoPatterns { span : param. pat . span } ) ;
9190 }
9291 }
9392 }
@@ -117,14 +116,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
117116 ) ) = expr. kind
118117 {
119118 if self . params . contains ( var_hir_id) {
120- self . tcx
121- . sess
122- . struct_span_err (
123- expr. span ,
124- "referencing function parameters is not allowed in naked functions" ,
125- )
126- . help ( "follow the calling convention in asm block to use parameters" )
127- . emit ( ) ;
119+ self . tcx . sess . emit_err ( ParamsNotAllowed { span : expr. span } ) ;
128120 return ;
129121 }
130122 }
@@ -139,26 +131,21 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
139131 if let [ ( ItemKind :: Asm | ItemKind :: Err , _) ] = this. items [ ..] {
140132 // Ok.
141133 } else {
142- let mut diag = struct_span_err ! (
143- tcx. sess,
144- tcx. def_span( def_id) ,
145- E0787 ,
146- "naked functions must contain a single asm block"
147- ) ;
148-
149134 let mut must_show_error = false ;
150135 let mut has_asm = false ;
151136 let mut has_err = false ;
137+ let mut multiple_asms = vec ! [ ] ;
138+ let mut non_asms = vec ! [ ] ;
152139 for & ( kind, span) in & this. items {
153140 match kind {
154141 ItemKind :: Asm if has_asm => {
155142 must_show_error = true ;
156- diag . span_label ( span, "multiple asm blocks are unsupported in naked functions" ) ;
143+ multiple_asms . push ( span) ;
157144 }
158145 ItemKind :: Asm => has_asm = true ,
159146 ItemKind :: NonAsm => {
160147 must_show_error = true ;
161- diag . span_label ( span, "non-asm is unsupported in naked functions" ) ;
148+ non_asms . push ( span) ;
162149 }
163150 ItemKind :: Err => has_err = true ,
164151 }
@@ -168,9 +155,11 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
168155 // errors, then don't show an additional error. This allows for appending/prepending
169156 // `compile_error!("...")` statements and reduces error noise.
170157 if must_show_error || !has_err {
171- diag. emit ( ) ;
172- } else {
173- diag. cancel ( ) ;
158+ tcx. sess . emit_err ( NakedFunctionsAsmBlock {
159+ span : tcx. def_span ( def_id) ,
160+ multiple_asms,
161+ non_asms,
162+ } ) ;
174163 }
175164 }
176165}
@@ -251,13 +240,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
251240 } )
252241 . collect ( ) ;
253242 if !unsupported_operands. is_empty ( ) {
254- struct_span_err ! (
255- self . tcx. sess,
256- unsupported_operands,
257- E0787 ,
258- "only `const` and `sym` operands are supported in naked functions" ,
259- )
260- . emit ( ) ;
243+ self . tcx . sess . emit_err ( NakedFunctionsOperands { unsupported_operands } ) ;
261244 }
262245
263246 let unsupported_options: Vec < & ' static str > = [
@@ -273,14 +256,10 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
273256 . collect ( ) ;
274257
275258 if !unsupported_options. is_empty ( ) {
276- struct_span_err ! (
277- self . tcx. sess,
259+ self . tcx . sess . emit_err ( NakedFunctionsAsmOptions {
278260 span,
279- E0787 ,
280- "asm options unsupported in naked functions: {}" ,
281- unsupported_options. join( ", " )
282- )
283- . emit ( ) ;
261+ unsupported_options : unsupported_options. join ( ", " ) ,
262+ } ) ;
284263 }
285264
286265 if !asm. options . contains ( InlineAsmOptions :: NORETURN ) {
@@ -290,20 +269,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
290269 . map_or_else ( || asm. template_strs . last ( ) . unwrap ( ) . 2 , |op| op. 1 )
291270 . shrink_to_hi ( ) ;
292271
293- struct_span_err ! (
294- self . tcx. sess,
295- span,
296- E0787 ,
297- "asm in naked functions must use `noreturn` option"
298- )
299- . span_suggestion (
300- last_span,
301- "consider specifying that the asm block is responsible \
302- for returning from the function",
303- ", options(noreturn)" ,
304- Applicability :: MachineApplicable ,
305- )
306- . emit ( ) ;
272+ self . tcx . sess . emit_err ( NakedFunctionsMustUseNoreturn { span, last_span } ) ;
307273 }
308274 }
309275}
0 commit comments