@@ -4,6 +4,7 @@ use self::State::*;
44
55use rustc_data_structures:: thin_vec:: ThinVec ;
66
7+ use errors:: DiagnosticBuilder ;
78use syntax:: ast;
89use syntax:: ext:: base;
910use syntax:: ext:: base:: * ;
@@ -51,6 +52,34 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
5152 feature_gate:: EXPLAIN_ASM ) ;
5253 }
5354
55+ let mut inline_asm = match parse_inline_asm ( cx, sp, tts) {
56+ Ok ( Some ( inline_asm) ) => inline_asm,
57+ Ok ( None ) => return DummyResult :: expr ( sp) ,
58+ Err ( mut err) => {
59+ err. emit ( ) ;
60+ return DummyResult :: expr ( sp) ;
61+ }
62+ } ;
63+
64+ // If there are no outputs, the inline assembly is executed just for its side effects,
65+ // so ensure that it is volatile
66+ if inline_asm. outputs . is_empty ( ) {
67+ inline_asm. volatile = true ;
68+ }
69+
70+ MacEager :: expr ( P ( ast:: Expr {
71+ id : ast:: DUMMY_NODE_ID ,
72+ node : ast:: ExprKind :: InlineAsm ( P ( inline_asm) ) ,
73+ span : sp,
74+ attrs : ThinVec :: new ( ) ,
75+ } ) )
76+ }
77+
78+ fn parse_inline_asm < ' a > (
79+ cx : & mut ExtCtxt < ' a > ,
80+ sp : Span ,
81+ tts : & [ tokenstream:: TokenTree ] ,
82+ ) -> Result < Option < ast:: InlineAsm > , DiagnosticBuilder < ' a > > {
5483 // Split the tts before the first colon, to avoid `asm!("x": y)` being
5584 // parsed as `asm!(z)` with `z = "x": y` which is type ascription.
5685 let first_colon = tts. iter ( )
@@ -80,22 +109,33 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
80109 if asm_str_style. is_some ( ) {
81110 // If we already have a string with instructions,
82111 // ending up in Asm state again is an error.
83- span_err ! ( cx, sp, E0660 , "malformed inline assembly" ) ;
84- return DummyResult :: expr ( sp) ;
112+ return Err ( struct_span_err ! (
113+ cx. parse_sess. span_diagnostic,
114+ sp,
115+ E0660 ,
116+ "malformed inline assembly"
117+ ) ) ;
85118 }
86119 // Nested parser, stop before the first colon (see above).
87120 let mut p2 = cx. new_parser_from_tts ( & tts[ ..first_colon] ) ;
88- let ( s, style) = match expr_to_string ( cx,
89- panictry ! ( p2. parse_expr( ) ) ,
90- "inline assembly must be a string literal" ) {
91- Some ( ( s, st) ) => ( s, st) ,
92- // let compilation continue
93- None => return DummyResult :: expr ( sp) ,
94- } ;
121+
122+ if p2. token == token:: Eof {
123+ let mut err =
124+ cx. struct_span_err ( sp, "macro requires a string literal as an argument" ) ;
125+ err. span_label ( sp, "string literal required" ) ;
126+ return Err ( err) ;
127+ }
128+
129+ let expr = p2. parse_expr ( ) ?;
130+ let ( s, style) =
131+ match expr_to_string ( cx, expr, "inline assembly must be a string literal" ) {
132+ Some ( ( s, st) ) => ( s, st) ,
133+ None => return Ok ( None ) ,
134+ } ;
95135
96136 // This is most likely malformed.
97137 if p2. token != token:: Eof {
98- let mut extra_tts = panictry ! ( p2. parse_all_token_trees( ) ) ;
138+ let mut extra_tts = p2. parse_all_token_trees ( ) ? ;
99139 extra_tts. extend ( tts[ first_colon..] . iter ( ) . cloned ( ) ) ;
100140 p = parse:: stream_to_parser ( cx. parse_sess , extra_tts. into_iter ( ) . collect ( ) ) ;
101141 }
@@ -105,18 +145,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
105145 }
106146 Outputs => {
107147 while p. token != token:: Eof && p. token != token:: Colon && p. token != token:: ModSep {
108-
109148 if !outputs. is_empty ( ) {
110149 p. eat ( & token:: Comma ) ;
111150 }
112151
113- let ( constraint, _str_style ) = panictry ! ( p. parse_str( ) ) ;
152+ let ( constraint, _ ) = p. parse_str ( ) ? ;
114153
115154 let span = p. prev_span ;
116155
117- panictry ! ( p. expect( & token:: OpenDelim ( token:: Paren ) ) ) ;
118- let out = panictry ! ( p. parse_expr( ) ) ;
119- panictry ! ( p. expect( & token:: CloseDelim ( token:: Paren ) ) ) ;
156+ p. expect ( & token:: OpenDelim ( token:: Paren ) ) ? ;
157+ let expr = p. parse_expr ( ) ? ;
158+ p. expect ( & token:: CloseDelim ( token:: Paren ) ) ? ;
120159
121160 // Expands a read+write operand into two operands.
122161 //
@@ -143,20 +182,19 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
143182 let is_indirect = constraint_str. contains ( "*" ) ;
144183 outputs. push ( ast:: InlineAsmOutput {
145184 constraint : output. unwrap_or ( constraint) ,
146- expr : out ,
185+ expr,
147186 is_rw,
148187 is_indirect,
149188 } ) ;
150189 }
151190 }
152191 Inputs => {
153192 while p. token != token:: Eof && p. token != token:: Colon && p. token != token:: ModSep {
154-
155193 if !inputs. is_empty ( ) {
156194 p. eat ( & token:: Comma ) ;
157195 }
158196
159- let ( constraint, _str_style ) = panictry ! ( p. parse_str( ) ) ;
197+ let ( constraint, _ ) = p. parse_str ( ) ? ;
160198
161199 if constraint. as_str ( ) . starts_with ( "=" ) {
162200 span_err ! ( cx, p. prev_span, E0662 ,
@@ -166,21 +204,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
166204 "input operand constraint contains '+'" ) ;
167205 }
168206
169- panictry ! ( p. expect( & token:: OpenDelim ( token:: Paren ) ) ) ;
170- let input = panictry ! ( p. parse_expr( ) ) ;
171- panictry ! ( p. expect( & token:: CloseDelim ( token:: Paren ) ) ) ;
207+ p. expect ( & token:: OpenDelim ( token:: Paren ) ) ? ;
208+ let input = p. parse_expr ( ) ? ;
209+ p. expect ( & token:: CloseDelim ( token:: Paren ) ) ? ;
172210
173211 inputs. push ( ( constraint, input) ) ;
174212 }
175213 }
176214 Clobbers => {
177215 while p. token != token:: Eof && p. token != token:: Colon && p. token != token:: ModSep {
178-
179216 if !clobs. is_empty ( ) {
180217 p. eat ( & token:: Comma ) ;
181218 }
182219
183- let ( s, _str_style ) = panictry ! ( p. parse_str( ) ) ;
220+ let ( s, _ ) = p. parse_str ( ) ? ;
184221
185222 if OPTIONS . iter ( ) . any ( |& opt| s == opt) {
186223 cx. span_warn ( p. prev_span , "expected a clobber, found an option" ) ;
@@ -193,7 +230,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
193230 }
194231 }
195232 Options => {
196- let ( option, _str_style ) = panictry ! ( p. parse_str( ) ) ;
233+ let ( option, _ ) = p. parse_str ( ) ? ;
197234
198235 if option == "volatile" {
199236 // Indicates that the inline assembly has side effects
@@ -234,26 +271,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
234271 }
235272 }
236273
237- // If there are no outputs, the inline assembly is executed just for its side effects,
238- // so ensure that it is volatile
239- if outputs. is_empty ( ) {
240- volatile = true ;
241- }
242-
243- MacEager :: expr ( P ( ast:: Expr {
244- id : ast:: DUMMY_NODE_ID ,
245- node : ast:: ExprKind :: InlineAsm ( P ( ast:: InlineAsm {
246- asm,
247- asm_str_style : asm_str_style. unwrap ( ) ,
248- outputs,
249- inputs,
250- clobbers : clobs,
251- volatile,
252- alignstack,
253- dialect,
254- ctxt : cx. backtrace ( ) ,
255- } ) ) ,
256- span : sp,
257- attrs : ThinVec :: new ( ) ,
274+ Ok ( Some ( ast:: InlineAsm {
275+ asm,
276+ asm_str_style : asm_str_style. unwrap ( ) ,
277+ outputs,
278+ inputs,
279+ clobbers : clobs,
280+ volatile,
281+ alignstack,
282+ dialect,
283+ ctxt : cx. backtrace ( ) ,
258284 } ) )
259285}
0 commit comments