1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
3 void clang_analyzer_eval(bool);
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; }
13 typedef A
* (A::*MemberFnPointer
)(void);
16 void testConditionalUse() {
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}}
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}}
29 clang_analyzer_eval(&A::getPtr
); // expected-warning{{TRUE}}
30 clang_analyzer_eval(A::MemberFnPointer(0)); // expected-warning{{FALSE}}
34 void testComparison() {
35 clang_analyzer_eval(&A::getPtr
== &A::getPtr
); // expected-warning{{TRUE}}
36 clang_analyzer_eval(&A::getPtr
== 0); // expected-warning{{FALSE}}
38 clang_analyzer_eval(&A::m_ptr
== &A::m_ptr
); // expected-warning{{TRUE}}
42 template <class _T1
, class _T2
> struct A
{
43 A (const _T1
&, const _T2
&);
46 typedef void *NPIdentifier
;
48 template <class T
> class B
{
50 typedef A
<NPIdentifier
, bool (T::*) (const NPIdentifier
*, unsigned,
51 NPIdentifier
*)> MethodMapMember
;
54 class C
: public B
<C
> {
56 bool Find(const NPIdentifier
*, unsigned, NPIdentifier
*);
59 void InitStaticData () {
60 C::MethodMapMember(0, &C::Find
); // don't crash
64 bool testDereferencing() {
68 A::MemberPointer member
= &A::m_ptr
;
70 clang_analyzer_eval(obj
.*member
== 0); // expected-warning{{TRUE}}
74 return obj
.*member
; // expected-warning{{The result of the '.*' expression is undefined}}
77 namespace testPointerToMemberFunction
{
79 virtual int foo() { return 1; }
80 int bar() { return 2; }
81 int static staticMemberFunction(int p
) { return p
+ 1; };
85 virtual int foo() { return 3; }
88 typedef int (A::*AFnPointer
)();
89 typedef int (B::*BFnPointer
)();
91 void testPointerToMemberCasts() {
92 AFnPointer AFP
= &A::bar
;
93 BFnPointer StaticCastedBase2Derived
= static_cast<BFnPointer
>(&A::bar
),
94 CCastedBase2Derived
= (BFnPointer
) (&A::bar
);
98 clang_analyzer_eval((a
.*AFP
)() == 2); // expected-warning{{TRUE}}
99 clang_analyzer_eval((b
.*StaticCastedBase2Derived
)() == 2); // expected-warning{{TRUE}}
100 clang_analyzer_eval(((b
.*CCastedBase2Derived
)() == 2)); // expected-warning{{TRUE}}
103 void testPointerToMemberVirtualCall() {
107 AFnPointer AFP
= &A::foo
;
109 clang_analyzer_eval((APtr
->*AFP
)() == 1); // expected-warning{{TRUE}}
113 clang_analyzer_eval((APtr
->*AFP
)() == 3); // expected-warning{{TRUE}}
116 void testPointerToStaticMemberCall() {
117 int (*fPtr
)(int) = &A::staticMemberFunction
;
118 if (fPtr
!= 0) { // no-crash
119 clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
122 } // end of testPointerToMemberFunction namespace
124 namespace testPointerToMemberData
{
130 void testPointerToMemberData() {
131 int A::*AMdPointer
= &A::i
;
137 clang_analyzer_eval(a
.i
== 43); // expected-warning{{TRUE}}
139 int *ptrToStaticField
= &A::j
;
140 if (ptrToStaticField
!= 0) {
141 *ptrToStaticField
= 7;
142 clang_analyzer_eval(*ptrToStaticField
== 7); // expected-warning{{TRUE}}
143 clang_analyzer_eval(A::j
== 7); // expected-warning{{TRUE}}
146 } // end of testPointerToMemberData namespace
148 namespace testPointerToMemberMiscCasts
{
153 struct D
: public B
{
161 int B::* pfb
= &B::f
;
165 clang_analyzer_eval(v
== 7); // expected-warning{{TRUE}}
167 } // end of testPointerToMemberMiscCasts namespace
169 namespace testPointerToMemberMiscCasts2
{
173 struct L
: public B
{ };
174 struct R
: public B
{ };
175 struct D
: public L
, R
{ };
187 clang_analyzer_eval(pdl
== pdr
); // expected-warning{{FALSE}}
188 clang_analyzer_eval(pb
== pl
); // expected-warning{{TRUE}}
190 } // end of testPointerToMemberMiscCasts2 namespace
192 namespace testPointerToMemberDiamond
{
196 struct L1
: public B
{ };
197 struct R1
: public B
{ };
198 struct M
: public L1
, R1
{ };
199 struct L2
: public M
{ };
200 struct R2
: public M
{ };
201 struct D2
: public L2
, R2
{ };
206 static_cast<L1
*>(&m
)->f
= 7;
207 static_cast<R1
*>(&m
)->f
= 16;
209 int L1::* pl1
= &B::f
;
210 int M::* pm_via_l1
= pl1
;
212 int R1::* pr1
= &B::f
;
213 int M::* pm_via_r1
= pr1
;
215 clang_analyzer_eval(m
.*(pm_via_l1
) == 7); // expected-warning {{TRUE}}
216 clang_analyzer_eval(m
.*(pm_via_r1
) == 16); // expected-warning {{TRUE}}
219 void double_diamond() {
222 static_cast<L1
*>(static_cast<L2
*>(&d2
))->f
= 1;
223 static_cast<L1
*>(static_cast<R2
*>(&d2
))->f
= 2;
224 static_cast<R1
*>(static_cast<L2
*>(&d2
))->f
= 3;
225 static_cast<R1
*>(static_cast<R2
*>(&d2
))->f
= 4;
227 clang_analyzer_eval(d2
.*(static_cast<int D2::*>(static_cast<int L2::*>(static_cast<int L1::*>(&B::f
)))) == 1); // expected-warning {{TRUE}}
228 clang_analyzer_eval(d2
.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int L1::*>(&B::f
)))) == 2); // expected-warning {{TRUE}}
229 clang_analyzer_eval(d2
.*(static_cast<int D2::*>(static_cast<int L2::*>(static_cast<int R1::*>(&B::f
)))) == 3); // expected-warning {{TRUE}}
230 clang_analyzer_eval(d2
.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int R1::*>(&B::f
)))) == 4); // expected-warning {{TRUE}}
232 } // end of testPointerToMemberDiamond namespace
234 namespace testAnonymousMember
{
255 clang_analyzer_eval(&A::a
); // expected-warning{{TRUE}}
256 clang_analyzer_eval(&A::b
); // expected-warning{{TRUE}}
257 clang_analyzer_eval(&A::c
); // expected-warning{{TRUE}}
258 clang_analyzer_eval(&A::d
); // expected-warning{{TRUE}}
259 clang_analyzer_eval(&A::e
); // expected-warning{{TRUE}}
260 clang_analyzer_eval(&A::f
); // expected-warning{{TRUE}}
269 clang_analyzer_eval(ap
); // expected-warning{{TRUE}}
270 clang_analyzer_eval(bp
); // expected-warning{{TRUE}}
271 clang_analyzer_eval(cp
); // expected-warning{{TRUE}}
272 clang_analyzer_eval(dp
); // expected-warning{{TRUE}}
273 clang_analyzer_eval(ep
); // expected-warning{{TRUE}}
274 clang_analyzer_eval(fp
); // expected-warning{{TRUE}}
283 clang_analyzer_eval(a
.*ap
== 1); // expected-warning{{TRUE}}
284 clang_analyzer_eval(a
.*bp
== 2); // expected-warning{{TRUE}}
285 clang_analyzer_eval(a
.*cp
== 3); // expected-warning{{TRUE}}
286 clang_analyzer_eval(a
.*dp
== 4); // expected-warning{{TRUE}}
287 clang_analyzer_eval(a
.*ep
== 5); // expected-warning{{TRUE}}
289 } // namespace testAnonymousMember
291 namespace testStaticCasting
{
297 struct Father
: public Grandfather
{};
298 struct Son
: public Father
{};
301 int Son::*sf
= &Son::field
;
304 int Grandfather::*gpf1
= static_cast<int Grandfather::*>(sf
);
305 int Grandfather::*gpf2
= static_cast<int Grandfather::*>(static_cast<int Father::*>(sf
));
306 int Grandfather::*gpf3
= static_cast<int Grandfather::*>(static_cast<int Son::*>(static_cast<int Father::*>(sf
)));
307 clang_analyzer_eval(grandpa
.*gpf1
== 10); // expected-warning{{TRUE}}
308 clang_analyzer_eval(grandpa
.*gpf2
== 10); // expected-warning{{TRUE}}
309 clang_analyzer_eval(grandpa
.*gpf3
== 10); // expected-warning{{TRUE}}
311 } // namespace testStaticCasting
315 class Derived
: public Base
{};
316 int foo(int Derived::*);
319 int Base::*p
= nullptr;
320 return foo(p
); // no-crash
322 } // namespace D126198