Files
TheRock/compiler/amd-llvm/clang-tools-extra/test/clang-tidy/checkers/performance/use-std-move.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

399 lines
13 KiB
C++

// RUN: %check_clang_tidy %s performance-use-std-move %t
// Definitions used in the tests
// -----------------------------
#include <utility>
struct NonTrivialMoveAssign {
NonTrivialMoveAssign() = default;
NonTrivialMoveAssign(const NonTrivialMoveAssign&) = default;
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;
};
struct NoDefaultedMoveAssign {
NoDefaultedMoveAssign& operator=(const NoDefaultedMoveAssign&);
NoDefaultedMoveAssign& operator=(NoDefaultedMoveAssign&&) = default;
NoMoveAssign Field;
};
struct PrivateMoveAssign {
PrivateMoveAssign& operator=(const PrivateMoveAssign&);
private:
PrivateMoveAssign& operator=(PrivateMoveAssign&&);
};
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-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(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-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
// Check moving already moved values
// ---------------------------------
void NonConvertibleNonTrivialMoveAssignAlreadyMoved(NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
// No message expected, it's already moved
target = std::move(source);
}
void NonConvertibleNonTrivialMoveAssignFromLValueAlreadyMoved(NonTrivialMoveAssign& target, NonTrivialMoveAssign&& source) {
// No message expected, it's already moved
target = std::move(source);
}
// Check moving within different context
// -------------------------------------
struct SomeRecord {
void ConvertibleNonTrivialMoveAssignWithinMethod(NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
// CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
};
auto ConvertibleNonTrivialMoveAssignWithinLambda = [](NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
// CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
};
void SomeFunction(NonTrivialMoveAssign source0, NonTrivialMoveAssign const &source1) {
auto NonConvertibleNonTrivialMoveAssignWithinLambdaAsCaptureByRef = [&](NonTrivialMoveAssign& target) {
// No message expected, cannot move a non-local variable.
target = source0;
// No message expected, cannot move a non-local variable.
target = source1;
};
auto ConvertibleNonTrivialMoveAssignWithinLambdaAsCapture = [=](NonTrivialMoveAssign& target) {
// No message expected, cannot move a non-local variable.
target = source0;
// No message expected, cannot move a non-local variable.
target = source1;
};
}
void ConvertibleNonTrivialMoveAssignShadowing(NonTrivialMoveAssign& target, NoMoveAssign source) {
{
NonTrivialMoveAssign source;
// CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
}
void ConvertibleNonTrivialMoveAssignShadowed(NoMoveAssign& target, NonTrivialMoveAssign source) {
{
NoMoveAssign source;
// No message expected, `source' refers to a non-movable variable.
target = source;
}
}
#define ASSIGN(x, y) x = y
void ConvertibleNonTrivialMoveAssignWithinMacro(NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
// No message expected, assignment within a macro.
ASSIGN(target, source);
}
template<class T>
void ConvertibleNonTrivialMoveAssignWithTemplateSource(NonTrivialMoveAssign& target, T source) {
// No message expected, type of source cannot be matched against `target's type.
target = source;
}
template<class T>
void ConvertibleNonTrivialMoveAssignWithTemplateTarget(T& target, NonTrivialMoveAssign source) {
// No message expected, type of target cannot be matched against `source's type.
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-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(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;
}
struct NonConvertibleNonTrivialMoveAssignFromMember {
NonTrivialMoveAssign source;
void NonConvertibleNonTrivialMoveAssignFromStatic(NonTrivialMoveAssign& target) {
// No message, `source' is not a local variable.
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-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
struct ConvertibleNonTrivialMoveAssignToMember {
NonTrivialMoveAssign target;
void NonConvertibleNonTrivialMoveAssignFromStatic(NonTrivialMoveAssign source) {
// CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
};
void ConvertibleNonTrivialMoveAssignToExtern(NonTrivialMoveAssign source) {
extern NonTrivialMoveAssign target;
// CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
void ConvertibleNonTrivialMoveAssignToTLS(NonTrivialMoveAssign source) {
thread_local NonTrivialMoveAssign target;
// CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
NonTrivialMoveAssign global_target;
void ConvertibleNonTrivialMoveAssignToGlobal(NonTrivialMoveAssign source) {
// CHECK-MESSAGES: [[@LINE+1]]:19: warning: 'source' could be moved here [performance-use-std-move]
global_target = source;
// CHECK-FIXES: global_target = std::move(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-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(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-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
else {
source.stuff();
// CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(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 incomplete definition
// ----------------------------------
struct fwd_cls;
struct fwd_cls {
void ConvertibleNonTrivialMoveAssignReferecingForwardDecl(fwd_cls src) {
// CHECK-MESSAGES: [[@LINE+2]]:13: warning: 'src' could be moved here [performance-use-std-move]
// CHECK-FIXES: *this = std::move(src);
*this = src;
}
fwd_cls &operator=(const fwd_cls &C);
fwd_cls &operator=(fwd_cls &&);
};
// 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;
}
void InvalidPrivateMoveAssign(PrivateMoveAssign& target, PrivateMoveAssign source) {
// No message expected, moving is private.
target = source;
}
void DeletedDefaultMoveAssign(NoDefaultedMoveAssign& target, NoDefaultedMoveAssign source) {
// No message expected, default move is invalid.
target = source;
}
// Check moving within control-flow
// --------------------------------
void ConvertibleNonTrivialMoveAssignWithinTestPred(bool pred, NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
// CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
if (pred)
target = target;
}
void NonConvertibleNonTrivialMoveAssignWithinTestPred(bool pred, NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
target = source;
if (pred)
source.stuff();
}
void ConvertibleNonTrivialMoveAssignWithinTestBothPred(bool pred, NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
// CHECK-MESSAGES: [[@LINE+1]]:12: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
if (pred)
target = target;
else
target.stuff();
}
void NonConvertibleNonTrivialMoveAssignWithinLoop(unsigned count, NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
while(--count)
target = source;
}
void ConvertibleNonTrivialMoveAssignWithinTestMultiplePred(bool pred0, bool pred1, NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
if(pred0) {
// CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
else {
if (pred1) {
// CHECK-MESSAGES: [[@LINE+1]]:16: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
}
else {
target.stuff();
}
}
}
void NonConvertibleNonTrivialMoveAssignWithinTestMultiplePred(bool pred0, bool pred1, NonTrivialMoveAssign& target, NonTrivialMoveAssign source) {
target = source;
if(pred0) {
target.stuff();
}
else {
// CHECK-MESSAGES: [[@LINE+1]]:14: warning: 'source' could be moved here [performance-use-std-move]
target = source;
// CHECK-FIXES: target = std::move(source);
if (pred1) {
target.stuff();
}
}
}