1 // RUN: %clang_analyze_cc1 -std=c++14 \
2 // RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
3 // RUN: -analyzer-output=text -verify %s
4
5 #include "Inputs/llvm.h"
6
7 namespace clang {
8 struct Shape {
9 template <typename T>
10 const T *castAs() const;
11
12 template <typename T>
13 const T *getAs() const;
14 };
15 class Triangle : public Shape {};
16 class Rectangle : public Shape {};
17 class Hexagon : public Shape {};
18 class Circle : public Shape {};
19 } // namespace clang
20
21 using namespace llvm;
22 using namespace clang;
23
evalReferences(const Shape & S)24 void evalReferences(const Shape &S) {
25 const auto &C = dyn_cast<Circle>(S);
26 // expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
27 // expected-note@-2 {{Dereference of null pointer}}
28 // expected-warning@-3 {{Dereference of null pointer}}
29 }
30
evalNonNullParamNonNullReturnReference(const Shape & S)31 void evalNonNullParamNonNullReturnReference(const Shape &S) {
32 const auto *C = dyn_cast_or_null<Circle>(S);
33 // expected-note@-1 {{'C' initialized here}}
34
35 if (!dyn_cast_or_null<Circle>(C)) {
36 // expected-note@-1 {{'C' is a 'Circle'}}
37 // expected-note@-2 {{Taking false branch}}
38 return;
39 }
40
41 if (dyn_cast_or_null<Triangle>(C)) {
42 // expected-note@-1 {{Assuming 'C' is not a 'Triangle'}}
43 // expected-note@-2 {{Taking false branch}}
44 return;
45 }
46
47 if (dyn_cast_or_null<Rectangle>(C)) {
48 // expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}}
49 // expected-note@-2 {{Taking false branch}}
50 return;
51 }
52
53 if (dyn_cast_or_null<Hexagon>(C)) {
54 // expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}}
55 // expected-note@-2 {{Taking false branch}}
56 return;
57 }
58
59 if (isa<Triangle>(C)) {
60 // expected-note@-1 {{'C' is not a 'Triangle'}}
61 // expected-note@-2 {{Taking false branch}}
62 return;
63 }
64
65 if (isa<Triangle, Rectangle>(C)) {
66 // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle'}}
67 // expected-note@-2 {{Taking false branch}}
68 return;
69 }
70
71 if (isa<Triangle, Rectangle, Hexagon>(C)) {
72 // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle' nor a 'Hexagon'}}
73 // expected-note@-2 {{Taking false branch}}
74 return;
75 }
76
77 if (isa<Circle, Rectangle, Hexagon>(C)) {
78 // expected-note@-1 {{'C' is a 'Circle'}}
79 // expected-note@-2 {{Taking true branch}}
80
81 (void)(1 / !C);
82 // expected-note@-1 {{'C' is non-null}}
83 // expected-note@-2 {{Division by zero}}
84 // expected-warning@-3 {{Division by zero}}
85 }
86 }
87
evalNonNullParamNonNullReturn(const Shape * S)88 void evalNonNullParamNonNullReturn(const Shape *S) {
89 const auto *C = cast<Circle>(S);
90 // expected-note@-1 {{'S' is a 'Circle'}}
91 // expected-note@-2 {{'C' initialized here}}
92
93 if (!dyn_cast_or_null<Circle>(C)) {
94 // expected-note@-1 {{'C' is a 'Circle'}}
95 // expected-note@-2 {{Taking false branch}}
96 return;
97 }
98
99 if (dyn_cast_or_null<Triangle>(C)) {
100 // expected-note@-1 {{Assuming 'C' is not a 'Triangle'}}
101 // expected-note@-2 {{Taking false branch}}
102 return;
103 }
104
105 if (dyn_cast_or_null<Rectangle>(C)) {
106 // expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}}
107 // expected-note@-2 {{Taking false branch}}
108 return;
109 }
110
111 if (dyn_cast_or_null<Hexagon>(C)) {
112 // expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}}
113 // expected-note@-2 {{Taking false branch}}
114 return;
115 }
116
117 if (isa<Triangle>(C)) {
118 // expected-note@-1 {{'C' is not a 'Triangle'}}
119 // expected-note@-2 {{Taking false branch}}
120 return;
121 }
122
123 if (isa<Triangle, Rectangle>(C)) {
124 // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle'}}
125 // expected-note@-2 {{Taking false branch}}
126 return;
127 }
128
129 if (isa<Triangle, Rectangle, Hexagon>(C)) {
130 // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle' nor a 'Hexagon'}}
131 // expected-note@-2 {{Taking false branch}}
132 return;
133 }
134
135 if (isa<Circle, Rectangle, Hexagon>(C)) {
136 // expected-note@-1 {{'C' is a 'Circle'}}
137 // expected-note@-2 {{Taking true branch}}
138
139 (void)(1 / !C);
140 // expected-note@-1 {{'C' is non-null}}
141 // expected-note@-2 {{Division by zero}}
142 // expected-warning@-3 {{Division by zero}}
143 }
144 }
145
evalNonNullParamNullReturn(const Shape * S)146 void evalNonNullParamNullReturn(const Shape *S) {
147 const auto *C = dyn_cast_or_null<Circle>(S);
148 // expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
149
150 if (const auto *T = dyn_cast_or_null<Triangle>(S)) {
151 // expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
152 // expected-note@-2 {{'T' initialized here}}
153 // expected-note@-3 {{'T' is non-null}}
154 // expected-note@-4 {{Taking true branch}}
155
156 (void)(1 / !T);
157 // expected-note@-1 {{'T' is non-null}}
158 // expected-note@-2 {{Division by zero}}
159 // expected-warning@-3 {{Division by zero}}
160 }
161 }
162
evalNullParamNullReturn(const Shape * S)163 void evalNullParamNullReturn(const Shape *S) {
164 const auto *C = dyn_cast_or_null<Circle>(S);
165 // expected-note@-1 {{Assuming null pointer is passed into cast}}
166 // expected-note@-2 {{'C' initialized to a null pointer value}}
167
168 (void)(1 / (bool)C);
169 // expected-note@-1 {{Division by zero}}
170 // expected-warning@-2 {{Division by zero}}
171 }
172
evalZeroParamNonNullReturnPointer(const Shape * S)173 void evalZeroParamNonNullReturnPointer(const Shape *S) {
174 const auto *C = S->castAs<Circle>();
175 // expected-note@-1 {{'S' is a 'Circle'}}
176 // expected-note@-2 {{'C' initialized here}}
177
178 (void)(1 / !C);
179 // expected-note@-1 {{'C' is non-null}}
180 // expected-note@-2 {{Division by zero}}
181 // expected-warning@-3 {{Division by zero}}
182 }
183
evalZeroParamNonNullReturn(const Shape & S)184 void evalZeroParamNonNullReturn(const Shape &S) {
185 const auto *C = S.castAs<Circle>();
186 // expected-note@-1 {{'C' initialized here}}
187
188 (void)(1 / !C);
189 // expected-note@-1 {{'C' is non-null}}
190 // expected-note@-2 {{Division by zero}}
191 // expected-warning@-3 {{Division by zero}}
192 }
193
evalZeroParamNullReturn(const Shape * S)194 void evalZeroParamNullReturn(const Shape *S) {
195 const auto &C = S->getAs<Circle>();
196 // expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
197 // expected-note@-2 {{Storing null pointer value}}
198 // expected-note@-3 {{'C' initialized here}}
199
200 if (!dyn_cast_or_null<Triangle>(S)) {
201 // expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
202 // expected-note@-2 {{Taking false branch}}
203 return;
204 }
205
206 if (!dyn_cast_or_null<Triangle>(S)) {
207 // expected-note@-1 {{'S' is a 'Triangle'}}
208 // expected-note@-2 {{Taking false branch}}
209 return;
210 }
211
212 (void)(1 / (bool)C);
213 // expected-note@-1 {{Division by zero}}
214 // expected-warning@-2 {{Division by zero}}
215 }
216