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