pointer-to-member.cpp revision 0156439a3d718ea0ef5922c38d189a60829c8a86
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -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
13void testConditionalUse() {
14  A obj;
15
16  obj.m_ptr = &obj;
17  clang_analyzer_eval(obj.m_ptr); // expected-warning{{TRUE}}
18  clang_analyzer_eval(&A::m_ptr); // expected-warning{{TRUE}}
19  clang_analyzer_eval(obj); // expected-warning{{TRUE}}
20
21  obj.m_ptr = 0;
22  clang_analyzer_eval(obj.m_ptr); // expected-warning{{FALSE}}
23  clang_analyzer_eval(A::MemberPointer(0)); // expected-warning{{FALSE}}
24  clang_analyzer_eval(obj); // expected-warning{{FALSE}}
25}
26
27// ---------------
28// FALSE NEGATIVES
29// ---------------
30
31bool testDereferencing() {
32  A obj;
33  obj.m_ptr = 0;
34
35  A::MemberPointer member = &A::m_ptr;
36
37  // FIXME: Should be TRUE.
38  clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}}
39
40  member = 0;
41
42  // FIXME: Should emit a null dereference.
43  return obj.*member; // no-warning
44}
45