forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			195 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -fsyntax-only -verify %s
 | |
| // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
 | |
| // RUN: %clang_cc1 -fsyntax-only -verify -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@+6 {{initialization of pointer of type 'int *' to null from a constant boolean expression}}
 | |
| #else
 | |
| // expected-error@+4 {{cannot initialize a parameter of type 'int *' with an rvalue of type 'bool'}}
 | |
| // expected-note@+3 {{passing argument to parameter 'j' here}}
 | |
| // expected-note@+2 6 {{candidate function not viable: requires 2 arguments, but 1 was provided}}
 | |
| #endif
 | |
| void foo(int* i, int *j=(false))
 | |
| {
 | |
|   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);
 | |
| #if __cplusplus <= 199711L
 | |
| // no-warning: explicit cast
 | |
| #else
 | |
| // expected-error@-4 {{no matching function for call to 'foo'}}
 | |
| #endif
 | |
| 
 | |
|   foo(0);
 | |
| #if __cplusplus <= 199711L
 | |
| // no-warning: not a bool, even though its convertible to bool
 | |
| #else
 | |
| // expected-error@-4 {{no matching function for call to 'foo'}}
 | |
| #endif
 | |
| 
 | |
|   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'}}
 | |
|   }
 | |
| }
 |