1 // RUN: %check_clang_tidy %s modernize-use-auto %t -- \
2 // RUN:   -config="{CheckOptions: [{key: modernize-use-auto.MinTypeNameLength, value: '0'}]}" \
3 // RUN:   -- -I %S/Inputs/modernize-use-auto -frtti
4 
5 struct A {
~AA6   virtual ~A() {}
7 };
8 
9 struct B : public A {};
10 
11 struct C {};
12 
f_static_cast()13 void f_static_cast() {
14   long l = 1;
15   int i1 = static_cast<int>(l);
16   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
17   // CHECK-FIXES: auto i1 = static_cast<int>(l);
18 
19   const int i2 = static_cast<int>(l);
20   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
21   // CHECK-FIXES: const auto i2 = static_cast<int>(l);
22 
23   long long ll = static_cast<long long>(l);
24   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
25   // CHECK-FIXES: auto ll = static_cast<long long>(l);
26   unsigned long long ull = static_cast<unsigned long long>(l);
27   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
28   // CHECK-FIXES: auto ull = static_cast<unsigned long long>(l);
29   unsigned int ui = static_cast<unsigned int>(l);
30   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
31   // CHECK-FIXES: auto ui = static_cast<unsigned int>(l);
32   long double ld = static_cast<long double>(l);
33   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
34   // CHECK-FIXES: auto ld = static_cast<long double>(l);
35 
36   A *a = new B();
37   B *b1 = static_cast<B *>(a);
38   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
39   // CHECK-FIXES: auto *b1 = static_cast<B *>(a);
40 
41   B *const b2 = static_cast<B *>(a);
42   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
43   // CHECK-FIXES: auto *const b2 = static_cast<B *>(a);
44 
45   const B *b3 = static_cast<const B *>(a);
46   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
47   // CHECK-FIXES: const auto *b3 = static_cast<const B *>(a);
48 
49   B &b4 = static_cast<B &>(*a);
50   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
51   // CHECK-FIXES: auto &b4 = static_cast<B &>(*a);
52 
53   const B &b5 = static_cast<const B &>(*a);
54   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a cast to avoid duplicating the type name
55   // CHECK-FIXES: const auto &b5 = static_cast<const B &>(*a);
56 
57   B &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
58   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
59   // CHECK-FIXES: auto &b6 = static_cast<B &>(*a), &b7 = static_cast<B &>(*a);
60 
61   // Don't warn when non-cast involved
62   long double cast = static_cast<long double>(l), noncast = 5;
63 
64   // Don't warn when auto is already being used.
65   auto i3 = static_cast<int>(l);
66   auto *b8 = static_cast<B *>(a);
67   auto &b9 = static_cast<B &>(*a);
68 }
69 
f_dynamic_cast()70 void f_dynamic_cast() {
71   A *a = new B();
72   B *b1 = dynamic_cast<B *>(a);
73   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
74   // CHECK-FIXES: auto *b1 = dynamic_cast<B *>(a);
75 
76   B &b2 = dynamic_cast<B &>(*a);
77   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
78   // CHECK-FIXES: auto &b2 = dynamic_cast<B &>(*a);
79 }
80 
f_reinterpret_cast()81 void f_reinterpret_cast() {
82   auto *a = new A();
83   C *c1 = reinterpret_cast<C *>(a);
84   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
85   // CHECK-FIXES: auto *c1 = reinterpret_cast<C *>(a);
86 
87   C &c2 = reinterpret_cast<C &>(*a);
88   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
89   // CHECK-FIXES: auto &c2 = reinterpret_cast<C &>(*a);
90 }
91 
f_const_cast()92 void f_const_cast() {
93   const A *a1 = new A();
94   A *a2 = const_cast<A *>(a1);
95   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
96   // CHECK-FIXES: auto *a2 = const_cast<A *>(a1);
97   A &a3 = const_cast<A &>(*a1);
98   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
99   // CHECK-FIXES: auto &a3 = const_cast<A &>(*a1);
100 }
101 
102 typedef unsigned char xmlChar;
103 #define BAD_CAST (xmlChar *)
104 
105 #define XMLCHAR_CAST(x) (xmlChar *)(x)
106 
107 #define CAST_IN_MACRO(x)         \
108   do {                           \
109     xmlChar *s = (xmlChar *)(x); \
110   } while (false);
111 // CHECK-FIXES: xmlChar *s = (xmlChar *)(x);
112 
f_cstyle_cast()113 void f_cstyle_cast() {
114   auto *a = new A();
115   C *c1 = (C *)a;
116   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
117   // CHECK-FIXES: auto *c1 = (C *)a;
118 
119   C &c2 = (C &)*a;
120   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
121   // CHECK-FIXES: auto &c2 = (C &)*a;
122 
123   xmlChar *s = BAD_CAST "xml";
124   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
125   // CHECK-FIXES: auto *s = BAD_CAST "xml";
126   xmlChar *t = XMLCHAR_CAST("xml");
127   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
128   // CHECK-FIXES: auto *t = XMLCHAR_CAST("xml");
129   CAST_IN_MACRO("xml");
130   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
131 }
132 
f_functional_cast()133 void f_functional_cast() {
134   long l = 1;
135   int i1 = int(l);
136   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a cast to avoid duplicating the type name
137   // CHECK-FIXES: auto i1 = int(l);
138 
139   B b;
140   A a = A(b);
141 }
142 
143 class StringRef
144 {
145 public:
146   StringRef(const char *);
147   const char *begin() const;
148   const char *end() const;
149 };
150 
151 template <typename T, typename U>
152 T template_value_cast(const U &u);
153 
154 template <typename T, typename U>
155 T *template_pointer_cast(U *u);
156 
157 template <typename T, typename U>
158 T &template_reference_cast(U &u);
159 
160 template <typename T, typename U>
161 const T *template_const_pointer_cast(const U *u);
162 
163 template <typename T, typename U>
164 const T &template_const_reference_cast(const U &u);
165 
166 template <typename T>
167 T template_value_get(StringRef s);
168 
169 struct S {
170   template <typename T>
171   const T *template_member_get();
172 };
173 
174 template <typename T>
175 T max(T t1, T t2);
176 
f_template_cast()177 void f_template_cast()
178 {
179   double d = 0;
180   int i1 = template_value_cast<int>(d);
181   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
182   // CHECK-FIXES: auto i1 = template_value_cast<int>(d);
183 
184   A *a = new B();
185   B *b1 = template_value_cast<B *>(a);
186   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
187   // CHECK-FIXES: auto *b1 = template_value_cast<B *>(a);
188   B &b2 = template_value_cast<B &>(*a);
189   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
190   // CHECK-FIXES: auto &b2 = template_value_cast<B &>(*a);
191   B *b3 = template_pointer_cast<B>(a);
192   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
193   // CHECK-FIXES: auto *b3 = template_pointer_cast<B>(a);
194   B &b4 = template_reference_cast<B>(*a);
195   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
196   // CHECK-FIXES: auto &b4 = template_reference_cast<B>(*a);
197   const B *b5 = template_const_pointer_cast<B>(a);
198   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
199   // CHECK-FIXES: const auto *b5 = template_const_pointer_cast<B>(a);
200   const B &b6 = template_const_reference_cast<B>(*a);
201   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
202   // CHECK-FIXES: const auto &b6 = template_const_reference_cast<B>(*a);
203   B *b7 = template_value_get<B *>("foo");
204   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
205   // CHECK-FIXES: auto *b7 = template_value_get<B *>("foo");
206   B *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
207   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use auto when initializing with a template cast to avoid duplicating the type name
208   // CHECK-FIXES: auto *b8 = template_value_get<B *>("foo"), *b9 = template_value_get<B *>("bar");
209 
210   S s;
211   const B *b10 = s.template_member_get<B>();
212   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use auto when initializing with a template cast to avoid duplicating the type name
213   // CHECK-FIXES: const auto *b10 = s.template_member_get<B>();
214 
215   // Don't warn when auto is already being used.
216   auto i2 = template_value_cast<int>(d);
217   auto *i3 = template_value_cast<int *>(d);
218   auto **i4 = template_value_cast<int **>(d);
219   auto &i5 = template_reference_cast<int>(d);
220 
221   // Don't warn for implicit template arguments.
222   int i6 = max(i1, i2);
223 
224   // Don't warn for mismatched var and initializer types.
225   A *a1 = template_value_cast<B *>(a);
226 
227   // Don't warn for mismatched var types.
228   B *b11 = template_value_get<B *>("foo"), b12 = template_value_get<B>("bar");
229 
230   // Don't warn for implicit variables.
231   for (auto &c : template_reference_cast<StringRef>(*a)) {
232   }
233 }
234