1
- use rustc_ast:: InlineAsmTemplatePiece ;
1
+ use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
2
2
use rustc_data_structures:: fx:: FxIndexSet ;
3
3
use rustc_hir:: { self as hir, LangItem } ;
4
4
use rustc_middle:: bug;
@@ -124,7 +124,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
124
124
idx : usize ,
125
125
reg : InlineAsmRegOrRegClass ,
126
126
expr : & ' tcx hir:: Expr < ' tcx > ,
127
- template : & [ InlineAsmTemplatePiece ] ,
127
+ asm : & hir :: InlineAsm < ' tcx > ,
128
128
is_input : bool ,
129
129
tied_input : Option < ( & ' tcx hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
130
130
target_features : & FxIndexSet < Symbol > ,
@@ -267,7 +267,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
267
267
// Search for any use of this operand without a modifier and emit
268
268
// the suggestion for them.
269
269
let mut spans = vec ! [ ] ;
270
- for piece in template {
270
+ for piece in asm . template {
271
271
if let & InlineAsmTemplatePiece :: Placeholder { operand_idx, modifier, span } = piece
272
272
{
273
273
if operand_idx == idx && modifier. is_none ( ) {
@@ -299,6 +299,28 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
299
299
}
300
300
}
301
301
302
+ match * ty. kind ( ) {
303
+ ty:: RawPtr ( _, hir:: Mutability :: Mut ) if asm. options . contains ( InlineAsmOptions :: READONLY ) =>
304
+ self
305
+ . tcx
306
+ . dcx ( )
307
+ . struct_span_warn ( expr. span , "passing a mutable pointer to asm! block with 'readonly' option." )
308
+ . with_note ( "`readonly` means that no memory write happens inside the asm! block." )
309
+ . with_note ( "This is not limited to global variables, it also includes passed pointers." )
310
+ . with_note ( "If passing this mutable pointer is intentional, remove the `readonly` attribute." )
311
+ . emit ( ) ,
312
+ ty:: RawPtr ( _, _) if asm. options . contains ( InlineAsmOptions :: NOMEM ) =>
313
+ self
314
+ . tcx
315
+ . dcx ( )
316
+ . struct_span_warn ( expr. span , "passing a pointer to asm! block with 'nomem' option." )
317
+ . with_note ( "`nomem` means that no memory write or read happens inside the asm! block." )
318
+ . with_note ( "This is not limited to global variables, it also includes passed pointers." )
319
+ . with_note ( "If passing this pointer is intentional, replace the `nomem` attribute with `readonly` or remove it completely." )
320
+ . emit ( ) ,
321
+ _ => { } // we're only interested in pointers when asm! has `nomem` or `readonly`
322
+ }
323
+
302
324
Some ( asm_ty)
303
325
}
304
326
@@ -399,46 +421,30 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
399
421
400
422
match * op {
401
423
hir:: InlineAsmOperand :: In { reg, expr } => {
402
- self . check_asm_operand_type (
403
- idx,
404
- reg,
405
- expr,
406
- asm. template ,
407
- true ,
408
- None ,
409
- target_features,
410
- ) ;
424
+ self . check_asm_operand_type ( idx, reg, expr, asm, true , None , target_features) ;
411
425
}
412
426
hir:: InlineAsmOperand :: Out { reg, late : _, expr } => {
413
427
if let Some ( expr) = expr {
414
428
self . check_asm_operand_type (
415
429
idx,
416
430
reg,
417
431
expr,
418
- asm. template ,
432
+ asm,
419
433
false ,
420
434
None ,
421
435
target_features,
422
436
) ;
423
437
}
424
438
}
425
439
hir:: InlineAsmOperand :: InOut { reg, late : _, expr } => {
426
- self . check_asm_operand_type (
427
- idx,
428
- reg,
429
- expr,
430
- asm. template ,
431
- false ,
432
- None ,
433
- target_features,
434
- ) ;
440
+ self . check_asm_operand_type ( idx, reg, expr, asm, false , None , target_features) ;
435
441
}
436
442
hir:: InlineAsmOperand :: SplitInOut { reg, late : _, in_expr, out_expr } => {
437
443
let in_ty = self . check_asm_operand_type (
438
444
idx,
439
445
reg,
440
446
in_expr,
441
- asm. template ,
447
+ asm,
442
448
true ,
443
449
None ,
444
450
target_features,
@@ -448,7 +454,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
448
454
idx,
449
455
reg,
450
456
out_expr,
451
- asm. template ,
457
+ asm,
452
458
false ,
453
459
Some ( ( in_expr, in_ty) ) ,
454
460
target_features,
0 commit comments