1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
2
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  // FIXME: Should be TRUE.
39  clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}}
40}
41
42namespace 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
69bool 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