298 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -std=c++11 -verify %s2// RUN: not %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -std=c++11 %s 2>&1 | FileCheck %s3 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 16namespace test0 {17 int32_t test1_positive(char *I, char *E) {18 return (E - I); // expected-warning {{implicit conversion loses integer precision}}19 }20 21 int32_t test1_negative(char *I, char *E) {22 return static_cast<int32_t>(E - I);23 }24 25 uint32_t test2_positive(uint64_t x) {26 return x; // expected-warning {{implicit conversion loses integer precision}}27 }28 29 uint32_t test2_negative(uint64_t x) {30 return (uint32_t) x;31 }32}33 34namespace test1 {35 uint64_t test1(int x, unsigned y) {36 return sizeof(x == y);37 }38 39 uint64_t test2(int x, unsigned y) {40 return __alignof(x == y);41 }42 43 void * const foo();44 bool test2(void *p) {45 return p == foo();46 }47}48 49namespace test2 {50 struct A {51 unsigned int x : 2;52 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 -Wconversion57// which is on by default.58 59void 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 that80 // 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 92namespace test4 {93 // FIXME: We should warn for non-dependent args (only when the param type is also non-dependent) only once94 // not once for the template + once for every instantiation95 template<typename T>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>103 void tmpl2(T t = NULL) {104 }105 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 114namespace test5 {115 template<int I>116 void func() {117 bool b = I;118 }119 120 template void func<3>();121}122 123namespace test6 {124 decltype(nullptr) func() {125 return NULL;126 }127}128 129namespace test7 {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 137namespace 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 a142 // macro boundary143 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 new159 // warnings.160 template <typename X>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 affects176 // the conditional statement.177 template <typename X>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 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 200namespace test9 {201 typedef decltype(nullptr) nullptr_t;202 nullptr_t EXIT();203 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.210namespace 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 221 void run(int x) {222 if (test1(x)) {}223 if (test2(x)) {}224 assert(test1(x));225 assert(test2(x));226 }227}228 229namespace test11 {230 231#define assert11(expr) ((expr) ? 0 : 0)232 233// The whitespace in macro run1 are important to trigger the macro being split234// over multiple SLocEntry's.235#define run1() (dostuff() ? \236 NULL : NULL)237#define run2() (dostuff() ? NULL : NULL)238int dostuff ();239 240void test(const char * content_type) {241 assert11(run1());242 assert11(run2());243}244 245}246 247namespace test12 {248 249#define x return NULL;250 251bool run() {252 x // expected-warning{{}}253}254 255}256 257// More tests with macros. Specficially, test function-like macros that either258// have a pointer return type or take pointer arguments. Basically, if the259// macro was changed into a function and Clang doesn't warn, then it shouldn't260// warn for the macro either.261namespace 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) arg266#define CHECK13(condition) test13(identity13(!(condition)))267 268void function1(const char* str) {269 CHECK13(check_str_nullptr_13(str));270 CHECK13(check_str_null_13(str));271}272 273bool some_bool_function(bool); // expected-note {{no known conversion}}274void 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;283void 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 290void run(int* ptr);291#define conditional_run_13(ptr) \292 if (ptr) run(ptr);293void function4() {294 conditional_run_13(nullptr);295 conditional_run_13(NULL);296}297}298