|
21 | 21 | using namespace clang;
|
22 | 22 | using namespace clang::interp;
|
23 | 23 |
|
24 |
| -Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} |
| 24 | +Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) { |
| 25 | + this->IntWidth = Ctx.getTargetInfo().getIntWidth(); |
| 26 | + this->LongWidth = Ctx.getTargetInfo().getLongWidth(); |
| 27 | + assert(Ctx.getTargetInfo().getCharWidth() == 8 && |
| 28 | + "We're assuming 8 bit chars"); |
| 29 | +} |
25 | 30 |
|
26 | 31 | Context::~Context() {}
|
27 | 32 |
|
@@ -216,65 +221,100 @@ bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
|
216 | 221 |
|
217 | 222 | const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
|
218 | 223 |
|
219 |
| -std::optional<PrimType> Context::classify(QualType T) const { |
220 |
| - if (T->isBooleanType()) |
221 |
| - return PT_Bool; |
222 |
| - |
223 |
| - if (T->isSignedIntegerOrEnumerationType()) { |
224 |
| - switch (Ctx.getIntWidth(T)) { |
225 |
| - case 64: |
226 |
| - return PT_Sint64; |
227 |
| - case 32: |
228 |
| - return PT_Sint32; |
229 |
| - case 16: |
230 |
| - return PT_Sint16; |
231 |
| - case 8: |
232 |
| - return PT_Sint8; |
233 |
| - default: |
234 |
| - return PT_IntAPS; |
235 |
| - } |
| 224 | +static PrimType integralTypeToPrimTypeS(unsigned BitWidth) { |
| 225 | + switch (BitWidth) { |
| 226 | + case 64: |
| 227 | + return PT_Sint64; |
| 228 | + case 32: |
| 229 | + return PT_Sint32; |
| 230 | + case 16: |
| 231 | + return PT_Sint16; |
| 232 | + case 8: |
| 233 | + return PT_Sint8; |
| 234 | + default: |
| 235 | + return PT_IntAPS; |
236 | 236 | }
|
| 237 | + llvm_unreachable("Unhandled BitWidth"); |
| 238 | +} |
| 239 | + |
| 240 | +static PrimType integralTypeToPrimTypeU(unsigned BitWidth) { |
| 241 | + switch (BitWidth) { |
| 242 | + case 64: |
| 243 | + return PT_Uint64; |
| 244 | + case 32: |
| 245 | + return PT_Uint32; |
| 246 | + case 16: |
| 247 | + return PT_Uint16; |
| 248 | + case 8: |
| 249 | + return PT_Uint8; |
| 250 | + default: |
| 251 | + return PT_IntAP; |
| 252 | + } |
| 253 | + llvm_unreachable("Unhandled BitWidth"); |
| 254 | +} |
| 255 | + |
| 256 | +std::optional<PrimType> Context::classify(QualType T) const { |
237 | 257 |
|
238 |
| - if (T->isUnsignedIntegerOrEnumerationType()) { |
239 |
| - switch (Ctx.getIntWidth(T)) { |
240 |
| - case 64: |
241 |
| - return PT_Uint64; |
242 |
| - case 32: |
243 |
| - return PT_Uint32; |
244 |
| - case 16: |
245 |
| - return PT_Uint16; |
246 |
| - case 8: |
247 |
| - return PT_Uint8; |
248 |
| - case 1: |
249 |
| - // Might happen for enum types. |
| 258 | + if (const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) { |
| 259 | + auto Kind = BT->getKind(); |
| 260 | + if (Kind == BuiltinType::Bool) |
250 | 261 | return PT_Bool;
|
251 |
| - default: |
252 |
| - return PT_IntAP; |
253 |
| - } |
| 262 | + if (Kind == BuiltinType::NullPtr) |
| 263 | + return PT_Ptr; |
| 264 | + if (Kind == BuiltinType::BoundMember) |
| 265 | + return PT_MemberPtr; |
| 266 | + |
| 267 | + // Just trying to avoid the ASTContext::getIntWidth call below. |
| 268 | + if (Kind == BuiltinType::Int) |
| 269 | + return integralTypeToPrimTypeS(this->IntWidth); |
| 270 | + if (Kind == BuiltinType::UInt) |
| 271 | + return integralTypeToPrimTypeU(this->IntWidth); |
| 272 | + if (Kind == BuiltinType::Long) |
| 273 | + return integralTypeToPrimTypeS(this->LongWidth); |
| 274 | + if (Kind == BuiltinType::ULong) |
| 275 | + return integralTypeToPrimTypeU(this->LongWidth); |
| 276 | + if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S) |
| 277 | + return integralTypeToPrimTypeS(8); |
| 278 | + if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U || |
| 279 | + Kind == BuiltinType::Char8) |
| 280 | + return integralTypeToPrimTypeU(8); |
| 281 | + |
| 282 | + if (BT->isSignedInteger()) |
| 283 | + return integralTypeToPrimTypeS(Ctx.getIntWidth(T)); |
| 284 | + if (BT->isUnsignedInteger()) |
| 285 | + return integralTypeToPrimTypeU(Ctx.getIntWidth(T)); |
| 286 | + |
| 287 | + if (BT->isFloatingPoint()) |
| 288 | + return PT_Float; |
254 | 289 | }
|
255 | 290 |
|
256 |
| - if (T->isNullPtrType()) |
| 291 | + if (T->isPointerOrReferenceType()) |
257 | 292 | return PT_Ptr;
|
258 | 293 |
|
259 |
| - if (T->isRealFloatingType()) |
260 |
| - return PT_Float; |
| 294 | + if (T->isMemberPointerType()) |
| 295 | + return PT_MemberPtr; |
261 | 296 |
|
262 |
| - if (T->isFunctionPointerType() || T->isFunctionReferenceType() || |
263 |
| - T->isFunctionType() || T->isBlockPointerType()) |
264 |
| - return PT_Ptr; |
| 297 | + if (const auto *BT = T->getAs<BitIntType>()) { |
| 298 | + if (BT->isSigned()) |
| 299 | + return integralTypeToPrimTypeS(BT->getNumBits()); |
| 300 | + return integralTypeToPrimTypeU(BT->getNumBits()); |
| 301 | + } |
265 | 302 |
|
266 |
| - if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) |
267 |
| - return PT_Ptr; |
| 303 | + if (const auto *ET = T->getAs<EnumType>()) { |
| 304 | + const auto *D = ET->getDecl(); |
| 305 | + if (!D->isComplete()) |
| 306 | + return std::nullopt; |
| 307 | + return classify(D->getIntegerType()); |
| 308 | + } |
268 | 309 |
|
269 | 310 | if (const auto *AT = T->getAs<AtomicType>())
|
270 | 311 | return classify(AT->getValueType());
|
271 | 312 |
|
272 | 313 | if (const auto *DT = dyn_cast<DecltypeType>(T))
|
273 | 314 | return classify(DT->getUnderlyingType());
|
274 | 315 |
|
275 |
| - if (T->isSpecificBuiltinType(BuiltinType::BoundMember) || |
276 |
| - T->isMemberPointerType()) |
277 |
| - return PT_MemberPtr; |
| 316 | + if (T->isObjCObjectPointerType() || T->isBlockPointerType()) |
| 317 | + return PT_Ptr; |
278 | 318 |
|
279 | 319 | if (T->isFixedPointType())
|
280 | 320 | return PT_FixedPoint;
|
|
0 commit comments