Clang Project

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