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()78 void negativeSmartPointer() {
79   for (auto P : View<Iterator<SmartPointer>>()) {
80     auto P2 = P;
81   }
82 }
83 
negative_smart_pointer()84 void negative_smart_pointer() {
85   for (auto p : View<Iterator<smart_pointer>>()) {
86     auto p2 = p;
87   }
88 }
89 
negativeSmartPtr()90 void negativeSmartPtr() {
91   for (auto P : View<Iterator<SmartPtr>>()) {
92     auto P2 = P;
93   }
94 }
95 
negative_smart_ptr()96 void negative_smart_ptr() {
97   for (auto p : View<Iterator<smart_ptr>>()) {
98     auto p2 = p;
99   }
100 }
101 
negativeSmartReference()102 void negativeSmartReference() {
103   for (auto R : View<Iterator<SmartReference>>()) {
104     auto R2 = R;
105   }
106 }
107 
negative_smart_reference()108 void negative_smart_reference() {
109   for (auto r : View<Iterator<smart_reference>>()) {
110     auto r2 = r;
111   }
112 }
113 
negativeSmartRef()114 void negativeSmartRef() {
115   for (auto R : View<Iterator<SmartRef>>()) {
116     auto R2 = R;
117   }
118 }
119 
negative_smart_ref()120 void negative_smart_ref() {
121   for (auto r : View<Iterator<smart_ref>>()) {
122     auto r2 = r;
123   }
124 }
125 
positiveOtherType()126 void 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()134 void negativeNotTooComplexRef() {
135   for (NotTooComplexRef R : View<Iterator<NotTooComplexRef>>()) {
136     auto R2 = R;
137   }
138 }
139 
negativeQualified()140 void 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()150 void 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