forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			133 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
 | |
| void clang_analyzer_eval(bool);
 | |
| 
 | |
| struct X0 { };
 | |
| bool operator==(const X0&, const X0&);
 | |
| 
 | |
| // PR7287
 | |
| struct test { int a[2]; };
 | |
| 
 | |
| void t2() {
 | |
|   test p = {{1,2}};
 | |
|   test q;
 | |
|   q = p;
 | |
| }
 | |
| 
 | |
| bool PR7287(X0 a, X0 b) {
 | |
|   return operator==(a, b);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Inlining non-static member operators mistakenly treated 'this' as the first
 | |
| // argument for a while.
 | |
| 
 | |
| struct IntComparable {
 | |
|   bool operator==(int x) const {
 | |
|     return x == 0;
 | |
|   }
 | |
| };
 | |
| 
 | |
| void testMemberOperator(IntComparable B) {
 | |
|   clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| namespace UserDefinedConversions {
 | |
|   class Convertible {
 | |
|   public:
 | |
|     operator int() const {
 | |
|       return 42;
 | |
|     }
 | |
|     operator bool() const {
 | |
|       return true;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   void test(const Convertible &obj) {
 | |
|     clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
 | |
|     clang_analyzer_eval(obj); // expected-warning{{TRUE}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| namespace RValues {
 | |
|   struct SmallOpaque {
 | |
|     float x;
 | |
|     int operator +() const {
 | |
|       return (int)x;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   struct LargeOpaque {
 | |
|     float x[4];
 | |
|     int operator +() const {
 | |
|       return (int)x[0];
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   SmallOpaque getSmallOpaque() {
 | |
|     SmallOpaque obj;
 | |
|     obj.x = 1.0;
 | |
|     return obj;
 | |
|   }
 | |
| 
 | |
|   LargeOpaque getLargeOpaque() {
 | |
|     LargeOpaque obj = LargeOpaque();
 | |
|     obj.x[0] = 1.0;
 | |
|     return obj;
 | |
|   }
 | |
| 
 | |
|   void test(int coin) {
 | |
|     // Force a cache-out when we try to conjure a temporary region for the operator call.
 | |
|     // ...then, don't crash.
 | |
|     clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
 | |
|     clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace SynthesizedAssignment {
 | |
|   struct A {
 | |
|     int a;
 | |
|     A& operator=(A& other) { a = -other.a; return *this; }
 | |
|     A& operator=(A&& other) { a = other.a+1; return *this; }
 | |
|   };
 | |
| 
 | |
|   struct B {
 | |
|     int x;
 | |
|     A a[3];
 | |
|     B& operator=(B&) = default;
 | |
|     B& operator=(B&&) = default;
 | |
|   };
 | |
| 
 | |
|   // This used to produce a warning about the iteration variable in the
 | |
|   // synthesized assignment operator being undefined.
 | |
|   void testNoWarning() {
 | |
|     B v, u;
 | |
|     u = v;
 | |
|   }
 | |
| 
 | |
|   void testNoWarningMove() {
 | |
|     B v, u;
 | |
|     u = static_cast<B &&>(v);
 | |
|   }
 | |
| 
 | |
|   void testConsistency() {
 | |
|     B v, u;
 | |
|     v.a[1].a = 47;
 | |
|     v.a[2].a = 42;
 | |
|     u = v;
 | |
|     clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}}
 | |
|     clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}}
 | |
|   }
 | |
| 
 | |
|   void testConsistencyMove() {
 | |
|     B v, u;
 | |
|     v.a[1].a = 47;
 | |
|     v.a[2].a = 42;
 | |
|     u = static_cast<B &&>(v);
 | |
|     clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}}
 | |
|     clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}}
 | |
|   }
 | |
| }
 |