1- use rustc_ast:: InlineAsmTemplatePiece ;
1+ use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
22use rustc_data_structures:: fx:: FxIndexSet ;
33use rustc_hir:: { self as hir, LangItem } ;
44use rustc_middle:: bug;
@@ -124,7 +124,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
124124 idx : usize ,
125125 reg : InlineAsmRegOrRegClass ,
126126 expr : & ' tcx hir:: Expr < ' tcx > ,
127- template : & [ InlineAsmTemplatePiece ] ,
127+ asm : & hir :: InlineAsm < ' tcx > ,
128128 is_input : bool ,
129129 tied_input : Option < ( & ' tcx hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
130130 target_features : & FxIndexSet < Symbol > ,
@@ -267,7 +267,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
267267 // Search for any use of this operand without a modifier and emit
268268 // the suggestion for them.
269269 let mut spans = vec ! [ ] ;
270- for piece in template {
270+ for piece in asm . template {
271271 if let & InlineAsmTemplatePiece :: Placeholder { operand_idx, modifier, span } = piece
272272 {
273273 if operand_idx == idx && modifier. is_none ( ) {
@@ -299,6 +299,28 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
299299 }
300300 }
301301
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+
302324 Some ( asm_ty)
303325 }
304326
@@ -399,46 +421,30 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
399421
400422 match * op {
401423 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) ;
411425 }
412426 hir:: InlineAsmOperand :: Out { reg, late : _, expr } => {
413427 if let Some ( expr) = expr {
414428 self . check_asm_operand_type (
415429 idx,
416430 reg,
417431 expr,
418- asm. template ,
432+ asm,
419433 false ,
420434 None ,
421435 target_features,
422436 ) ;
423437 }
424438 }
425439 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) ;
435441 }
436442 hir:: InlineAsmOperand :: SplitInOut { reg, late : _, in_expr, out_expr } => {
437443 let in_ty = self . check_asm_operand_type (
438444 idx,
439445 reg,
440446 in_expr,
441- asm. template ,
447+ asm,
442448 true ,
443449 None ,
444450 target_features,
@@ -448,7 +454,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
448454 idx,
449455 reg,
450456 out_expr,
451- asm. template ,
457+ asm,
452458 false ,
453459 Some ( ( in_expr, in_ty) ) ,
454460 target_features,
0 commit comments