186 lines
4.7 KiB
C++
186 lines
4.7 KiB
C++
// Since -fdelayed-template-parsing is enabled by default on Windows (as a
|
|
// Microsoft extension), -fno-delayed-template-parsing is used for the tests in
|
|
// order to have the same behavior on all systems.
|
|
//
|
|
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
|
// RUN: clang-modernize -pass-by-value %t.cpp -- -std=c++11 -fno-delayed-template-parsing -I %S
|
|
// RUN: FileCheck -input-file=%t.cpp %s
|
|
//
|
|
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
|
// RUN: clang-modernize -pass-by-value %t.cpp -- -std=c++11 -fno-delayed-template-parsing -I %S
|
|
// RUN: FileCheck -check-prefix=SAFE_RISK -input-file=%t.cpp %s
|
|
|
|
#include "basic.h"
|
|
// CHECK: #include <utility>
|
|
|
|
// Test that when the class declaration can't be modified we won't modify the
|
|
// definition either.
|
|
UnmodifiableClass::UnmodifiableClass(const Movable &M) : M(M) {}
|
|
// CHECK: UnmodifiableClass::UnmodifiableClass(const Movable &M) : M(M) {}
|
|
|
|
struct A {
|
|
A(const Movable &M) : M(M) {}
|
|
// CHECK: A(Movable M) : M(std::move(M)) {}
|
|
// SAFE_RISK: A(const Movable &M) : M(M) {}
|
|
Movable M;
|
|
};
|
|
|
|
// Test that we aren't modifying other things than a parameter
|
|
Movable GlobalObj;
|
|
struct B {
|
|
B(const Movable &M) : M(GlobalObj) {}
|
|
// CHECK: B(const Movable &M) : M(GlobalObj) {}
|
|
Movable M;
|
|
};
|
|
|
|
// Test that a parameter with more than one reference to it won't be changed.
|
|
struct C {
|
|
// Tests extra-reference in body
|
|
C(const Movable &M) : M(M) { this->i = M.a; }
|
|
// CHECK: C(const Movable &M) : M(M) { this->i = M.a; }
|
|
|
|
// Tests extra-reference in init-list
|
|
C(const Movable &M, int) : M(M), i(M.a) {}
|
|
// CHECK: C(const Movable &M, int) : M(M), i(M.a) {}
|
|
Movable M;
|
|
int i;
|
|
};
|
|
|
|
// Test that both declaration and definition are updated
|
|
struct D {
|
|
D(const Movable &M);
|
|
// CHECK: D(Movable M);
|
|
Movable M;
|
|
};
|
|
D::D(const Movable &M) : M(M) {}
|
|
// CHECK: D::D(Movable M) : M(std::move(M)) {}
|
|
|
|
// Test with default parameter
|
|
struct E {
|
|
E(const Movable &M = Movable()) : M(M) {}
|
|
// CHECK: E(Movable M = Movable()) : M(std::move(M)) {}
|
|
Movable M;
|
|
};
|
|
|
|
// Test with object that can't be moved
|
|
struct F {
|
|
F(const NotMovable &NM) : NM(NM) {}
|
|
// CHECK: F(const NotMovable &NM) : NM(NM) {}
|
|
NotMovable NM;
|
|
};
|
|
|
|
// Test unnamed parameter in declaration
|
|
struct G {
|
|
G(const Movable &);
|
|
// CHECK: G(Movable );
|
|
Movable M;
|
|
};
|
|
G::G(const Movable &M) : M(M) {}
|
|
// CHECK: G::G(Movable M) : M(std::move(M)) {}
|
|
|
|
// Test parameter with and without qualifier
|
|
namespace ns_H {
|
|
typedef ::Movable HMovable;
|
|
}
|
|
struct H {
|
|
H(const ns_H::HMovable &M);
|
|
// CHECK: H(ns_H::HMovable M);
|
|
ns_H::HMovable M;
|
|
};
|
|
using namespace ns_H;
|
|
H::H(const HMovable &M) : M(M) {}
|
|
// CHECK: H(HMovable M) : M(std::move(M)) {}
|
|
|
|
// Try messing up with macros
|
|
#define MOVABLE_PARAM(Name) const Movable & Name
|
|
// CHECK: #define MOVABLE_PARAM(Name) const Movable & Name
|
|
struct I {
|
|
I(MOVABLE_PARAM(M)) : M(M) {}
|
|
// CHECK: I(MOVABLE_PARAM(M)) : M(M) {}
|
|
Movable M;
|
|
};
|
|
#undef MOVABLE_PARAM
|
|
|
|
// Test that templates aren't modified
|
|
template <typename T> struct J {
|
|
J(const T &M) : M(M) {}
|
|
// CHECK: J(const T &M) : M(M) {}
|
|
T M;
|
|
};
|
|
J<Movable> j1(Movable());
|
|
J<NotMovable> j2(NotMovable());
|
|
|
|
struct K_Movable {
|
|
K_Movable() = default;
|
|
K_Movable(const K_Movable &) = default;
|
|
K_Movable(K_Movable &&o) { dummy = o.dummy; }
|
|
int dummy;
|
|
};
|
|
|
|
// Test with movable type with an user defined move constructor.
|
|
struct K {
|
|
K(const K_Movable &M) : M(M) {}
|
|
// CHECK: K(K_Movable M) : M(std::move(M)) {}
|
|
K_Movable M;
|
|
};
|
|
|
|
template <typename T> struct L {
|
|
L(const Movable &M) : M(M) {}
|
|
// CHECK: L(Movable M) : M(std::move(M)) {}
|
|
Movable M;
|
|
};
|
|
L<int> l(Movable());
|
|
|
|
// Test with a non-instantiated template class
|
|
template <typename T> struct N {
|
|
N(const Movable &M) : M(M) {}
|
|
// CHECK: N(Movable M) : M(std::move(M)) {}
|
|
|
|
Movable M;
|
|
T A;
|
|
};
|
|
|
|
// Test with value parameter
|
|
struct O {
|
|
O(Movable M) : M(M) {}
|
|
// CHECK: O(Movable M) : M(std::move(M)) {}
|
|
Movable M;
|
|
};
|
|
|
|
// Test with a const-value parameter
|
|
struct P {
|
|
P(const Movable M) : M(M) {}
|
|
// CHECK: P(const Movable M) : M(M) {}
|
|
Movable M;
|
|
};
|
|
|
|
// Test with multiples parameters where some need to be changed and some don't
|
|
// need to.
|
|
struct Q {
|
|
Q(const Movable &A, const Movable &B, const Movable &C, double D)
|
|
: A(A), B(B), C(C), D(D) {}
|
|
// CHECK: Q(const Movable &A, Movable B, Movable C, double D)
|
|
// CHECK-NEXT: : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
|
|
const Movable &A;
|
|
Movable B;
|
|
Movable C;
|
|
double D;
|
|
};
|
|
|
|
// Test that value-parameters with a nested name specifier are left as-is
|
|
namespace ns_R {
|
|
typedef ::Movable RMovable;
|
|
}
|
|
struct R {
|
|
R(ns_R::RMovable M) : M(M) {}
|
|
// CHECK: R(ns_R::RMovable M) : M(std::move(M)) {}
|
|
ns_R::RMovable M;
|
|
};
|
|
|
|
// Test with rvalue parameter
|
|
struct S {
|
|
S(Movable &&M) : M(M) {}
|
|
// CHECK: S(Movable &&M) : M(M) {}
|
|
Movable M;
|
|
};
|