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