xref: /minix3/external/bsd/llvm/dist/clang/test/Analysis/pointer-to-member.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
2*f4a2713aSLionel Sambuc 
3*f4a2713aSLionel Sambuc void clang_analyzer_eval(bool);
4*f4a2713aSLionel Sambuc 
5*f4a2713aSLionel Sambuc struct A {
6*f4a2713aSLionel Sambuc   // This conversion operator allows implicit conversion to bool but not to other integer types.
7*f4a2713aSLionel Sambuc   typedef A * (A::*MemberPointer);
operator MemberPointerA8*f4a2713aSLionel Sambuc   operator MemberPointer() const { return m_ptr ? &A::m_ptr : 0; }
9*f4a2713aSLionel Sambuc 
10*f4a2713aSLionel Sambuc   A *m_ptr;
11*f4a2713aSLionel Sambuc 
12*f4a2713aSLionel Sambuc   A *getPtr();
13*f4a2713aSLionel Sambuc   typedef A * (A::*MemberFnPointer)(void);
14*f4a2713aSLionel Sambuc };
15*f4a2713aSLionel Sambuc 
testConditionalUse()16*f4a2713aSLionel Sambuc void testConditionalUse() {
17*f4a2713aSLionel Sambuc   A obj;
18*f4a2713aSLionel Sambuc 
19*f4a2713aSLionel Sambuc   obj.m_ptr = &obj;
20*f4a2713aSLionel Sambuc   clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}}
21*f4a2713aSLionel Sambuc   clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}}
22*f4a2713aSLionel Sambuc   clang_analyzer_eval(obj); // expected-warning{{TRUE}}
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc   obj.m_ptr = 0;
25*f4a2713aSLionel Sambuc   clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}}
26*f4a2713aSLionel Sambuc   clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}}
27*f4a2713aSLionel Sambuc   clang_analyzer_eval(obj); // expected-warning{{FALSE}}
28*f4a2713aSLionel Sambuc 
29*f4a2713aSLionel Sambuc   clang_analyzer_eval(&A::getPtr); // expected-warning{{TRUE}}
30*f4a2713aSLionel Sambuc   clang_analyzer_eval(A::MemberFnPointer(0)); // expected-warning{{FALSE}}
31*f4a2713aSLionel Sambuc }
32*f4a2713aSLionel Sambuc 
33*f4a2713aSLionel Sambuc 
testComparison()34*f4a2713aSLionel Sambuc void testComparison() {
35*f4a2713aSLionel Sambuc   clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}}
36*f4a2713aSLionel Sambuc   clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}}
37*f4a2713aSLionel Sambuc 
38*f4a2713aSLionel Sambuc   // FIXME: Should be TRUE.
39*f4a2713aSLionel Sambuc   clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}}
40*f4a2713aSLionel Sambuc }
41*f4a2713aSLionel Sambuc 
42*f4a2713aSLionel Sambuc namespace PR15742 {
43*f4a2713aSLionel Sambuc   template <class _T1, class _T2> struct A {
44*f4a2713aSLionel Sambuc     A (const _T1 &, const _T2 &);
45*f4a2713aSLionel Sambuc   };
46*f4a2713aSLionel Sambuc 
47*f4a2713aSLionel Sambuc   typedef void *NPIdentifier;
48*f4a2713aSLionel Sambuc 
49*f4a2713aSLionel Sambuc   template <class T> class B {
50*f4a2713aSLionel Sambuc   public:
51*f4a2713aSLionel Sambuc     typedef A<NPIdentifier, bool (T::*) (const NPIdentifier *, unsigned,
52*f4a2713aSLionel Sambuc                                          NPIdentifier *)> MethodMapMember;
53*f4a2713aSLionel Sambuc   };
54*f4a2713aSLionel Sambuc 
55*f4a2713aSLionel Sambuc   class C : public B<C> {
56*f4a2713aSLionel Sambuc   public:
57*f4a2713aSLionel Sambuc     bool Find(const NPIdentifier *, unsigned, NPIdentifier *);
58*f4a2713aSLionel Sambuc   };
59*f4a2713aSLionel Sambuc 
InitStaticData()60*f4a2713aSLionel Sambuc   void InitStaticData () {
61*f4a2713aSLionel Sambuc     C::MethodMapMember(0, &C::Find); // don't crash
62*f4a2713aSLionel Sambuc   }
63*f4a2713aSLionel Sambuc }
64*f4a2713aSLionel Sambuc 
65*f4a2713aSLionel Sambuc // ---------------
66*f4a2713aSLionel Sambuc // FALSE NEGATIVES
67*f4a2713aSLionel Sambuc // ---------------
68*f4a2713aSLionel Sambuc 
testDereferencing()69*f4a2713aSLionel Sambuc bool testDereferencing() {
70*f4a2713aSLionel Sambuc   A obj;
71*f4a2713aSLionel Sambuc   obj.m_ptr = 0;
72*f4a2713aSLionel Sambuc 
73*f4a2713aSLionel Sambuc   A::MemberPointer member = &A::m_ptr;
74*f4a2713aSLionel Sambuc 
75*f4a2713aSLionel Sambuc   // FIXME: Should be TRUE.
76*f4a2713aSLionel Sambuc   clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}}
77*f4a2713aSLionel Sambuc 
78*f4a2713aSLionel Sambuc   member = 0;
79*f4a2713aSLionel Sambuc 
80*f4a2713aSLionel Sambuc   // FIXME: Should emit a null dereference.
81*f4a2713aSLionel Sambuc   return obj.*member; // no-warning
82*f4a2713aSLionel Sambuc }
83