xref: /aosp_15_r20/external/clang/test/Analysis/operator-calls.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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