================
@@ -0,0 +1,180 @@
+// RUN: %check_clang_tidy %s performance-inefficient-copy-assign %t
+
+// Definitions used in the tests
+// -----------------------------
+
+struct NonTrivialMoveAssign {
+  NonTrivialMoveAssign& operator=(const NonTrivialMoveAssign&);
+  NonTrivialMoveAssign& operator=(NonTrivialMoveAssign&&);
+  NonTrivialMoveAssign& operator+=(const NonTrivialMoveAssign&);
+  NonTrivialMoveAssign& operator+=(NonTrivialMoveAssign&&);
+  void stuff();
+};
+
+struct TrivialMoveAssign {
+  TrivialMoveAssign& operator=(const TrivialMoveAssign&);
+  TrivialMoveAssign& operator=(TrivialMoveAssign&&) = default;
+};
+
+struct NoMoveAssign {
+  NoMoveAssign& operator=(const NoMoveAssign&);
+  NoMoveAssign& operator=(NoMoveAssign&&) = delete;
+};
+
+template<class T>
+void use(T&) {}
+
+// Check moving from various reference/pointer type
+// ------------------------------------------------
+
+void ConvertibleNonTrivialMoveAssign(NonTrivialMoveAssign& target, 
NonTrivialMoveAssign source) {
+  // CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  target = source;
+}
+
+void NonProfitableNonTrivialMoveAssignPointer(NonTrivialMoveAssign*& target, 
NonTrivialMoveAssign* source) {
+  // No message expected, moving is possible but non profitable for pointer.
+  target = source;
+}
+
+void ConvertibleNonTrivialMoveAssignFromLValue(NonTrivialMoveAssign& target, 
NonTrivialMoveAssign&& source) {
+  // CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  target = source;
+}
+
+// Check moving from various storage
+// ---------------------------------
+
+void NonConvertibleNonTrivialMoveAssignFromLocal(NonTrivialMoveAssign& target) 
{
+  const NonTrivialMoveAssign source;
+  // No message, moving a const-qualified value is not valid.
+  target = source;
+}
+
+void NonConvertibleNonTrivialMoveAssignFromConst(NonTrivialMoveAssign& target) 
{
+  NonTrivialMoveAssign source;
+  // CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  target = source;
+}
+
+void NonConvertibleNonTrivialMoveAssignFromStatic(NonTrivialMoveAssign& 
target) {
+  static NonTrivialMoveAssign source;
+  // No message, the lifetime of `source' does not end with the scope of the 
function.
+  target = source;
+}
+
+void NonConvertibleNonTrivialMoveAssignFromExtern(NonTrivialMoveAssign& 
target) {
+  extern NonTrivialMoveAssign source;
+  // No message, the lifetime of `source' does not end with the scope of the 
function.
+  target = source;
+}
+
+void NonConvertibleNonTrivialMoveAssignFromTLS(NonTrivialMoveAssign& target) {
+  thread_local NonTrivialMoveAssign source;
+  // No message, the lifetime of `source' does not end with the scope of the 
function.
+  target = source;
+}
+
+NonTrivialMoveAssign global_source;
+void NonConvertibleNonTrivialMoveAssignToGlobal(NonTrivialMoveAssign& target) {
+  // No message, the lifetime of `source' does not end with the scope of the 
function.
+  target = global_source;
+}
+
+
+// Check moving to various storage
+// -------------------------------
+
+void ConvertibleNonTrivialMoveAssignToStatic(NonTrivialMoveAssign source) {
+  static NonTrivialMoveAssign target;
+  // CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  target = source;
+}
+
+void ConvertibleNonTrivialMoveAssignToExtern(NonTrivialMoveAssign source) {
+  extern NonTrivialMoveAssign target;
+  // CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  target = source;
+}
+
+void ConvertibleNonTrivialMoveAssignToTLS(NonTrivialMoveAssign source) {
+  thread_local NonTrivialMoveAssign target;
+  // CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  target = source;
+}
+
+NonTrivialMoveAssign global_target;
+void ConvertibleNonTrivialMoveAssignToGlobal(NonTrivialMoveAssign source) {
+  // CHECK-MESSAGES: [[@LINE+1]]:19: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+  global_target = source;
+}
+
+void NonConvertibleNonTrivialMoveAssignRValue(NonTrivialMoveAssign& target, 
NonTrivialMoveAssign const& source) {
+  // No message expected, moving a reference is invalid there.
+  target = source;
+}
+
+void NonProfitableTrivialMoveAssign(TrivialMoveAssign& target, 
TrivialMoveAssign source) {
+  // No message expected, moving is possible but pedantic.
+  target = source;
+}
+
+// Check moving in presence of control flow or use
+// -----------------------------------------------
+
+void ConvertibleNonTrivialMoveAssignWithBranching(bool cond, 
NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
+  if(cond) {
+    // CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+    target = source;
+  }
+}
+
+void NonConvertibleNonTrivialMoveAssignWithBranchingAndUse(bool cond, 
NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
+  if(cond) {
+    // No message expected, moving would make use invalid.
+    target = source;
+  }
+  use(source);
+}
+
+void ConvertibleNonTrivialMoveAssignBothBranches(bool cond, 
NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
+  if(cond) {
+    // CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+    target = source;
+  }
+  else {
+    source.stuff();
+    // CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here 
[performance-inefficient-copy-assign]
+    target = source;
+  }
+}
+
+void NonConvertibleNonTrivialMoveAssignWithExtraUse(NonTrivialMoveAssign& 
target, NonTrivialMoveAssign source) {
+  // No message expected, moving would make the call to `stuff' invalid.
+  target = source;
+  source.stuff();
+}
+
+void NonConvertibleNonTrivialMoveAssignInLoop(NonTrivialMoveAssign& target, 
NonTrivialMoveAssign source) {
+  // No message expected, moving would make the next iteration invalid.
+  for(int i = 0; i < 10; ++i)
+    target = source;
+}
+
+// Check moving for invalid / non profitable type or operation
+// -----------------------------------------------------------
+
+void NonConvertibleNonTrivialMoveUpdateAssign(NonTrivialMoveAssign& target, 
NonTrivialMoveAssign source) {
+  // No message currently expected, we only consider assignment.
+  target += source;
+}
+
+void NonProfitableTrivialTypeAssign(int& target, int source) {
+  // No message needed, it's correct to move but pedantic.
+  target = source;
+}
+
+void InvalidMoveAssign(NoMoveAssign& target, NoMoveAssign source) {
+  // No message expected, moving is deleted.
+  target = source;
+}
----------------
serge-sans-paille wrote:

I have a false positive with lambda, all other tests have been added.

https://github.com/llvm/llvm-project/pull/179467
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to