1 | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s |
2 | void clang_analyzer_eval(bool); |
3 | |
4 | struct X0 { }; |
5 | bool operator==(const X0&, const X0&); |
6 | |
7 | // PR7287 |
8 | struct test { int a[2]; }; |
9 | |
10 | void t2() { |
11 | test p = {{1,2}}; |
12 | test q; |
13 | q = p; |
14 | } |
15 | |
16 | bool 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 | |
24 | struct IntComparable { |
25 | bool operator==(int x) const { |
26 | return x == 0; |
27 | } |
28 | }; |
29 | |
30 | void testMemberOperator(IntComparable B) { |
31 | clang_analyzer_eval(B == 0); // expected-warning{{TRUE}} |
32 | } |
33 | |
34 | |
35 | |
36 | namespace 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 | |
54 | namespace 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 | |
89 | namespace 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 | |