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 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 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 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 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 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 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 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 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