1 // RUN: %check_clang_tidy %s performance-for-range-copy %t -- \ 2 // RUN: -config="{CheckOptions: [{key: performance-for-range-copy.AllowedTypes, value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$;qualified::Type;::fully::QualifiedType'}]}" \ 3 // RUN: -- -fno-delayed-template-parsing 4 5 template <typename T> 6 struct Iterator { operator ++Iterator7 void operator++() {} operator *Iterator8 const T& operator*() { 9 static T* TT = new T(); 10 return *TT; 11 } operator !=Iterator12 bool operator!=(const Iterator &) { return false; } 13 typedef const T& const_reference; 14 }; 15 template <typename T> 16 struct View { beginView17 T begin() { return T(); } beginView18 T begin() const { return T(); } endView19 T end() { return T(); } endView20 T end() const { return T(); } 21 typedef typename T::const_reference const_reference; 22 }; 23 24 struct SmartPointer { 25 ~SmartPointer(); 26 }; 27 28 struct smart_pointer { 29 ~smart_pointer(); 30 }; 31 32 struct SmartPtr { 33 ~SmartPtr(); 34 }; 35 36 struct smart_ptr { 37 ~smart_ptr(); 38 }; 39 40 struct SmartReference { 41 ~SmartReference(); 42 }; 43 44 struct smart_reference { 45 ~smart_reference(); 46 }; 47 48 struct SmartRef { 49 ~SmartRef(); 50 }; 51 52 struct smart_ref { 53 ~smart_ref(); 54 }; 55 56 struct OtherType { 57 ~OtherType(); 58 }; 59 60 template <typename T> struct SomeComplexTemplate { 61 ~SomeComplexTemplate(); 62 }; 63 64 typedef SomeComplexTemplate<int> NotTooComplexRef; 65 66 namespace qualified { 67 struct Type { 68 ~Type(); 69 }; 70 } // namespace qualified 71 72 namespace fully { 73 struct QualifiedType { 74 ~QualifiedType(); 75 }; 76 } // namespace fully 77 negativeSmartPointer()78void negativeSmartPointer() { 79 for (auto P : View<Iterator<SmartPointer>>()) { 80 auto P2 = P; 81 } 82 } 83 negative_smart_pointer()84void negative_smart_pointer() { 85 for (auto p : View<Iterator<smart_pointer>>()) { 86 auto p2 = p; 87 } 88 } 89 negativeSmartPtr()90void negativeSmartPtr() { 91 for (auto P : View<Iterator<SmartPtr>>()) { 92 auto P2 = P; 93 } 94 } 95 negative_smart_ptr()96void negative_smart_ptr() { 97 for (auto p : View<Iterator<smart_ptr>>()) { 98 auto p2 = p; 99 } 100 } 101 negativeSmartReference()102void negativeSmartReference() { 103 for (auto R : View<Iterator<SmartReference>>()) { 104 auto R2 = R; 105 } 106 } 107 negative_smart_reference()108void negative_smart_reference() { 109 for (auto r : View<Iterator<smart_reference>>()) { 110 auto r2 = r; 111 } 112 } 113 negativeSmartRef()114void negativeSmartRef() { 115 for (auto R : View<Iterator<SmartRef>>()) { 116 auto R2 = R; 117 } 118 } 119 negative_smart_ref()120void negative_smart_ref() { 121 for (auto r : View<Iterator<smart_ref>>()) { 122 auto r2 = r; 123 } 124 } 125 positiveOtherType()126void positiveOtherType() { 127 for (auto O : View<Iterator<OtherType>>()) { 128 // 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] 129 // CHECK-FIXES: for (const auto& O : View<Iterator<OtherType>>()) { 130 auto O2 = O; 131 } 132 } 133 negativeNotTooComplexRef()134void negativeNotTooComplexRef() { 135 for (NotTooComplexRef R : View<Iterator<NotTooComplexRef>>()) { 136 auto R2 = R; 137 } 138 } 139 negativeQualified()140void negativeQualified() { 141 for (auto Q : View<Iterator<qualified::Type>>()) { 142 auto Q2 = Q; 143 } 144 using qualified::Type; 145 for (auto Q : View<Iterator<Type>>()) { 146 auto Q2 = Q; 147 } 148 } 149 negativeFullyQualified()150void negativeFullyQualified() { 151 for (auto Q : View<Iterator<fully::QualifiedType>>()) { 152 auto Q2 = Q; 153 } 154 using fully::QualifiedType; 155 for (auto Q : View<Iterator<QualifiedType>>()) { 156 auto Q2 = Q; 157 } 158 } 159