// 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 // 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 struct J { J(const T &M) : M(M) {} // CHECK: J(const T &M) : M(M) {} T M; }; J j1(Movable()); J 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 struct L { L(const Movable &M) : M(M) {} // CHECK: L(Movable M) : M(std::move(M)) {} Movable M; }; L l(Movable()); // Test with a non-instantiated template class template 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; };