For destination = Arc::clone(move arg0) and destination = ptr::read(move arg0), destination = alias copy args0 For AtomicPtr::store(move args0, move args1, move args2), args0 = copy args1 For other callsites like `destination = call fn(move args0)`, heuristically assumes that destination = copy args0
(&mut self, terminator: &Terminator<'tcx>, _location: Location)
| 603 | /// heuristically assumes that |
| 604 | /// destination = copy args0 |
| 605 | fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, _location: Location) { |
| 606 | if let TerminatorKind::Call { |
| 607 | func, |
| 608 | args, |
| 609 | destination, |
| 610 | .. |
| 611 | } = &terminator.kind |
| 612 | { |
| 613 | match ( |
| 614 | args.iter() |
| 615 | .map(|x| x.node.clone()) |
| 616 | .collect::<Vec<_>>() |
| 617 | .as_slice(), |
| 618 | destination, |
| 619 | ) { |
| 620 | (&[Operand::Move(arg)], dest) | (&[Operand::Copy(arg)], dest) => { |
| 621 | let func_ty = func.ty(self.body, self.tcx); |
| 622 | if let TyKind::FnDef(def_id, substs) = func_ty.kind() { |
| 623 | if ownership::is_arc_or_rc_clone(*def_id, substs, self.tcx) |
| 624 | || ownership::is_ptr_read(*def_id, self.tcx) |
| 625 | { |
| 626 | return self.process_alias_copy(arg.as_ref(), dest.as_ref()); |
| 627 | } |
| 628 | } |
| 629 | self.process_call_arg_dest(arg.as_ref(), dest.as_ref()); |
| 630 | } |
| 631 | (&[Operand::Move(arg), _], dest) => { |
| 632 | let func_ty = func.ty(self.body, self.tcx); |
| 633 | if let TyKind::FnDef(def_id, _) = func_ty.kind() { |
| 634 | if ownership::is_index(*def_id, self.tcx) { |
| 635 | // index(arg0, arg1) |
| 636 | // e.g., <String as Index<std::ops::Range<usize>>>::index(move _97, move _98) |
| 637 | self.process_call_arg_dest(arg.as_ref(), dest.as_ref()) |
| 638 | } |
| 639 | } |
| 640 | } |
| 641 | (&[Operand::Move(arg0), Operand::Move(arg1), Operand::Move(_arg2)], _dest) |
| 642 | | (&[Operand::Move(arg0), Operand::Move(arg1), Operand::Copy(_arg2)], _dest) => { |
| 643 | let func_ty = func.ty(self.body, self.tcx); |
| 644 | if let TyKind::FnDef(def_id, list) = func_ty.kind() { |
| 645 | if is_atomic_ptr_store(*def_id, list, self.tcx) { |
| 646 | // AtomicPtr::store(arg0, arg1, ord) equals to arg0 = call(arg1) |
| 647 | self.process_call_arg_dest(arg1.as_ref(), arg0.as_ref()) |
| 648 | } |
| 649 | } |
| 650 | } |
| 651 | _ => {} |
| 652 | } |
| 653 | } |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | /// We do not use Must/May/Not since the pointer analysis implementation is overapproximate. |
nothing calls this directly
no test coverage detected