1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s 2*67e74705SXin Li 3*67e74705SXin Li void clang_analyzer_eval(bool); 4*67e74705SXin Li 5*67e74705SXin Li struct A { 6*67e74705SXin Li // This conversion operator allows implicit conversion to bool but not to other integer types. 7*67e74705SXin Li typedef A * (A::*MemberPointer); operator MemberPointerA8*67e74705SXin Li operator MemberPointer() const { return m_ptr ? &A::m_ptr : 0; } 9*67e74705SXin Li 10*67e74705SXin Li A *m_ptr; 11*67e74705SXin Li 12*67e74705SXin Li A *getPtr(); 13*67e74705SXin Li typedef A * (A::*MemberFnPointer)(void); 14*67e74705SXin Li }; 15*67e74705SXin Li testConditionalUse()16*67e74705SXin Livoid testConditionalUse() { 17*67e74705SXin Li A obj; 18*67e74705SXin Li 19*67e74705SXin Li obj.m_ptr = &obj; 20*67e74705SXin Li clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}} 21*67e74705SXin Li clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}} 22*67e74705SXin Li clang_analyzer_eval(obj); // expected-warning{{TRUE}} 23*67e74705SXin Li 24*67e74705SXin Li obj.m_ptr = 0; 25*67e74705SXin Li clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}} 26*67e74705SXin Li clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}} 27*67e74705SXin Li clang_analyzer_eval(obj); // expected-warning{{FALSE}} 28*67e74705SXin Li 29*67e74705SXin Li clang_analyzer_eval(&A::getPtr); // expected-warning{{TRUE}} 30*67e74705SXin Li clang_analyzer_eval(A::MemberFnPointer(0)); // expected-warning{{FALSE}} 31*67e74705SXin Li } 32*67e74705SXin Li 33*67e74705SXin Li testComparison()34*67e74705SXin Livoid testComparison() { 35*67e74705SXin Li clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}} 36*67e74705SXin Li clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}} 37*67e74705SXin Li 38*67e74705SXin Li // FIXME: Should be TRUE. 39*67e74705SXin Li clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}} 40*67e74705SXin Li } 41*67e74705SXin Li 42*67e74705SXin Li namespace PR15742 { 43*67e74705SXin Li template <class _T1, class _T2> struct A { 44*67e74705SXin Li A (const _T1 &, const _T2 &); 45*67e74705SXin Li }; 46*67e74705SXin Li 47*67e74705SXin Li typedef void *NPIdentifier; 48*67e74705SXin Li 49*67e74705SXin Li template <class T> class B { 50*67e74705SXin Li public: 51*67e74705SXin Li typedef A<NPIdentifier, bool (T::*) (const NPIdentifier *, unsigned, 52*67e74705SXin Li NPIdentifier *)> MethodMapMember; 53*67e74705SXin Li }; 54*67e74705SXin Li 55*67e74705SXin Li class C : public B<C> { 56*67e74705SXin Li public: 57*67e74705SXin Li bool Find(const NPIdentifier *, unsigned, NPIdentifier *); 58*67e74705SXin Li }; 59*67e74705SXin Li InitStaticData()60*67e74705SXin Li void InitStaticData () { 61*67e74705SXin Li C::MethodMapMember(0, &C::Find); // don't crash 62*67e74705SXin Li } 63*67e74705SXin Li } 64*67e74705SXin Li 65*67e74705SXin Li // --------------- 66*67e74705SXin Li // FALSE NEGATIVES 67*67e74705SXin Li // --------------- 68*67e74705SXin Li testDereferencing()69*67e74705SXin Libool testDereferencing() { 70*67e74705SXin Li A obj; 71*67e74705SXin Li obj.m_ptr = 0; 72*67e74705SXin Li 73*67e74705SXin Li A::MemberPointer member = &A::m_ptr; 74*67e74705SXin Li 75*67e74705SXin Li // FIXME: Should be TRUE. 76*67e74705SXin Li clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}} 77*67e74705SXin Li 78*67e74705SXin Li member = 0; 79*67e74705SXin Li 80*67e74705SXin Li // FIXME: Should emit a null dereference. 81*67e74705SXin Li return obj.*member; // no-warning 82*67e74705SXin Li } 83