1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
// RUN: %clang_cc1 -fsyntax-only -verify=expected,expected-cxx11 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify=expected,expected-cxx11 -std=c++11 %s
namespace BooleanFalse {
int* j = false;
#if __cplusplus <= 199711L
// expected-warning@-2 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
#else
// expected-error@-4 {{cannot initialize a variable of type 'int *' with an rvalue of type 'bool'}}
#endif
#if __cplusplus <= 199711L
// expected-warning@+5 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
#else
// expected-error@+3 {{cannot initialize a parameter of type 'int *' with an rvalue of type 'bool'}}
// expected-note@+2 {{passing argument to parameter 'j' here}}
#endif
void bar(int *j = false);
#if __cplusplus > 199711L
// expected-note@+2 4{{candidate function not viable: no known conversion}}
#endif
void foo(int *i)
{
foo(false);
#if __cplusplus <= 199711L
// expected-warning@-2 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
#else
// expected-error@-4 {{no matching function for call to 'foo'}}
#endif
foo((int*)false); // OK: explicit cast
foo(0); // OK: not a bool, even though it's convertible to bool
foo(false == true);
#if __cplusplus <= 199711L
// expected-warning@-2 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
#else
// expected-error@-4 {{no matching function for call to 'foo'}}
#endif
foo((42 + 24) < 32);
#if __cplusplus <= 199711L
// expected-warning@-2 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
#else
// expected-error@-4 {{no matching function for call to 'foo'}}
#endif
const bool kFlag = false;
foo(kFlag);
#if __cplusplus <= 199711L
// expected-warning@-2 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
#else
// expected-error@-4 {{no matching function for call to 'foo'}}
#endif
}
char f(struct Undefined*);
double f(...);
// Ensure that when using false in metaprogramming machinery its conversion
// isn't flagged.
template <int N> struct S {};
S<sizeof(f(false))> s;
}
namespace Function {
void f1();
struct S {
static void f2();
};
extern void f3() __attribute__((weak_import));
struct S2 {
static void f4() __attribute__((weak_import));
};
bool f5();
bool f6(int);
void bar() {
bool b;
b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}} \
expected-note {{suffix with parentheses to turn this into a function call}}
b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
// implicit casts of weakly imported symbols are ok:
b = f3;
if (f3) {}
b = S2::f4;
if (S2::f4) {}
}
}
namespace Array {
#define GetValue(ptr) ((ptr) ? ptr[0] : 0)
extern int a[] __attribute__((weak));
int b[] = {8,13,21};
struct {
int x[10];
} c;
const char str[] = "text";
void ignore() {
if (a) {}
if (a) {}
(void)GetValue(b);
}
void test() {
if (b) {}
// expected-warning@-1{{address of array 'b' will always evaluate to 'true'}}
if (b) {}
// expected-warning@-1{{address of array 'b' will always evaluate to 'true'}}
if (c.x) {}
// expected-warning@-1{{address of array 'c.x' will always evaluate to 'true'}}
if (str) {}
// expected-warning@-1{{address of array 'str' will always evaluate to 'true'}}
}
}
namespace Pointer {
extern int a __attribute__((weak));
int b;
static int c;
class S {
public:
static int a;
int b;
};
void ignored() {
if (&a) {}
}
void test() {
S s;
if (&b) {}
// expected-warning@-1{{address of 'b' will always evaluate to 'true'}}
if (&c) {}
// expected-warning@-1{{address of 'c' will always evaluate to 'true'}}
if (&s.a) {}
// expected-warning@-1{{address of 's.a' will always evaluate to 'true'}}
if (&s.b) {}
// expected-warning@-1{{address of 's.b' will always evaluate to 'true'}}
if (&S::a) {}
// expected-warning@-1{{address of 'S::a' will always evaluate to 'true'}}
}
}
namespace macros {
#define assert(x) if (x) {}
#define zero_on_null(x) ((x) ? *(x) : 0)
int array[5];
void fun();
int x;
void test() {
assert(array);
assert(array && "expecting null pointer");
// expected-warning@-1{{address of array 'array' will always evaluate to 'true'}}
assert(fun);
assert(fun && "expecting null pointer");
// expected-warning@-1{{address of function 'fun' will always evaluate to 'true'}}
// expected-note@-2 {{prefix with the address-of operator to silence this warning}}
// TODO: warn on assert(&x) while not warning on zero_on_null(&x)
zero_on_null(&x);
assert(zero_on_null(&x));
assert(&x);
assert(&x && "expecting null pointer");
// expected-warning@-1{{address of 'x' will always evaluate to 'true'}}
}
}
namespace Template {
// FIXME: These cases should not warn.
template<int *p> void f() { if (p) {} } // expected-warning 2{{will always evaluate to 'true'}} expected-cxx11-warning {{implicit conversion of nullptr}}
template<int (*p)[3]> void g() { if (p) {} } // expected-warning 2{{will always evaluate to 'true'}} expected-cxx11-warning {{implicit conversion of nullptr}}
template<int (*p)()> void h() { if (p) {} }
int a, b[3], c[3][3], d();
template void f<&a>(); // expected-note {{instantiation of}}
template void f<b>(); // expected-note {{instantiation of}}
#if __cplusplus >= 201103L
template void f<(int*)nullptr>(); // expected-note {{instantiation of}}
#endif
template void g<&b>(); // expected-note {{instantiation of}}
template void g<c>(); // expected-note {{instantiation of}}
#if __cplusplus >= 201103L
template void g<(int(*)[3])nullptr>(); // expected-note {{instantiation of}}
#endif
template void h<d>();
}
|