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 13 void testConditionalUse() { 14 A obj; 15 16 obj.m_ptr = &obj; 17 clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}} 18 clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}} 19 clang_analyzer_eval(obj); // expected-warning{{TRUE}} 20 21 obj.m_ptr = 0; 22 clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}} 23 clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}} 24 clang_analyzer_eval(obj); // expected-warning{{FALSE}} 25 } 26 27 // --------------- 28 // FALSE NEGATIVES 29 // --------------- 30 31 bool testDereferencing() { 32 A obj; 33 obj.m_ptr = 0; 34 35 A::MemberPointer member = &A::m_ptr; 36 37 // FIXME: Should be TRUE. 38 clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}} 39 40 member = 0; 41 42 // FIXME: Should emit a null dereference. 43 return obj.*member; // no-warning 44 } 45