1 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-output=text -verify %s 2 void clang_analyzer_eval(bool); 3 4 struct X0 { }; 5 bool operator==(const X0&, const X0&); 6 7 // PR7287 8 struct test { int a[2]; }; 9 10 void t2() { 11 test p = {{1,2}}; 12 test q; 13 q = p; 14 } 15 16 bool PR7287(X0 a, X0 b) { 17 return operator==(a, b); 18 } 19 20 21 // Inlining non-static member operators mistakenly treated 'this' as the first 22 // argument for a while. 23 24 struct IntComparable { 25 bool operator==(int x) const { 26 return x == 0; 27 } 28 }; 29 30 void testMemberOperator(IntComparable B) { 31 clang_analyzer_eval(B == 0); // expected-warning{{TRUE}} 32 // expected-note@-1{{TRUE}} 33 } 34 35 36 37 namespace UserDefinedConversions { 38 class Convertible { 39 public: 40 operator int() const { 41 return 42; 42 } 43 operator bool() const { 44 return true; 45 } 46 }; 47 48 void test(const Convertible &obj) { 49 clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}} 50 // expected-note@-1{{TRUE}} 51 clang_analyzer_eval(obj); // expected-warning{{TRUE}} 52 // expected-note@-1{{TRUE}} 53 } 54 } 55 56 57 namespace RValues { 58 struct SmallOpaque { 59 float x; 60 int operator +() const { 61 return (int)x; 62 } 63 }; 64 65 struct LargeOpaque { 66 float x[4]; 67 int operator +() const { 68 return (int)x[0]; 69 } 70 }; 71 72 SmallOpaque getSmallOpaque() { 73 SmallOpaque obj; 74 obj.x = 1.0; 75 return obj; 76 } 77 78 LargeOpaque getLargeOpaque() { 79 LargeOpaque obj = LargeOpaque(); 80 obj.x[0] = 1.0; 81 return obj; 82 } 83 84 void test(int coin) { 85 // Force a cache-out when we try to conjure a temporary region for the operator call. 86 // ...then, don't crash. 87 clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}} 88 // expected-note@-1{{Assuming 'coin' is 0}} 89 // expected-note@-2{{'?' condition is false}} 90 // expected-note@-3{{UNKNOWN}} 91 // expected-note@-4{{Assuming 'coin' is 0}} 92 // expected-note@-5{{'?' condition is false}} 93 clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}} 94 // expected-note@-1{{'coin' is 0}} 95 // expected-note@-2{{'?' condition is false}} 96 // expected-note@-3{{UNKNOWN}} 97 } 98 } 99 100 namespace SynthesizedAssignment { 101 struct A { 102 int a; 103 A& operator=(A& other) { a = -other.a; return *this; } 104 A& operator=(A&& other) { a = other.a+1; return *this; } 105 }; 106 107 struct B { 108 int x; 109 A a[3]; 110 B& operator=(B&) = default; 111 B& operator=(B&&) = default; 112 }; 113 114 // This used to produce a warning about the iteration variable in the 115 // synthesized assignment operator being undefined. 116 // 117 // Note: The warning we want to avoid can be found in https://bugs.llvm.org/show_bug.cgi?id=16745. 118 // Back in the day, this function was created we couldn't evaluate non-POD type array construction, 119 // so we couldn't evaluate the copy assignment either, hence we didn't detect that a field is 120 // uninitialized. 121 void testNoWarning() { 122 123 B v, u; 124 u = v; // expected-warning@110{{Assigned value is garbage or undefined}} 125 // expected-note@-1{{Calling defaulted copy assignment operator for 'B'}} 126 // expected-note@110{{Assigned value is garbage or undefined}} 127 } 128 129 void testNoWarningMove() { 130 B v, u; 131 u = static_cast<B &&>(v); // expected-warning@111{{Assigned value is garbage or undefined}} 132 // expected-note@-1{{Calling defaulted move assignment operator for 'B'}} 133 // expected-note@111{{Assigned value is garbage or undefined}} 134 } 135 136 void testConsistency() { 137 B v, u; 138 v.x = 0; 139 v.a[0].a = 24; 140 v.a[1].a = 47; 141 v.a[2].a = 42; 142 u = v; 143 clang_analyzer_eval(u.a[0].a == -24); // expected-warning{{TRUE}} 144 // expected-note@-1{{TRUE}} 145 clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}} 146 // expected-note@-1{{TRUE}} 147 clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}} 148 // expected-note@-1{{TRUE}} 149 } 150 151 void testConsistencyMove() { 152 B v, u; 153 v.x = 0; 154 v.a[0].a = 24; 155 v.a[1].a = 47; 156 v.a[2].a = 42; 157 u = static_cast<B &&>(v); 158 clang_analyzer_eval(u.a[0].a == 25); // expected-warning{{TRUE}} 159 // expected-note@-1{{TRUE}} 160 clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}} 161 // expected-note@-1{{TRUE}} 162 clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}} 163 // expected-note@-1{{TRUE}} 164 } 165 } 166