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