xref: /llvm-project/clang/test/SemaCXX/conversion.cpp (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -std=c++11 -verify %s
2 // RUN: not %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -std=c++11 %s 2>&1 | FileCheck %s
3 
4 #include <stddef.h>
5 
6 typedef   signed char  int8_t;
7 typedef   signed short int16_t;
8 typedef   signed int   int32_t;
9 typedef   signed long  int64_t;
10 
11 typedef unsigned char  uint8_t;
12 typedef unsigned short uint16_t;
13 typedef unsigned int   uint32_t;
14 typedef unsigned long  uint64_t;
15 
16 namespace test0 {
test1_positive(char * I,char * E)17   int32_t test1_positive(char *I, char *E) {
18     return (E - I); // expected-warning {{implicit conversion loses integer precision}}
19   }
20 
test1_negative(char * I,char * E)21   int32_t test1_negative(char *I, char *E) {
22     return static_cast<int32_t>(E - I);
23   }
24 
test2_positive(uint64_t x)25   uint32_t test2_positive(uint64_t x) {
26     return x; // expected-warning {{implicit conversion loses integer precision}}
27   }
28 
test2_negative(uint64_t x)29   uint32_t test2_negative(uint64_t x) {
30     return (uint32_t) x;
31   }
32 }
33 
34 namespace test1 {
test1(int x,unsigned y)35   uint64_t test1(int x, unsigned y) {
36     return sizeof(x == y);
37   }
38 
test2(int x,unsigned y)39   uint64_t test2(int x, unsigned y) {
40     return __alignof(x == y);
41   }
42 
43   void * const foo();
test2(void * p)44   bool test2(void *p) {
45     return p == foo();
46   }
47 }
48 
49 namespace test2 {
50   struct A {
51     unsigned int x : 2;
Atest2::A52     A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to 2}}
53   };
54 }
55 
56 // This file tests -Wnull-conversion, a subcategory of -Wconversion
57 // which is on by default.
58 
test3()59 void test3() {
60   int a = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}}
61   int b;
62   b = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}}
63   long l = NULL; // FIXME: this should also warn, but currently does not if sizeof(NULL)==sizeof(inttype)
64   int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}}
65   int d;
66   d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}}
67   bool bl = NULL; // expected-warning {{implicit conversion of NULL constant to 'bool'}}
68   char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}}
69   unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}}
70   short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}}
71   double dbl = NULL; // expected-warning {{implicit conversion of NULL constant to 'double'}}
72 
73   // Use FileCheck to ensure we don't get any unnecessary macro-expansion notes
74   // (that don't appear as 'real' notes & can't be seen/tested by -verify)
75   // CHECK-NOT: note:
76   // CHECK: note: expanded from macro 'FINIT'
77 #define FINIT int a3 = NULL;
78   FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}}
79   // we don't catch the case of #define FOO NULL ... int i = FOO; but that
80   // seems a bit narrow anyway and avoiding that helps us skip other cases.
81 
82   int *ip = NULL;
83   int (*fp)() = NULL;
84   struct foo {
85     int n;
86     void func();
87   };
88   int foo::*datamem = NULL;
89   int (foo::*funmem)() = NULL;
90 }
91 
92 namespace test4 {
93   // FIXME: We should warn for non-dependent args (only when the param type is also non-dependent) only once
94   // not once for the template + once for every instantiation
95   template<typename T>
tmpl(char c=NULL,T a=NULL,T b=1024)96   void tmpl(char c = NULL, // expected-warning 3 {{implicit conversion of NULL constant to 'char'}}
97             T a = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} \
98                            expected-warning {{implicit conversion of NULL constant to 'int'}}
99             T b = 1024) { // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1024 to 0}}
100   }
101 
102   template<typename T>
tmpl2(T t=NULL)103   void tmpl2(T t = NULL) {
104   }
105 
func()106   void func() {
107     tmpl<char>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<char>' required here}}
108     tmpl<int>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<int>' required here}}
109     tmpl<int>();
110     tmpl2<int*>();
111   }
112 }
113 
114 namespace test5 {
115   template<int I>
func()116   void func() {
117     bool b = I;
118   }
119 
120   template void func<3>();
121 }
122 
123 namespace test6 {
func()124   decltype(nullptr) func() {
125     return NULL;
126   }
127 }
128 
129 namespace test7 {
fun()130   bool fun() {
131     bool x = nullptr; // expected-error {{cannot initialize}}
132     if (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
133     return nullptr; // expected-error {{cannot initialize}}
134   }
135 }
136 
137 namespace test8 {
138   #define NULL_COND(cond) ((cond) ? &num : NULL)
139   #define NULL_WRAPPER NULL_COND(false)
140 
141   // don't warn on NULL conversion through the conditional operator across a
142   // macro boundary
macro()143   void macro() {
144     int num;
145     bool b = NULL_COND(true);
146     if (NULL_COND(true)) {}
147     while (NULL_COND(true)) {}
148     for (;NULL_COND(true);) {}
149     do {} while (NULL_COND(true));
150 
151     if (NULL_WRAPPER) {}
152     while (NULL_WRAPPER) {}
153     for (;NULL_WRAPPER;) {}
154     do {} while (NULL_WRAPPER);
155   }
156 
157   // Identical to the previous function except with a template argument.
158   // This ensures that template instantiation does not introduce any new
159   // warnings.
160   template <typename X>
template_and_macro()161   void template_and_macro() {
162     int num;
163     bool b = NULL_COND(true);
164     if (NULL_COND(true)) {}
165     while (NULL_COND(true)) {}
166     for (;NULL_COND(true);) {}
167     do {} while (NULL_COND(true));
168 
169     if (NULL_WRAPPER) {}
170     while (NULL_WRAPPER) {}
171     for (;NULL_WRAPPER;) {}
172     do {} while (NULL_WRAPPER);
173   }
174 
175   // Identical to the previous function except the template argument affects
176   // the conditional statement.
177   template <typename X>
template_and_macro2()178   void template_and_macro2() {
179     X num;
180     bool b = NULL_COND(true);
181     if (NULL_COND(true)) {}
182     while (NULL_COND(true)) {}
183     for (;NULL_COND(true);) {}
184     do {} while (NULL_COND(true));
185 
186     if (NULL_WRAPPER) {}
187     while (NULL_WRAPPER) {}
188     for (;NULL_WRAPPER;) {}
189     do {} while (NULL_WRAPPER);
190   }
191 
run()192   void run() {
193     template_and_macro<int>();
194     template_and_macro<double>();
195     template_and_macro2<int>();
196     template_and_macro2<double>();
197   }
198 }
199 
200 namespace test9 {
201   typedef decltype(nullptr) nullptr_t;
202   nullptr_t EXIT();
203 
test()204   bool test() {
205     return EXIT(); // expected-error {{cannot initialize}}
206   }
207 }
208 
209 // Test NULL macro inside a macro has same warnings nullptr inside a macro.
210 namespace test10 {
211 #define test1(cond) \
212       ((cond) ? nullptr : NULL)
213 #define test2(cond) \
214       ((cond) ? NULL : nullptr)
215 
216 #define assert(cond) \
217       ((cond) ? foo() : bar())
218   void foo();
219   void bar();
220 
run(int x)221   void run(int x) {
222     if (test1(x)) {}
223     if (test2(x)) {}
224     assert(test1(x));
225     assert(test2(x));
226   }
227 }
228 
229 namespace test11 {
230 
231 #define assert11(expr) ((expr) ? 0 : 0)
232 
233 // The whitespace in macro run1 are important to trigger the macro being split
234 // over multiple SLocEntry's.
235 #define run1() (dostuff() ? \
236     NULL                                   : NULL)
237 #define run2() (dostuff() ? NULL : NULL)
238 int dostuff ();
239 
test(const char * content_type)240 void test(const char * content_type) {
241   assert11(run1());
242   assert11(run2());
243 }
244 
245 }
246 
247 namespace test12 {
248 
249 #define x return NULL;
250 
run()251 bool run() {
252   x  // expected-warning{{}}
253 }
254 
255 }
256 
257 // More tests with macros.  Specficially, test function-like macros that either
258 // have a pointer return type or take pointer arguments.  Basically, if the
259 // macro was changed into a function and Clang doesn't warn, then it shouldn't
260 // warn for the macro either.
261 namespace test13 {
262 #define check_str_nullptr_13(str) ((str) ? str : nullptr)
263 #define check_str_null_13(str) ((str) ? str : NULL)
264 #define test13(condition) if (condition) return;
265 #define identity13(arg) arg
266 #define CHECK13(condition) test13(identity13(!(condition)))
267 
function1(const char * str)268 void function1(const char* str) {
269   CHECK13(check_str_nullptr_13(str));
270   CHECK13(check_str_null_13(str));
271 }
272 
273 bool some_bool_function(bool); // expected-note {{no known conversion}}
function2()274 void function2() {
275   CHECK13(some_bool_function(nullptr));  // expected-error {{no matching function}}
276   CHECK13(some_bool_function(NULL));  // expected-warning {{implicit conversion of NULL constant to 'bool'}}
277 }
278 
279 #define run_check_nullptr_13(str) \
280     if (check_str_nullptr_13(str)) return;
281 #define run_check_null_13(str) \
282     if (check_str_null_13(str)) return;
function3(const char * str)283 void function3(const char* str) {
284   run_check_nullptr_13(str)
285   run_check_null_13(str)
286   if (check_str_nullptr_13(str)) return;
287   if (check_str_null_13(str)) return;
288 }
289 
290 void run(int* ptr);
291 #define conditional_run_13(ptr) \
292     if (ptr) run(ptr);
function4()293 void function4() {
294   conditional_run_13(nullptr);
295   conditional_run_13(NULL);
296 }
297 }
298