| // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s |
| |
| void clang_analyzer_eval(bool); |
| |
| struct A { |
| // This conversion operator allows implicit conversion to bool but not to other integer types. |
| typedef A * (A::*MemberPointer); |
| operator MemberPointer() const { return m_ptr ? &A::m_ptr : 0; } |
| |
| A *m_ptr; |
| |
| A *getPtr(); |
| typedef A * (A::*MemberFnPointer)(void); |
| }; |
| |
| void testConditionalUse() { |
| A obj; |
| |
| obj.m_ptr = &obj; |
| clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}} |
| clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}} |
| clang_analyzer_eval(obj); // expected-warning{{TRUE}} |
| |
| obj.m_ptr = 0; |
| clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}} |
| clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}} |
| clang_analyzer_eval(obj); // expected-warning{{FALSE}} |
| |
| clang_analyzer_eval(&A::getPtr); // expected-warning{{TRUE}} |
| clang_analyzer_eval(A::MemberFnPointer(0)); // expected-warning{{FALSE}} |
| } |
| |
| |
| void testComparison() { |
| clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}} |
| clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}} |
| |
| // FIXME: Should be TRUE. |
| clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}} |
| } |
| |
| namespace PR15742 { |
| template <class _T1, class _T2> struct A { |
| A (const _T1 &, const _T2 &); |
| }; |
| |
| typedef void *NPIdentifier; |
| |
| template <class T> class B { |
| public: |
| typedef A<NPIdentifier, bool (T::*) (const NPIdentifier *, unsigned, |
| NPIdentifier *)> MethodMapMember; |
| }; |
| |
| class C : public B<C> { |
| public: |
| bool Find(const NPIdentifier *, unsigned, NPIdentifier *); |
| }; |
| |
| void InitStaticData () { |
| C::MethodMapMember(0, &C::Find); // don't crash |
| } |
| } |
| |
| // --------------- |
| // FALSE NEGATIVES |
| // --------------- |
| |
| bool testDereferencing() { |
| A obj; |
| obj.m_ptr = 0; |
| |
| A::MemberPointer member = &A::m_ptr; |
| |
| // FIXME: Should be TRUE. |
| clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}} |
| |
| member = 0; |
| |
| // FIXME: Should emit a null dereference. |
| return obj.*member; // no-warning |
| } |