inline.cpp revision b66529d04727dc686b97ea3d937fc9785792f505
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s 2 3void clang_analyzer_eval(bool); 4void clang_analyzer_checkInlined(bool); 5 6class A { 7public: 8 int getZero() { return 0; } 9 virtual int getNum() { return 0; } 10}; 11 12void test(A &a) { 13 clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}} 14 clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}} 15 16 A copy(a); 17 clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}} 18 clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}} 19} 20 21 22class One : public A { 23public: 24 virtual int getNum() { return 1; } 25}; 26 27void testPathSensitivity(int x) { 28 A a; 29 One b; 30 31 A *ptr; 32 switch (x) { 33 case 0: 34 ptr = &a; 35 break; 36 case 1: 37 ptr = &b; 38 break; 39 default: 40 return; 41 } 42 43 // This should be true on both branches. 44 clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}} 45} 46 47 48namespace PureVirtualParent { 49 class Parent { 50 public: 51 virtual int pureVirtual() const = 0; 52 int callVirtual() const { 53 return pureVirtual(); 54 } 55 }; 56 57 class Child : public Parent { 58 public: 59 virtual int pureVirtual() const { 60 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 61 return 42; 62 } 63 }; 64 65 void testVirtual() { 66 Child x; 67 68 clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}} 69 clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}} 70 } 71} 72 73 74namespace PR13569 { 75 class Parent { 76 protected: 77 int m_parent; 78 virtual int impl() const = 0; 79 80 Parent() : m_parent(0) {} 81 82 public: 83 int interface() const { 84 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 85 return impl(); 86 } 87 }; 88 89 class Child : public Parent { 90 protected: 91 virtual int impl() const { 92 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 93 return m_parent + m_child; 94 } 95 96 public: 97 Child() : m_child(0) {} 98 99 int m_child; 100 }; 101 102 void testVirtual() { 103 Child x; 104 x.m_child = 42; 105 106 // Don't crash when inlining and devirtualizing. 107 x.interface(); 108 } 109 110 111 class Grandchild : public Child {}; 112 113 void testDevirtualizeToMiddle() { 114 Grandchild x; 115 x.m_child = 42; 116 117 // Don't crash when inlining and devirtualizing. 118 x.interface(); 119 } 120} 121 122namespace PR13569_virtual { 123 class Parent { 124 protected: 125 int m_parent; 126 virtual int impl() const = 0; 127 128 Parent() : m_parent(0) {} 129 130 public: 131 int interface() const { 132 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 133 return impl(); 134 } 135 }; 136 137 class Child : virtual public Parent { 138 protected: 139 virtual int impl() const { 140 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}} 141 return m_parent + m_child; 142 } 143 144 public: 145 Child() : m_child(0) {} 146 147 int m_child; 148 }; 149 150 void testVirtual() { 151 Child x; 152 x.m_child = 42; 153 154 // Don't crash when inlining and devirtualizing. 155 x.interface(); 156 } 157 158 159 class Grandchild : virtual public Child {}; 160 161 void testDevirtualizeToMiddle() { 162 Grandchild x; 163 x.m_child = 42; 164 165 // Don't crash when inlining and devirtualizing. 166 x.interface(); 167 } 168} 169 170namespace Invalidation { 171 struct X { 172 void touch(int &x) const { 173 x = 0; 174 } 175 176 void touch2(int &x) const; 177 178 virtual void touchV(int &x) const { 179 x = 0; 180 } 181 182 virtual void touchV2(int &x) const; 183 184 int test() const { 185 // We were accidentally not invalidating under -analyzer-ipa=inlining 186 // at one point for virtual methods with visible definitions. 187 int a, b, c, d; 188 touch(a); 189 touch2(b); 190 touchV(c); 191 touchV2(d); 192 return a + b + c + d; // no-warning 193 } 194 }; 195} 196 197namespace DefaultArgs { 198 int takesDefaultArgs(int i = 42) { 199 return -i; 200 } 201 202 void testFunction() { 203 clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}} 204 clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}} 205 } 206 207 class Secret { 208 public: 209 static const int value = 42; 210 int get(int i = value) { 211 return i; 212 } 213 }; 214 215 void testMethod() { 216 Secret obj; 217 clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}} 218 219 // FIXME: Should be 'TRUE'. See PR13673 or <rdar://problem/11720796>. 220 clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}} 221 222 // FIXME: Even if we constrain the variable, we still have a problem. 223 // See PR13385 or <rdar://problem/12156507>. 224 if (Secret::value != 42) 225 return; 226 clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}} 227 clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}} 228 } 229} 230