summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2016-01-29 15:54:26 +0000
committerAlexander Kornienko <alexfh@google.com>2016-01-29 15:54:26 +0000
commit5aebfe2e4ac51ed95ca8751ee11e9952fda91012 (patch)
tree897515012886af8b170157589e62e55fbf9b79c0 /clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
parentbfee5f73529d1ba48746f1a059fa81e565541a23 (diff)
downloadbcm5719-llvm-5aebfe2e4ac51ed95ca8751ee11e9952fda91012.tar.gz
bcm5719-llvm-5aebfe2e4ac51ed95ca8751ee11e9952fda91012.zip
[clang-tidy] ForRangeCopyCheck that warns on and fixes unnecessary copies of loop variables.
Patch by Felix Berger! Differential revision: http://reviews.llvm.org/D13849 llvm-svn: 259199
Diffstat (limited to 'clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp')
-rw-r--r--clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp223
1 files changed, 223 insertions, 0 deletions
diff --git a/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp b/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
new file mode 100644
index 00000000000..c65160936a7
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/performance-for-range-copy.cpp
@@ -0,0 +1,223 @@
+// RUN: %check_clang_tidy %s performance-for-range-copy %t
+
+namespace std {
+
+template <typename _Tp>
+struct remove_reference { typedef _Tp type; };
+
+template <typename _Tp>
+constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
+ return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
+}
+
+} // std
+
+template <typename T>
+struct Iterator {
+ void operator++() {}
+ const T& operator*() {
+ static T* TT = new T();
+ return *TT;
+ }
+ bool operator!=(const Iterator &) { return false; }
+ typedef const T& const_reference;
+};
+template <typename T>
+struct View {
+ T begin() { return T(); }
+ T begin() const { return T(); }
+ T end() { return T(); }
+ T end() const { return T(); }
+ typedef typename T::const_reference const_reference;
+};
+
+struct ConstructorConvertible {
+};
+
+struct S {
+ S();
+ S(const S &);
+ S(const ConstructorConvertible&) {}
+ ~S();
+ S &operator=(const S &);
+};
+
+struct Convertible {
+ operator S() const {
+ return S();
+ }
+};
+
+void negativeConstReference() {
+ for (const S &S1 : View<Iterator<S>>()) {
+ }
+}
+
+void negativeUserDefinedConversion() {
+ Convertible C[0];
+ for (const S &S1 : C) {
+ }
+}
+
+void negativeImplicitConstructorConversion() {
+ ConstructorConvertible C[0];
+ for (const S &S1 : C) {
+ }
+}
+
+template <typename T>
+void uninstantiated() {
+ for (const S S1 : View<Iterator<S>>()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is not a reference type; this creates a copy in each iteration; consider making this a reference [performance-for-range-copy]
+ // CHECK-FIXES: {{^}} for (const S& S1 : View<Iterator<S>>()) {}
+
+ // Don't warn on dependent types.
+ for (const T t1 : View<Iterator<T>>()) {
+ }
+}
+
+template <typename T>
+void instantiated() {
+ for (const S S2 : View<Iterator<S>>()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is {{.*}}
+ // CHECK-FIXES: {{^}} for (const S& S2 : View<Iterator<S>>()) {}
+
+ for (const T T2 : View<Iterator<T>>()) {}
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: the loop variable's type is {{.*}}
+ // CHECK-FIXES: {{^}} for (const T& T2 : View<Iterator<T>>()) {}
+}
+
+template <typename T>
+void instantiatedNegativeTypedefConstReference() {
+ for (typename T::const_reference T2 : T()) {
+ S S1 = T2;
+ }
+}
+
+void f() {
+ instantiated<int>();
+ instantiated<S>();
+ instantiatedNegativeTypedefConstReference<View<Iterator<S>>>();
+}
+
+struct Mutable {
+ Mutable() {}
+ Mutable(const Mutable &) = default;
+ Mutable(const Mutable &, const Mutable &) {}
+ void setBool(bool B) {}
+ bool constMethod() const {
+ return true;
+ }
+ Mutable& operator[](int I) {
+ return *this;
+ }
+ bool operator==(const Mutable &Other) const {
+ return true;
+ }
+ ~Mutable() {}
+};
+
+Mutable& operator<<(Mutable &Out, bool B) {
+ Out.setBool(B);
+ return Out;
+}
+
+bool operator!=(const Mutable& M1, const Mutable& M2) {
+ return false;
+}
+
+void use(const Mutable &M);
+void useTwice(const Mutable &M1, const Mutable &M2);
+void useByValue(Mutable M);
+void useByConstValue(const Mutable M);
+void mutate(Mutable *M);
+void mutate(Mutable &M);
+void onceConstOnceMutated(const Mutable &M1, Mutable &M2);
+
+void negativeVariableIsMutated() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ mutate(M);
+ }
+ for (auto M : View<Iterator<Mutable>>()) {
+ mutate(&M);
+ }
+ for (auto M : View<Iterator<Mutable>>()) {
+ M.setBool(true);
+ }
+}
+
+void negativeOnceConstOnceMutated() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ onceConstOnceMutated(M, M);
+ }
+}
+
+void negativeVarIsMoved() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ auto Moved = std::move(M);
+ }
+}
+
+void negativeNonConstOperatorIsInvoked() {
+ for (auto NonConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ auto& N = NonConstOperatorInvokee[0];
+ }
+}
+
+void negativeNonConstNonMemberOperatorInvoked() {
+ for (auto NonConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ NonConstOperatorInvokee << true;
+ }
+}
+
+void positiveOnlyConstMethodInvoked() {
+ for (auto M : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& M : View<Iterator<Mutable>>()) {
+ M.constMethod();
+ }
+}
+
+void positiveOnlyUsedAsConstArguments() {
+ for (auto UsedAsConst : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& UsedAsConst : View<Iterator<Mutable>>()) {
+ use(UsedAsConst);
+ useTwice(UsedAsConst, UsedAsConst);
+ useByValue(UsedAsConst);
+ useByConstValue(UsedAsConst);
+ }
+}
+
+void positiveOnlyUsedInCopyConstructor() {
+ for (auto A : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& A : View<Iterator<Mutable>>()) {
+ Mutable Copy = A;
+ Mutable Copy2(A);
+ }
+}
+
+void positiveTwoConstConstructorArgs() {
+ for (auto A : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& A : View<Iterator<Mutable>>()) {
+ Mutable Copy(A, A);
+ }
+}
+
+void PositiveConstMemberOperatorInvoked() {
+ for (auto ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ bool result = ConstOperatorInvokee == Mutable();
+ }
+}
+
+void PositiveConstNonMemberOperatorInvoked() {
+ for (auto ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
+ // CHECK-FIXES: for (const auto& ConstOperatorInvokee : View<Iterator<Mutable>>()) {
+ bool result = ConstOperatorInvokee != Mutable();
+ }
+}
OpenPOWER on IntegriCloud