1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s 2 3 void clang_analyzer_eval(bool); 4 5 struct 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 16 void 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 34 void testComparison() { 35 clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}} 36 clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}} 37 38 // FIXME: Should be TRUE. 39 clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}} 40 } 41 42 namespace PR15742 { 43 template <class _T1, class _T2> struct A { 44 A (const _T1 &, const _T2 &); 45 }; 46 47 typedef void *NPIdentifier; 48 49 template <class T> class B { 50 public: 51 typedef A<NPIdentifier, bool (T::*) (const NPIdentifier *, unsigned, 52 NPIdentifier *)> MethodMapMember; 53 }; 54 55 class C : public B<C> { 56 public: 57 bool Find(const NPIdentifier *, unsigned, NPIdentifier *); 58 }; 59 60 void InitStaticData () { 61 C::MethodMapMember(0, &C::Find); // don't crash 62 } 63 } 64 65 // --------------- 66 // FALSE NEGATIVES 67 // --------------- 68 69 bool testDereferencing() { 70 A obj; 71 obj.m_ptr = 0; 72 73 A::MemberPointer member = &A::m_ptr; 74 75 // FIXME: Should be TRUE. 76 clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}} 77 78 member = 0; 79 80 // FIXME: Should emit a null dereference. 81 return obj.*member; // no-warning 82 } 83