1*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
2*67e74705SXin Li void clang_analyzer_eval(bool);
3*67e74705SXin Li
4*67e74705SXin Li struct X0 { };
5*67e74705SXin Li bool operator==(const X0&, const X0&);
6*67e74705SXin Li
7*67e74705SXin Li // PR7287
8*67e74705SXin Li struct test { int a[2]; };
9*67e74705SXin Li
t2()10*67e74705SXin Li void t2() {
11*67e74705SXin Li test p = {{1,2}};
12*67e74705SXin Li test q;
13*67e74705SXin Li q = p;
14*67e74705SXin Li }
15*67e74705SXin Li
PR7287(X0 a,X0 b)16*67e74705SXin Li bool PR7287(X0 a, X0 b) {
17*67e74705SXin Li return operator==(a, b);
18*67e74705SXin Li }
19*67e74705SXin Li
20*67e74705SXin Li
21*67e74705SXin Li // Inlining non-static member operators mistakenly treated 'this' as the first
22*67e74705SXin Li // argument for a while.
23*67e74705SXin Li
24*67e74705SXin Li struct IntComparable {
operator ==IntComparable25*67e74705SXin Li bool operator==(int x) const {
26*67e74705SXin Li return x == 0;
27*67e74705SXin Li }
28*67e74705SXin Li };
29*67e74705SXin Li
testMemberOperator(IntComparable B)30*67e74705SXin Li void testMemberOperator(IntComparable B) {
31*67e74705SXin Li clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
32*67e74705SXin Li }
33*67e74705SXin Li
34*67e74705SXin Li
35*67e74705SXin Li
36*67e74705SXin Li namespace UserDefinedConversions {
37*67e74705SXin Li class Convertible {
38*67e74705SXin Li public:
operator int() const39*67e74705SXin Li operator int() const {
40*67e74705SXin Li return 42;
41*67e74705SXin Li }
operator bool() const42*67e74705SXin Li operator bool() const {
43*67e74705SXin Li return true;
44*67e74705SXin Li }
45*67e74705SXin Li };
46*67e74705SXin Li
test(const Convertible & obj)47*67e74705SXin Li void test(const Convertible &obj) {
48*67e74705SXin Li clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
49*67e74705SXin Li clang_analyzer_eval(obj); // expected-warning{{TRUE}}
50*67e74705SXin Li }
51*67e74705SXin Li }
52*67e74705SXin Li
53*67e74705SXin Li
54*67e74705SXin Li namespace RValues {
55*67e74705SXin Li struct SmallOpaque {
56*67e74705SXin Li float x;
operator +RValues::SmallOpaque57*67e74705SXin Li int operator +() const {
58*67e74705SXin Li return (int)x;
59*67e74705SXin Li }
60*67e74705SXin Li };
61*67e74705SXin Li
62*67e74705SXin Li struct LargeOpaque {
63*67e74705SXin Li float x[4];
operator +RValues::LargeOpaque64*67e74705SXin Li int operator +() const {
65*67e74705SXin Li return (int)x[0];
66*67e74705SXin Li }
67*67e74705SXin Li };
68*67e74705SXin Li
getSmallOpaque()69*67e74705SXin Li SmallOpaque getSmallOpaque() {
70*67e74705SXin Li SmallOpaque obj;
71*67e74705SXin Li obj.x = 1.0;
72*67e74705SXin Li return obj;
73*67e74705SXin Li }
74*67e74705SXin Li
getLargeOpaque()75*67e74705SXin Li LargeOpaque getLargeOpaque() {
76*67e74705SXin Li LargeOpaque obj = LargeOpaque();
77*67e74705SXin Li obj.x[0] = 1.0;
78*67e74705SXin Li return obj;
79*67e74705SXin Li }
80*67e74705SXin Li
test(int coin)81*67e74705SXin Li void test(int coin) {
82*67e74705SXin Li // Force a cache-out when we try to conjure a temporary region for the operator call.
83*67e74705SXin Li // ...then, don't crash.
84*67e74705SXin Li clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
85*67e74705SXin Li clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
86*67e74705SXin Li }
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li namespace SynthesizedAssignment {
90*67e74705SXin Li struct A {
91*67e74705SXin Li int a;
operator =SynthesizedAssignment::A92*67e74705SXin Li A& operator=(A& other) { a = -other.a; return *this; }
operator =SynthesizedAssignment::A93*67e74705SXin Li A& operator=(A&& other) { a = other.a+1; return *this; }
94*67e74705SXin Li };
95*67e74705SXin Li
96*67e74705SXin Li struct B {
97*67e74705SXin Li int x;
98*67e74705SXin Li A a[3];
99*67e74705SXin Li B& operator=(B&) = default;
100*67e74705SXin Li B& operator=(B&&) = default;
101*67e74705SXin Li };
102*67e74705SXin Li
103*67e74705SXin Li // This used to produce a warning about the iteration variable in the
104*67e74705SXin Li // synthesized assignment operator being undefined.
testNoWarning()105*67e74705SXin Li void testNoWarning() {
106*67e74705SXin Li B v, u;
107*67e74705SXin Li u = v;
108*67e74705SXin Li }
109*67e74705SXin Li
testNoWarningMove()110*67e74705SXin Li void testNoWarningMove() {
111*67e74705SXin Li B v, u;
112*67e74705SXin Li u = static_cast<B &&>(v);
113*67e74705SXin Li }
114*67e74705SXin Li
testConsistency()115*67e74705SXin Li void testConsistency() {
116*67e74705SXin Li B v, u;
117*67e74705SXin Li v.a[1].a = 47;
118*67e74705SXin Li v.a[2].a = 42;
119*67e74705SXin Li u = v;
120*67e74705SXin Li clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}}
121*67e74705SXin Li clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}}
122*67e74705SXin Li }
123*67e74705SXin Li
testConsistencyMove()124*67e74705SXin Li void testConsistencyMove() {
125*67e74705SXin Li B v, u;
126*67e74705SXin Li v.a[1].a = 47;
127*67e74705SXin Li v.a[2].a = 42;
128*67e74705SXin Li u = static_cast<B &&>(v);
129*67e74705SXin Li clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}}
130*67e74705SXin Li clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}}
131*67e74705SXin Li }
132*67e74705SXin Li }
133