1 // RUN: %check_clang_tidy -std=c++11-or-later %s abseil-upgrade-duration-conversions %t -- -- -I%S/Inputs
2 // FIXME: Fix the checker to work in C++17 mode.
3 
4 using int64_t = long long;
5 
6 #include "absl/time/time.h"
7 
8 template <typename T> struct ConvertibleTo {
9   operator T() const;
10 };
11 
12 template <typename T>
13 ConvertibleTo<T> operator+(ConvertibleTo<T>, ConvertibleTo<T>);
14 
15 template <typename T>
16 ConvertibleTo<T> operator*(ConvertibleTo<T>, ConvertibleTo<T>);
17 
arithmeticOperatorBasicPositive()18 void arithmeticOperatorBasicPositive() {
19   absl::Duration d;
20   d *= ConvertibleTo<int64_t>();
21   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
22   // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int64_t>());
23   d /= ConvertibleTo<int64_t>();
24   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
25   // CHECK-FIXES: d /= static_cast<int64_t>(ConvertibleTo<int64_t>());
26   d = ConvertibleTo<int64_t>() * d;
27   // CHECK-MESSAGES: [[@LINE-1]]:7: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
28   // CHECK-FIXES: d = static_cast<int64_t>(ConvertibleTo<int64_t>()) * d;
29   d = d * ConvertibleTo<int64_t>();
30   // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
31   // CHECK-FIXES: d = d * static_cast<int64_t>(ConvertibleTo<int64_t>());
32   d = d / ConvertibleTo<int64_t>();
33   // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
34   // CHECK-FIXES: d = d / static_cast<int64_t>(ConvertibleTo<int64_t>());
35   d.operator*=(ConvertibleTo<int64_t>());
36   // CHECK-MESSAGES: [[@LINE-1]]:16: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
37   // CHECK-FIXES: d.operator*=(static_cast<int64_t>(ConvertibleTo<int64_t>()));
38   d.operator/=(ConvertibleTo<int64_t>());
39   // CHECK-MESSAGES: [[@LINE-1]]:16: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
40   // CHECK-FIXES: d.operator/=(static_cast<int64_t>(ConvertibleTo<int64_t>()));
41   d = operator*(ConvertibleTo<int64_t>(), d);
42   // CHECK-MESSAGES: [[@LINE-1]]:17: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
43   // CHECK-FIXES: d = operator*(static_cast<int64_t>(ConvertibleTo<int64_t>()), d);
44   d = operator*(d, ConvertibleTo<int64_t>());
45   // CHECK-MESSAGES: [[@LINE-1]]:20: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
46   // CHECK-FIXES: d = operator*(d, static_cast<int64_t>(ConvertibleTo<int64_t>()));
47   d = operator/(d, ConvertibleTo<int64_t>());
48   // CHECK-MESSAGES: [[@LINE-1]]:20: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
49   // CHECK-FIXES: d = operator/(d, static_cast<int64_t>(ConvertibleTo<int64_t>()));
50   ConvertibleTo<int64_t> c;
51   d *= (c + c) * c + c;
52   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
53   // CHECK-FIXES: d *= static_cast<int64_t>((c + c) * c + c)
54   d /= (c + c) * c + c;
55   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
56   // CHECK-FIXES: d /= static_cast<int64_t>((c + c) * c + c)
57   d = d * c * c;
58   // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
59   // CHECK-MESSAGES: [[@LINE-2]]:15: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
60   // CHECK-FIXES: d = d * static_cast<int64_t>(c) * static_cast<int64_t>(c)
61   d = c * d * c;
62   // CHECK-MESSAGES: [[@LINE-1]]:7: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
63   // CHECK-MESSAGES: [[@LINE-2]]:15: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
64   // CHECK-FIXES: d = static_cast<int64_t>(c) * d * static_cast<int64_t>(c)
65   d = d / c * c;
66   // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
67   // CHECK-MESSAGES: [[@LINE-2]]:15: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
68   // CHECK-FIXES: d = d / static_cast<int64_t>(c) * static_cast<int64_t>(c)
69 }
70 
arithmeticOperatorBasicNegative()71 void arithmeticOperatorBasicNegative() {
72   absl::Duration d;
73   d *= char{1};
74   d *= 1;
75   d *= int64_t{1};
76   d *= 1.0f;
77   d *= 1.0;
78   d *= 1.0l;
79   d /= char{1};
80   d /= 1;
81   d /= int64_t{1};
82   d /= 1.0f;
83   d /= 1.0;
84   d /= 1.0l;
85   d = d * char{1};
86   d = d * 1;
87   d = d * int64_t{1};
88   d = d * 1.0f;
89   d = d * 1.0;
90   d = d * 1.0l;
91   d = char{1} * d;
92   d = 1 * d;
93   d = int64_t{1} * d;
94   d = 1.0f * d;
95   d = 1.0 * d;
96   d = 1.0l * d;
97   d = d / char{1};
98   d = d / 1;
99   d = d / int64_t{1};
100   d = d / 1.0f;
101   d = d / 1.0;
102   d = d / 1.0l;
103 
104   d *= static_cast<int>(ConvertibleTo<int>());
105   d *= (int)ConvertibleTo<int>();
106   d *= int(ConvertibleTo<int>());
107   d /= static_cast<int>(ConvertibleTo<int>());
108   d /= (int)ConvertibleTo<int>();
109   d /= int(ConvertibleTo<int>());
110   d = static_cast<int>(ConvertibleTo<int>()) * d;
111   d = (int)ConvertibleTo<int>() * d;
112   d = int(ConvertibleTo<int>()) * d;
113   d = d * static_cast<int>(ConvertibleTo<int>());
114   d = d * (int)ConvertibleTo<int>();
115   d = d * int(ConvertibleTo<int>());
116   d = d / static_cast<int>(ConvertibleTo<int>());
117   d = d / (int)ConvertibleTo<int>();
118   d = d / int(ConvertibleTo<int>());
119 
120   d *= 1 + ConvertibleTo<int>();
121   d /= 1 + ConvertibleTo<int>();
122   d = (1 + ConvertibleTo<int>()) * d;
123   d = d * (1 + ConvertibleTo<int>());
124   d = d / (1 + ConvertibleTo<int>());
125 }
126 
templateForOpsSpecialization(T)127 template <typename T> void templateForOpsSpecialization(T) {}
128 template <>
templateForOpsSpecialization(absl::Duration d)129 void templateForOpsSpecialization<absl::Duration>(absl::Duration d) {
130   d *= ConvertibleTo<int64_t>();
131   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
132   // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int64_t>());
133 }
134 
arithmeticNonTypeTemplateParamSpecialization()135 template <int N> void arithmeticNonTypeTemplateParamSpecialization() {
136   absl::Duration d;
137   d *= N;
138 }
139 
arithmeticNonTypeTemplateParamSpecialization()140 template <> void arithmeticNonTypeTemplateParamSpecialization<5>() {
141   absl::Duration d;
142   d *= ConvertibleTo<int>();
143   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
144   // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int>());
145 }
146 
templateOpsFix()147 template <typename T> void templateOpsFix() {
148   absl::Duration d;
149   d *= ConvertibleTo<int64_t>();
150   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
151   // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int64_t>());
152 }
153 
templateOpsWarnOnly(T t,U u)154 template <typename T, typename U> void templateOpsWarnOnly(T t, U u) {
155   t *= u;
156   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
157   absl::Duration d;
158   d *= u;
159   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
160 }
161 
162 template <typename T> struct TemplateTypeOpsWarnOnly {
memberATemplateTypeOpsWarnOnly163   void memberA(T t) {
164     d *= t;
165     // CHECK-MESSAGES: [[@LINE-1]]:10: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
166   }
memberBTemplateTypeOpsWarnOnly167   template <typename U, typename V> void memberB(U u, V v) {
168     u *= v;
169     // CHECK-MESSAGES: [[@LINE-1]]:10: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
170     d *= v;
171     // CHECK-MESSAGES: [[@LINE-1]]:10: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
172   }
173 
174   absl::Duration d;
175 };
176 
177 template <typename T, typename U>
178 void templateOpsInstantiationBeforeDefinition(T t, U u);
179 
arithmeticOperatorsInTemplates()180 void arithmeticOperatorsInTemplates() {
181   templateForOpsSpecialization(5);
182   templateForOpsSpecialization(absl::Duration());
183   arithmeticNonTypeTemplateParamSpecialization<1>();
184   arithmeticNonTypeTemplateParamSpecialization<5>();
185   templateOpsFix<int>();
186   templateOpsWarnOnly(absl::Duration(), ConvertibleTo<int>());
187   templateOpsInstantiationBeforeDefinition(absl::Duration(),
188                                            ConvertibleTo<int>());
189   TemplateTypeOpsWarnOnly<ConvertibleTo<int>> t;
190   t.memberA(ConvertibleTo<int>());
191   t.memberB(absl::Duration(), ConvertibleTo<int>());
192 }
193 
194 template <typename T, typename U>
templateOpsInstantiationBeforeDefinition(T t,U u)195 void templateOpsInstantiationBeforeDefinition(T t, U u) {
196   t *= u;
197   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
198   absl::Duration d;
199   d *= u;
200   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
201 }
202 
203 #define FUNCTION_MACRO(x) x
204 #define CONVERTIBLE_TMP ConvertibleTo<int>()
205 #define ONLY_WARN_INSIDE_MACRO_ARITHMETIC_OP d *= ConvertibleTo<int>()
206 
207 #define T_OBJECT T()
208 #define T_CALL_EXPR d *= T()
209 
arithmeticTemplateAndMacro()210 template <typename T> void arithmeticTemplateAndMacro() {
211   absl::Duration d;
212   d *= T_OBJECT;
213   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
214   d *= CONVERTIBLE_TMP;
215   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
216   // CHECK-FIXES: d *= static_cast<int64_t>(CONVERTIBLE_TMP);
217   T_CALL_EXPR;
218   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
219 }
220 
221 #define TEMPLATE_MACRO(type)                                                   \
222   template <typename T> void TemplateInMacro(T t) {                            \
223     type d;                                                                    \
224     d *= t;                                                                    \
225   }
226 
TEMPLATE_MACRO(absl::Duration)227 TEMPLATE_MACRO(absl::Duration)
228 // CHECK-MESSAGES: [[@LINE-1]]:1: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
229 
230 void arithmeticOperatorsInMacros() {
231   absl::Duration d;
232   d = FUNCTION_MACRO(d * ConvertibleTo<int>());
233   // CHECK-MESSAGES: [[@LINE-1]]:26: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
234   // CHECK-FIXES: d = FUNCTION_MACRO(d * static_cast<int64_t>(ConvertibleTo<int>()));
235   d *= FUNCTION_MACRO(ConvertibleTo<int>());
236   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
237   // CHECK-FIXES: d *= static_cast<int64_t>(FUNCTION_MACRO(ConvertibleTo<int>()));
238   d *= CONVERTIBLE_TMP;
239   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
240   // CHECK-FIXES: d *= static_cast<int64_t>(CONVERTIBLE_TMP);
241   ONLY_WARN_INSIDE_MACRO_ARITHMETIC_OP;
242   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
243   arithmeticTemplateAndMacro<ConvertibleTo<int>>();
244   TemplateInMacro(ConvertibleTo<int>());
245 }
246 
factoryFunctionPositive()247 void factoryFunctionPositive() {
248   // User defined conversion:
249   (void)absl::Nanoseconds(ConvertibleTo<int64_t>());
250   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
251   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
252   (void)absl::Microseconds(ConvertibleTo<int64_t>());
253   // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
254   // CHECK-FIXES: (void)absl::Microseconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
255   (void)absl::Milliseconds(ConvertibleTo<int64_t>());
256   // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
257   // CHECK-FIXES: (void)absl::Milliseconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
258   (void)absl::Seconds(ConvertibleTo<int64_t>());
259   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
260   // CHECK-FIXES: (void)absl::Seconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
261   (void)absl::Minutes(ConvertibleTo<int64_t>());
262   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
263   // CHECK-FIXES: (void)absl::Minutes(static_cast<int64_t>(ConvertibleTo<int64_t>()));
264   (void)absl::Hours(ConvertibleTo<int64_t>());
265   // CHECK-MESSAGES: [[@LINE-1]]:21: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
266   // CHECK-FIXES: (void)absl::Hours(static_cast<int64_t>(ConvertibleTo<int64_t>()));
267 
268   // User defined conversion to integral type, followed by built-in conversion:
269   (void)absl::Nanoseconds(ConvertibleTo<char>());
270   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
271   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<char>()));
272   (void)absl::Microseconds(ConvertibleTo<char>());
273   // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
274   // CHECK-FIXES: (void)absl::Microseconds(static_cast<int64_t>(ConvertibleTo<char>()));
275   (void)absl::Milliseconds(ConvertibleTo<char>());
276   // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
277   // CHECK-FIXES: (void)absl::Milliseconds(static_cast<int64_t>(ConvertibleTo<char>()));
278   (void)absl::Seconds(ConvertibleTo<char>());
279   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
280   // CHECK-FIXES: (void)absl::Seconds(static_cast<int64_t>(ConvertibleTo<char>()));
281   (void)absl::Minutes(ConvertibleTo<char>());
282   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
283   // CHECK-FIXES: (void)absl::Minutes(static_cast<int64_t>(ConvertibleTo<char>()));
284   (void)absl::Hours(ConvertibleTo<char>());
285   // CHECK-MESSAGES: [[@LINE-1]]:21: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
286   // CHECK-FIXES: (void)absl::Hours(static_cast<int64_t>(ConvertibleTo<char>()));
287 
288   // User defined conversion to floating point type, followed by built-in conversion:
289   (void)absl::Nanoseconds(ConvertibleTo<float>());
290   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
291   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<float>()));
292   (void)absl::Microseconds(ConvertibleTo<float>());
293   // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
294   // CHECK-FIXES: (void)absl::Microseconds(static_cast<int64_t>(ConvertibleTo<float>()));
295   (void)absl::Milliseconds(ConvertibleTo<float>());
296   // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
297   // CHECK-FIXES: (void)absl::Milliseconds(static_cast<int64_t>(ConvertibleTo<float>()));
298   (void)absl::Seconds(ConvertibleTo<float>());
299   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
300   // CHECK-FIXES: (void)absl::Seconds(static_cast<int64_t>(ConvertibleTo<float>()));
301   (void)absl::Minutes(ConvertibleTo<float>());
302   // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
303   // CHECK-FIXES: (void)absl::Minutes(static_cast<int64_t>(ConvertibleTo<float>()));
304   (void)absl::Hours(ConvertibleTo<float>());
305   // CHECK-MESSAGES: [[@LINE-1]]:21: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
306   // CHECK-FIXES: (void)absl::Hours(static_cast<int64_t>(ConvertibleTo<float>()));
307 }
308 
factoryFunctionNegative()309 void factoryFunctionNegative() {
310   (void)absl::Nanoseconds(char{1});
311   (void)absl::Nanoseconds(1);
312   (void)absl::Nanoseconds(int64_t{1});
313   (void)absl::Nanoseconds(1.0f);
314   (void)absl::Microseconds(char{1});
315   (void)absl::Microseconds(1);
316   (void)absl::Microseconds(int64_t{1});
317   (void)absl::Microseconds(1.0f);
318   (void)absl::Milliseconds(char{1});
319   (void)absl::Milliseconds(1);
320   (void)absl::Milliseconds(int64_t{1});
321   (void)absl::Milliseconds(1.0f);
322   (void)absl::Seconds(char{1});
323   (void)absl::Seconds(1);
324   (void)absl::Seconds(int64_t{1});
325   (void)absl::Seconds(1.0f);
326   (void)absl::Minutes(char{1});
327   (void)absl::Minutes(1);
328   (void)absl::Minutes(int64_t{1});
329   (void)absl::Minutes(1.0f);
330   (void)absl::Hours(char{1});
331   (void)absl::Hours(1);
332   (void)absl::Hours(int64_t{1});
333   (void)absl::Hours(1.0f);
334 
335   (void)absl::Nanoseconds(static_cast<int>(ConvertibleTo<int>()));
336   (void)absl::Microseconds(static_cast<int>(ConvertibleTo<int>()));
337   (void)absl::Milliseconds(static_cast<int>(ConvertibleTo<int>()));
338   (void)absl::Seconds(static_cast<int>(ConvertibleTo<int>()));
339   (void)absl::Minutes(static_cast<int>(ConvertibleTo<int>()));
340   (void)absl::Hours(static_cast<int>(ConvertibleTo<int>()));
341 }
342 
templateForFactorySpecialization(T)343 template <typename T> void templateForFactorySpecialization(T) {}
templateForFactorySpecialization(ConvertibleTo<int> c)344 template <> void templateForFactorySpecialization<ConvertibleTo<int>>(ConvertibleTo<int> c) {
345   (void)absl::Nanoseconds(c);
346   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
347   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(c));
348 }
349 
factoryNonTypeTemplateParamSpecialization()350 template <int N> void factoryNonTypeTemplateParamSpecialization() {
351   (void)absl::Nanoseconds(N);
352 }
353 
factoryNonTypeTemplateParamSpecialization()354 template <> void factoryNonTypeTemplateParamSpecialization<5>() {
355   (void)absl::Nanoseconds(ConvertibleTo<int>());
356   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
357   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<int>()));
358 }
359 
templateFactoryFix()360 template <typename T> void templateFactoryFix() {
361   (void)absl::Nanoseconds(ConvertibleTo<int>());
362   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
363   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<int>()));
364 }
365 
templateFactoryWarnOnly(T t)366 template <typename T> void templateFactoryWarnOnly(T t) {
367   (void)absl::Nanoseconds(t);
368   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
369 }
370 
371 template <typename T> void templateFactoryInstantiationBeforeDefinition(T t);
372 
373 template <typename T> struct TemplateTypeFactoryWarnOnly {
memberATemplateTypeFactoryWarnOnly374   void memberA(T t) {
375     (void)absl::Nanoseconds(t);
376     // CHECK-MESSAGES: [[@LINE-1]]:29: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
377   }
memberBTemplateTypeFactoryWarnOnly378   template <typename U> void memberB(U u) {
379     (void)absl::Nanoseconds(u);
380     // CHECK-MESSAGES: [[@LINE-1]]:29: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
381   }
382 };
383 
factoryInTemplates()384 void factoryInTemplates() {
385   templateForFactorySpecialization(5);
386   templateForFactorySpecialization(ConvertibleTo<int>());
387   factoryNonTypeTemplateParamSpecialization<1>();
388   factoryNonTypeTemplateParamSpecialization<5>();
389   templateFactoryFix<int>();
390   templateFactoryWarnOnly(ConvertibleTo<int>());
391   templateFactoryInstantiationBeforeDefinition(ConvertibleTo<int>());
392   TemplateTypeFactoryWarnOnly<ConvertibleTo<int>> t;
393   t.memberA(ConvertibleTo<int>());
394   t.memberB(ConvertibleTo<int>());
395 }
396 
templateFactoryInstantiationBeforeDefinition(T t)397 template <typename T> void templateFactoryInstantiationBeforeDefinition(T t) {
398   (void)absl::Nanoseconds(t);
399   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
400 }
401 
402 #define ONLY_WARN_INSIDE_MACRO_FACTORY                                         \
403   (void)absl::Nanoseconds(ConvertibleTo<int>())
404 #define T_CALL_FACTORTY_INSIDE_MACRO (void)absl::Nanoseconds(T())
405 
factoryTemplateAndMacro()406 template <typename T> void factoryTemplateAndMacro() {
407   (void)absl::Nanoseconds(T_OBJECT);
408   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
409   (void)absl::Nanoseconds(CONVERTIBLE_TMP);
410   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
411   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(CONVERTIBLE_TMP))
412   T_CALL_FACTORTY_INSIDE_MACRO;
413   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
414 }
415 
416 #define TEMPLATE_FACTORY_MACRO(factory)                                        \
417   template <typename T> void TemplateFactoryInMacro(T t) { (void)factory(t); }
418 
TEMPLATE_FACTORY_MACRO(absl::Nanoseconds)419 TEMPLATE_FACTORY_MACRO(absl::Nanoseconds)
420 // CHECK-MESSAGES: [[@LINE-1]]:1: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
421 
422 void factoryInMacros() {
423   (void)absl::Nanoseconds(FUNCTION_MACRO(ConvertibleTo<int>()));
424   // CHECK-MESSAGES: [[@LINE-1]]:42: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
425   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(FUNCTION_MACRO(ConvertibleTo<int>())));
426   (void)absl::Nanoseconds(CONVERTIBLE_TMP);
427   // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
428   // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(CONVERTIBLE_TMP))
429   ONLY_WARN_INSIDE_MACRO_FACTORY;
430   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
431   factoryTemplateAndMacro<ConvertibleTo<int>>();
432   TemplateFactoryInMacro(ConvertibleTo<int>());
433 }
434 
435 // This is a reduced test-case for PR39949 and manifested in this check.
436 namespace std {
437 template <typename _Tp>
438 _Tp declval();
439 
440 template <typename _Functor, typename... _ArgTypes>
441 struct __res {
442   template <typename... _Args>
443   static decltype(declval<_Functor>()(_Args()...)) _S_test(int);
444 
445   template <typename...>
446   static void _S_test(...);
447 
448   typedef decltype(_S_test<_ArgTypes...>(0)) type;
449 };
450 
451 template <typename>
452 struct function;
453 
454 template <typename... _ArgTypes>
455 struct function<void(_ArgTypes...)> {
456   template <typename _Functor,
457             typename = typename __res<_Functor, _ArgTypes...>::type>
functionstd::function458   function(_Functor) {}
459 };
460 } // namespace std
461 
462 typedef std::function<void(void)> F;
463 
foo()464 F foo() {
465   return F([] {});
466 }
467