323 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s2 3void clang_analyzer_eval(bool);4 5struct A {6 // This conversion operator allows implicit conversion to bool but not to other integer types.7 typedef A * (A::*MemberPointer);8 operator MemberPointer() const { return m_ptr ? &A::m_ptr : 0; }9 10 A *m_ptr;11 12 A *getPtr();13 typedef A * (A::*MemberFnPointer)(void);14};15 16void testConditionalUse() {17 A obj;18 19 obj.m_ptr = &obj;20 clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}}21 clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}}22 clang_analyzer_eval(obj); // expected-warning{{TRUE}}23 24 obj.m_ptr = 0;25 clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}}26 clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}}27 clang_analyzer_eval(obj); // expected-warning{{FALSE}}28 29 clang_analyzer_eval(&A::getPtr); // expected-warning{{TRUE}}30 clang_analyzer_eval(A::MemberFnPointer(0)); // expected-warning{{FALSE}}31}32 33 34void testComparison() {35 clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}}36 clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}}37 38 clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{TRUE}}39}40 41namespace PR15742 {42 template <class _T1, class _T2> struct A {43 A (const _T1 &, const _T2 &);44 };45 46 typedef void *NPIdentifier;47 48 template <class T> class B {49 public:50 typedef A<NPIdentifier, bool (T::*) (const NPIdentifier *, unsigned,51 NPIdentifier *)> MethodMapMember;52 };53 54 class C : public B<C> {55 public:56 bool Find(const NPIdentifier *, unsigned, NPIdentifier *);57 };58 59 void InitStaticData () {60 C::MethodMapMember(0, &C::Find); // don't crash61 }62}63 64bool testDereferencing() {65 A obj;66 obj.m_ptr = 0;67 68 A::MemberPointer member = &A::m_ptr;69 70 clang_analyzer_eval(obj.*member == 0); // expected-warning{{TRUE}}71 72 member = 0;73 74 return obj.*member; // expected-warning{{The result of the '.*' expression is undefined}}75}76 77namespace testPointerToMemberFunction {78 struct A {79 virtual int foo() { return 1; }80 int bar() { return 2; }81 int static staticMemberFunction(int p) { return p + 1; };82 };83 84 struct B : public A {85 virtual int foo() { return 3; }86 };87 88 typedef int (A::*AFnPointer)();89 typedef int (B::*BFnPointer)();90 91 void testPointerToMemberCasts() {92 AFnPointer AFP = &A::bar;93 BFnPointer StaticCastedBase2Derived = static_cast<BFnPointer>(&A::bar),94 CCastedBase2Derived = (BFnPointer) (&A::bar);95 A a;96 B b;97 98 clang_analyzer_eval((a.*AFP)() == 2); // expected-warning{{TRUE}}99 clang_analyzer_eval((b.*StaticCastedBase2Derived)() == 2); // expected-warning{{TRUE}}100 clang_analyzer_eval(((b.*CCastedBase2Derived)() == 2)); // expected-warning{{TRUE}}101 }102 103 void testPointerToMemberVirtualCall() {104 A a;105 B b;106 A *APtr = &a;107 AFnPointer AFP = &A::foo;108 109 clang_analyzer_eval((APtr->*AFP)() == 1); // expected-warning{{TRUE}}110 111 APtr = &b;112 113 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}114 }115 116 void testPointerToStaticMemberCall() {117 int (*fPtr)(int) = &A::staticMemberFunction;118 if (fPtr != 0) { // no-crash119 clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}120 }121 }122} // end of testPointerToMemberFunction namespace123 124namespace testPointerToMemberData {125 struct A {126 int i;127 static int j;128 };129 130 void testPointerToMemberData() {131 int A::*AMdPointer = &A::i;132 A a;133 134 a.i = 42;135 a.*AMdPointer += 1;136 137 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}138 139 int *ptrToStaticField = &A::j;140 if (ptrToStaticField != 0) {141 *ptrToStaticField = 7;142 clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}143 clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}144 }145 }146} // end of testPointerToMemberData namespace147 148namespace testPointerToMemberMiscCasts {149struct B {150 int f;151};152 153struct D : public B {154 int g;155};156 157void foo() {158 D d;159 d.f = 7;160 161 int B::* pfb = &B::f;162 int D::* pfd = pfb;163 int v = d.*pfd;164 165 clang_analyzer_eval(v == 7); // expected-warning{{TRUE}}166}167} // end of testPointerToMemberMiscCasts namespace168 169namespace testPointerToMemberMiscCasts2 {170struct B {171 int f;172};173struct L : public B { };174struct R : public B { };175struct D : public L, R { };176 177void foo() {178 D d;179 180 int B::* pb = &B::f;181 int L::* pl = pb;182 int R::* pr = pb;183 184 int D::* pdl = pl;185 int D::* pdr = pr;186 187 clang_analyzer_eval(pdl == pdr); // expected-warning{{FALSE}}188 clang_analyzer_eval(pb == pl); // expected-warning{{TRUE}}189}190} // end of testPointerToMemberMiscCasts2 namespace191 192namespace testPointerToMemberDiamond {193struct B {194 int f;195};196struct L1 : public B { };197struct R1 : public B { };198struct M : public L1, R1 { };199struct L2 : public M { };200struct R2 : public M { };201struct D2 : public L2, R2 { };202 203void diamond() {204 M m;205 206 static_cast<L1 *>(&m)->f = 7;207 static_cast<R1 *>(&m)->f = 16;208 209 int L1::* pl1 = &B::f;210 int M::* pm_via_l1 = pl1;211 212 int R1::* pr1 = &B::f;213 int M::* pm_via_r1 = pr1;214 215 clang_analyzer_eval(m.*(pm_via_l1) == 7); // expected-warning {{TRUE}}216 clang_analyzer_eval(m.*(pm_via_r1) == 16); // expected-warning {{TRUE}}217}218 219void double_diamond() {220 D2 d2;221 222 static_cast<L1 *>(static_cast<L2 *>(&d2))->f = 1;223 static_cast<L1 *>(static_cast<R2 *>(&d2))->f = 2;224 static_cast<R1 *>(static_cast<L2 *>(&d2))->f = 3;225 static_cast<R1 *>(static_cast<R2 *>(&d2))->f = 4;226 227 clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int L2::*>(static_cast<int L1::*>(&B::f)))) == 1); // expected-warning {{TRUE}}228 clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int L1::*>(&B::f)))) == 2); // expected-warning {{TRUE}}229 clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int L2::*>(static_cast<int R1::*>(&B::f)))) == 3); // expected-warning {{TRUE}}230 clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int R1::*>(&B::f)))) == 4); // expected-warning {{TRUE}}231}232} // end of testPointerToMemberDiamond namespace233 234namespace testAnonymousMember {235struct A {236 int a;237 struct {238 int b;239 int c;240 };241 struct {242 struct {243 int d;244 int e;245 };246 };247 struct {248 union {249 int f;250 };251 };252};253 254void test() {255 clang_analyzer_eval(&A::a); // expected-warning{{TRUE}}256 clang_analyzer_eval(&A::b); // expected-warning{{TRUE}}257 clang_analyzer_eval(&A::c); // expected-warning{{TRUE}}258 clang_analyzer_eval(&A::d); // expected-warning{{TRUE}}259 clang_analyzer_eval(&A::e); // expected-warning{{TRUE}}260 clang_analyzer_eval(&A::f); // expected-warning{{TRUE}}261 262 int A::*ap = &A::a,263 A::*bp = &A::b,264 A::*cp = &A::c,265 A::*dp = &A::d,266 A::*ep = &A::e,267 A::*fp = &A::f;268 269 clang_analyzer_eval(ap); // expected-warning{{TRUE}}270 clang_analyzer_eval(bp); // expected-warning{{TRUE}}271 clang_analyzer_eval(cp); // expected-warning{{TRUE}}272 clang_analyzer_eval(dp); // expected-warning{{TRUE}}273 clang_analyzer_eval(ep); // expected-warning{{TRUE}}274 clang_analyzer_eval(fp); // expected-warning{{TRUE}}275 276 A a;277 a.a = 1;278 a.b = 2;279 a.c = 3;280 a.d = 4;281 a.e = 5;282 283 clang_analyzer_eval(a.*ap == 1); // expected-warning{{TRUE}}284 clang_analyzer_eval(a.*bp == 2); // expected-warning{{TRUE}}285 clang_analyzer_eval(a.*cp == 3); // expected-warning{{TRUE}}286 clang_analyzer_eval(a.*dp == 4); // expected-warning{{TRUE}}287 clang_analyzer_eval(a.*ep == 5); // expected-warning{{TRUE}}288}289} // namespace testAnonymousMember290 291namespace testStaticCasting {292// From bug #48739293struct Grandfather {294 int field;295};296 297struct Father : public Grandfather {};298struct Son : public Father {};299 300void test() {301 int Son::*sf = &Son::field;302 Grandfather grandpa;303 grandpa.field = 10;304 int Grandfather::*gpf1 = static_cast<int Grandfather::*>(sf);305 int Grandfather::*gpf2 = static_cast<int Grandfather::*>(static_cast<int Father::*>(sf));306 int Grandfather::*gpf3 = static_cast<int Grandfather::*>(static_cast<int Son::*>(static_cast<int Father::*>(sf)));307 clang_analyzer_eval(grandpa.*gpf1 == 10); // expected-warning{{TRUE}}308 clang_analyzer_eval(grandpa.*gpf2 == 10); // expected-warning{{TRUE}}309 clang_analyzer_eval(grandpa.*gpf3 == 10); // expected-warning{{TRUE}}310}311} // namespace testStaticCasting312 313namespace D126198 {314class Base {};315class Derived : public Base {};316int foo(int Derived::*);317 318int test() {319 int Base::*p = nullptr;320 return foo(p); // no-crash321}322} // namespace D126198323