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