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