diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 84e8a010738..38a5829b3f7 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -16,8 +16,8 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::{ - def_id, BinOpKind, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, GenericArg, HirId, LoopSource, - MatchSource, Mutability, Node, Pat, PatKind, QPath, Stmt, StmtKind, + def_id, BinOpKind, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, GenericArg, HirId, InlineAsmOperand, + LoopSource, MatchSource, Mutability, Node, Pat, PatKind, QPath, Stmt, StmtKind, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -693,6 +693,20 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { NeverLoopResult::AlwaysBreak } }, + ExprKind::InlineAsm(ref asm) => asm + .operands + .iter() + .map(|o| match o { + InlineAsmOperand::In { expr, .. } + | InlineAsmOperand::InOut { expr, .. } + | InlineAsmOperand::Const { expr } + | InlineAsmOperand::Sym { expr } => never_loop_expr(expr, main_loop_id), + InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id), + InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { + never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id) + }, + }) + .fold(NeverLoopResult::Otherwise, combine_both), ExprKind::Struct(_, _, None) | ExprKind::Yield(_, _) | ExprKind::Closure(_, _, _, _, _) diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 74601008dca..bbcf396eef7 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -469,6 +469,10 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Ret(None) = {};", current); } }, + ExprKind::InlineAsm(_) => { + println!("InlineAsm(_) = {};", current); + println!(" // unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); + }, ExprKind::LlvmInlineAsm(_) => { println!("LlvmInlineAsm(_) = {};", current); println!(" // unimplemented: `ExprKind::LlvmInlineAsm` is not further destructured at the moment"); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index bd7da57c665..92c27e79452 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,10 +1,11 @@ use crate::consts::{constant_context, constant_simple}; use crate::utils::differing_macro_contexts; +use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{ BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FnRetTy, GenericArg, - GenericArgs, Guard, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, Ty, - TyKind, TypeBinding, + GenericArgs, Guard, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path, PathSegment, QPath, + Stmt, StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lint::LateContext; use rustc_middle::ich::StableHashingContextProvider; @@ -474,6 +475,56 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(a); self.hash_expr(i); }, + ExprKind::InlineAsm(ref asm) => { + for piece in asm.template { + match piece { + InlineAsmTemplatePiece::String(s) => s.hash(&mut self.s), + InlineAsmTemplatePiece::Placeholder { + operand_idx, + modifier, + span: _, + } => { + operand_idx.hash(&mut self.s); + modifier.hash(&mut self.s); + }, + } + } + asm.options.hash(&mut self.s); + for op in asm.operands { + match op { + InlineAsmOperand::In { reg, expr } => { + reg.hash(&mut self.s); + self.hash_expr(expr); + }, + InlineAsmOperand::Out { reg, late, expr } => { + reg.hash(&mut self.s); + late.hash(&mut self.s); + if let Some(expr) = expr { + self.hash_expr(expr); + } + }, + InlineAsmOperand::InOut { reg, late, expr } => { + reg.hash(&mut self.s); + late.hash(&mut self.s); + self.hash_expr(expr); + }, + InlineAsmOperand::SplitInOut { + reg, + late, + in_expr, + out_expr, + } => { + reg.hash(&mut self.s); + late.hash(&mut self.s); + self.hash_expr(in_expr); + if let Some(out_expr) = out_expr { + self.hash_expr(out_expr); + } + }, + InlineAsmOperand::Const { expr } | InlineAsmOperand::Sym { expr } => self.hash_expr(expr), + } + } + }, ExprKind::LlvmInlineAsm(..) | ExprKind::Err => {}, ExprKind::Lit(ref l) => { l.node.hash(&mut self.s); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 7e8c61ba24a..748c11fac64 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -1,7 +1,7 @@ //! checks for attributes use crate::utils::get_attr; -use rustc_ast::ast::Attribute; +use rustc_ast::ast::{Attribute, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::Session; @@ -282,6 +282,31 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, e, indent + 1); } }, + hir::ExprKind::InlineAsm(ref asm) => { + println!("{}InlineAsm", ind); + println!("{}template: {}", ind, InlineAsmTemplatePiece::to_string(asm.template)); + println!("{}options: {:?}", ind, asm.options); + println!("{}operands:", ind); + for op in asm.operands { + match op { + hir::InlineAsmOperand::In { expr, .. } => print_expr(cx, expr, indent + 1), + hir::InlineAsmOperand::Out { expr, .. } => { + if let Some(expr) = expr { + print_expr(cx, expr, indent + 1); + } + }, + hir::InlineAsmOperand::InOut { expr, .. } => print_expr(cx, expr, indent + 1), + hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { + print_expr(cx, in_expr, indent + 1); + if let Some(out_expr) = out_expr { + print_expr(cx, out_expr, indent + 1); + } + }, + hir::InlineAsmOperand::Const { expr } => print_expr(cx, expr, indent + 1), + hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1), + } + } + }, hir::ExprKind::LlvmInlineAsm(ref asm) => { let inputs = &asm.inputs_exprs; let outputs = &asm.outputs_exprs; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index a8fe637d3d9..4ebe2e2852f 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -108,6 +108,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Call(..) | hir::ExprKind::Field(..) | hir::ExprKind::Index(..) + | hir::ExprKind::InlineAsm(..) | hir::ExprKind::LlvmInlineAsm(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Loop(..) @@ -150,6 +151,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Field(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Index(..) + | ast::ExprKind::InlineAsm(..) | ast::ExprKind::LlvmInlineAsm(..) | ast::ExprKind::Lit(..) | ast::ExprKind::Loop(..) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 26bf463bd29..dfa6223f1b9 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -353,7 +353,8 @@ impl Write { is_write: bool, ) -> (Option, Option) { use fmt_macros::{ - AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, Parser, Piece, + AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, ParseMode, Parser, + Piece, }; let tts = tts.clone(); @@ -376,7 +377,7 @@ impl Write { }; let tmp = fmtstr.symbol.as_str(); let mut args = vec![]; - let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false); + let mut fmt_parser = Parser::new(&tmp, None, None, false, ParseMode::Format); while let Some(piece) = fmt_parser.next() { if !fmt_parser.errors.is_empty() { return (None, expr);