1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the APValue class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_APVALUE_H 14 #define LLVM_CLANG_AST_APVALUE_H 15 16 #include "clang/Basic/FixedPoint.h" 17 #include "clang/Basic/LLVM.h" 18 #include "llvm/ADT/APFloat.h" 19 #include "llvm/ADT/APSInt.h" 20 #include "llvm/ADT/PointerIntPair.h" 21 #include "llvm/ADT/PointerUnion.h" 22 23 namespace clang { 24 class AddrLabelExpr; 25 class ASTContext; 26 class CharUnits; 27 class CXXRecordDecl; 28 class Decl; 29 class DiagnosticBuilder; 30 class Expr; 31 class FieldDecl; 32 struct PrintingPolicy; 33 class Type; 34 class ValueDecl; 35 36 /// Symbolic representation of typeid(T) for some type T. 37 class TypeInfoLValue { 38 const Type *T; 39 40 public: 41 TypeInfoLValue() : T() {} 42 explicit TypeInfoLValue(const Type *T); 43 44 const Type *getType() const { return T; } 45 explicit operator bool() const { return T; } 46 47 void *getOpaqueValue() { return const_cast<Type*>(T); } 48 static TypeInfoLValue getFromOpaqueValue(void *Value) { 49 TypeInfoLValue V; 50 V.T = reinterpret_cast<const Type*>(Value); 51 return V; 52 } 53 54 void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; 55 }; 56 } 57 58 namespace llvm { 59 template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> { 60 static void *getAsVoidPointer(clang::TypeInfoLValue V) { 61 return V.getOpaqueValue(); 62 } 63 static clang::TypeInfoLValue getFromVoidPointer(void *P) { 64 return clang::TypeInfoLValue::getFromOpaqueValue(P); 65 } 66 // Validated by static_assert in APValue.cpp; hardcoded to avoid needing 67 // to include Type.h. 68 static constexpr int NumLowBitsAvailable = 3; 69 }; 70 } 71 72 namespace clang { 73 /// APValue - This class implements a discriminated union of [uninitialized] 74 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], 75 /// [Vector: N * APValue], [Array: N * APValue] 76 class APValue { 77 typedef llvm::APSInt APSInt; 78 typedef llvm::APFloat APFloat; 79 public: 80 enum ValueKind { 81 /// There is no such object (it's outside its lifetime). 82 None, 83 /// This object has an indeterminate value (C++ [basic.indet]). 84 Indeterminate, 85 Int, 86 Float, 87 FixedPoint, 88 ComplexInt, 89 ComplexFloat, 90 LValue, 91 Vector, 92 Array, 93 Struct, 94 Union, 95 MemberPointer, 96 AddrLabelDiff 97 }; 98 99 class LValueBase { 100 typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue> 101 PtrTy; 102 103 public: 104 LValueBase() : Local{} {} 105 LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0); 106 LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0); 107 static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); 108 109 template <class T> 110 bool is() const { return Ptr.is<T>(); } 111 112 template <class T> 113 T get() const { return Ptr.get<T>(); } 114 115 template <class T> 116 T dyn_cast() const { return Ptr.dyn_cast<T>(); } 117 118 void *getOpaqueValue() const; 119 120 bool isNull() const; 121 122 explicit operator bool() const; 123 124 unsigned getCallIndex() const; 125 unsigned getVersion() const; 126 QualType getTypeInfoType() const; 127 128 friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); 129 friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { 130 return !(LHS == RHS); 131 } 132 friend llvm::hash_code hash_value(const LValueBase &Base); 133 134 private: 135 PtrTy Ptr; 136 struct LocalState { 137 unsigned CallIndex, Version; 138 }; 139 union { 140 LocalState Local; 141 /// The type std::type_info, if this is a TypeInfoLValue. 142 void *TypeInfoType; 143 }; 144 }; 145 146 /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we 147 /// mean a virtual or non-virtual base class subobject. 148 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; 149 150 /// A non-discriminated union of a base, field, or array index. 151 class LValuePathEntry { 152 static_assert(sizeof(uintptr_t) <= sizeof(uint64_t), 153 "pointer doesn't fit in 64 bits?"); 154 uint64_t Value; 155 156 public: 157 LValuePathEntry() : Value() {} 158 LValuePathEntry(BaseOrMemberType BaseOrMember) 159 : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {} 160 static LValuePathEntry ArrayIndex(uint64_t Index) { 161 LValuePathEntry Result; 162 Result.Value = Index; 163 return Result; 164 } 165 166 BaseOrMemberType getAsBaseOrMember() const { 167 return BaseOrMemberType::getFromOpaqueValue( 168 reinterpret_cast<void *>(Value)); 169 } 170 uint64_t getAsArrayIndex() const { return Value; } 171 172 friend bool operator==(LValuePathEntry A, LValuePathEntry B) { 173 return A.Value == B.Value; 174 } 175 friend bool operator!=(LValuePathEntry A, LValuePathEntry B) { 176 return A.Value != B.Value; 177 } 178 friend llvm::hash_code hash_value(LValuePathEntry A) { 179 return llvm::hash_value(A.Value); 180 } 181 }; 182 struct NoLValuePath {}; 183 struct UninitArray {}; 184 struct UninitStruct {}; 185 186 friend class ASTReader; 187 friend class ASTWriter; 188 189 private: 190 ValueKind Kind; 191 192 struct ComplexAPSInt { 193 APSInt Real, Imag; 194 ComplexAPSInt() : Real(1), Imag(1) {} 195 }; 196 struct ComplexAPFloat { 197 APFloat Real, Imag; 198 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 199 }; 200 struct LV; 201 struct Vec { 202 APValue *Elts; 203 unsigned NumElts; 204 Vec() : Elts(nullptr), NumElts(0) {} 205 ~Vec() { delete[] Elts; } 206 }; 207 struct Arr { 208 APValue *Elts; 209 unsigned NumElts, ArrSize; 210 Arr(unsigned NumElts, unsigned ArrSize); 211 ~Arr(); 212 }; 213 struct StructData { 214 APValue *Elts; 215 unsigned NumBases; 216 unsigned NumFields; 217 StructData(unsigned NumBases, unsigned NumFields); 218 ~StructData(); 219 }; 220 struct UnionData { 221 const FieldDecl *Field; 222 APValue *Value; 223 UnionData(); 224 ~UnionData(); 225 }; 226 struct AddrLabelDiffData { 227 const AddrLabelExpr* LHSExpr; 228 const AddrLabelExpr* RHSExpr; 229 }; 230 struct MemberPointerData; 231 232 // We ensure elsewhere that Data is big enough for LV and MemberPointerData. 233 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, 234 ComplexAPFloat, Vec, Arr, StructData, 235 UnionData, AddrLabelDiffData> DataType; 236 static const size_t DataSize = sizeof(DataType); 237 238 DataType Data; 239 240 public: 241 APValue() : Kind(None) {} 242 explicit APValue(APSInt I) : Kind(None) { 243 MakeInt(); setInt(std::move(I)); 244 } 245 explicit APValue(APFloat F) : Kind(None) { 246 MakeFloat(); setFloat(std::move(F)); 247 } 248 explicit APValue(APFixedPoint FX) : Kind(None) { 249 MakeFixedPoint(std::move(FX)); 250 } 251 explicit APValue(const APValue *E, unsigned N) : Kind(None) { 252 MakeVector(); setVector(E, N); 253 } 254 APValue(APSInt R, APSInt I) : Kind(None) { 255 MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); 256 } 257 APValue(APFloat R, APFloat I) : Kind(None) { 258 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); 259 } 260 APValue(const APValue &RHS); 261 APValue(APValue &&RHS) : Kind(None) { swap(RHS); } 262 APValue(LValueBase B, const CharUnits &O, NoLValuePath N, 263 bool IsNullPtr = false) 264 : Kind(None) { 265 MakeLValue(); setLValue(B, O, N, IsNullPtr); 266 } 267 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, 268 bool OnePastTheEnd, bool IsNullPtr = false) 269 : Kind(None) { 270 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); 271 } 272 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { 273 MakeArray(InitElts, Size); 274 } 275 APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { 276 MakeStruct(B, M); 277 } 278 explicit APValue(const FieldDecl *D, const APValue &V = APValue()) 279 : Kind(None) { 280 MakeUnion(); setUnion(D, V); 281 } 282 APValue(const ValueDecl *Member, bool IsDerivedMember, 283 ArrayRef<const CXXRecordDecl*> Path) : Kind(None) { 284 MakeMemberPointer(Member, IsDerivedMember, Path); 285 } 286 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) 287 : Kind(None) { 288 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); 289 } 290 static APValue IndeterminateValue() { 291 APValue Result; 292 Result.Kind = Indeterminate; 293 return Result; 294 } 295 296 ~APValue() { 297 if (Kind != None && Kind != Indeterminate) 298 DestroyDataAndMakeUninit(); 299 } 300 301 /// Returns whether the object performed allocations. 302 /// 303 /// If APValues are constructed via placement new, \c needsCleanup() 304 /// indicates whether the destructor must be called in order to correctly 305 /// free all allocated memory. 306 bool needsCleanup() const; 307 308 /// Swaps the contents of this and the given APValue. 309 void swap(APValue &RHS); 310 311 ValueKind getKind() const { return Kind; } 312 313 bool isAbsent() const { return Kind == None; } 314 bool isIndeterminate() const { return Kind == Indeterminate; } 315 bool hasValue() const { return Kind != None && Kind != Indeterminate; } 316 317 bool isInt() const { return Kind == Int; } 318 bool isFloat() const { return Kind == Float; } 319 bool isFixedPoint() const { return Kind == FixedPoint; } 320 bool isComplexInt() const { return Kind == ComplexInt; } 321 bool isComplexFloat() const { return Kind == ComplexFloat; } 322 bool isLValue() const { return Kind == LValue; } 323 bool isVector() const { return Kind == Vector; } 324 bool isArray() const { return Kind == Array; } 325 bool isStruct() const { return Kind == Struct; } 326 bool isUnion() const { return Kind == Union; } 327 bool isMemberPointer() const { return Kind == MemberPointer; } 328 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } 329 330 void dump() const; 331 void dump(raw_ostream &OS) const; 332 333 void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; 334 std::string getAsString(const ASTContext &Ctx, QualType Ty) const; 335 336 APSInt &getInt() { 337 assert(isInt() && "Invalid accessor"); 338 return *(APSInt*)(char*)Data.buffer; 339 } 340 const APSInt &getInt() const { 341 return const_cast<APValue*>(this)->getInt(); 342 } 343 344 /// Try to convert this value to an integral constant. This works if it's an 345 /// integer, null pointer, or offset from a null pointer. Returns true on 346 /// success. 347 bool toIntegralConstant(APSInt &Result, QualType SrcTy, 348 const ASTContext &Ctx) const; 349 350 APFloat &getFloat() { 351 assert(isFloat() && "Invalid accessor"); 352 return *(APFloat*)(char*)Data.buffer; 353 } 354 const APFloat &getFloat() const { 355 return const_cast<APValue*>(this)->getFloat(); 356 } 357 358 APFixedPoint &getFixedPoint() { 359 assert(isFixedPoint() && "Invalid accessor"); 360 return *(APFixedPoint *)(char *)Data.buffer; 361 } 362 const APFixedPoint &getFixedPoint() const { 363 return const_cast<APValue *>(this)->getFixedPoint(); 364 } 365 366 APSInt &getComplexIntReal() { 367 assert(isComplexInt() && "Invalid accessor"); 368 return ((ComplexAPSInt*)(char*)Data.buffer)->Real; 369 } 370 const APSInt &getComplexIntReal() const { 371 return const_cast<APValue*>(this)->getComplexIntReal(); 372 } 373 374 APSInt &getComplexIntImag() { 375 assert(isComplexInt() && "Invalid accessor"); 376 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; 377 } 378 const APSInt &getComplexIntImag() const { 379 return const_cast<APValue*>(this)->getComplexIntImag(); 380 } 381 382 APFloat &getComplexFloatReal() { 383 assert(isComplexFloat() && "Invalid accessor"); 384 return ((ComplexAPFloat*)(char*)Data.buffer)->Real; 385 } 386 const APFloat &getComplexFloatReal() const { 387 return const_cast<APValue*>(this)->getComplexFloatReal(); 388 } 389 390 APFloat &getComplexFloatImag() { 391 assert(isComplexFloat() && "Invalid accessor"); 392 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; 393 } 394 const APFloat &getComplexFloatImag() const { 395 return const_cast<APValue*>(this)->getComplexFloatImag(); 396 } 397 398 const LValueBase getLValueBase() const; 399 CharUnits &getLValueOffset(); 400 const CharUnits &getLValueOffset() const { 401 return const_cast<APValue*>(this)->getLValueOffset(); 402 } 403 bool isLValueOnePastTheEnd() const; 404 bool hasLValuePath() const; 405 ArrayRef<LValuePathEntry> getLValuePath() const; 406 unsigned getLValueCallIndex() const; 407 unsigned getLValueVersion() const; 408 bool isNullPointer() const; 409 410 APValue &getVectorElt(unsigned I) { 411 assert(isVector() && "Invalid accessor"); 412 assert(I < getVectorLength() && "Index out of range"); 413 return ((Vec*)(char*)Data.buffer)->Elts[I]; 414 } 415 const APValue &getVectorElt(unsigned I) const { 416 return const_cast<APValue*>(this)->getVectorElt(I); 417 } 418 unsigned getVectorLength() const { 419 assert(isVector() && "Invalid accessor"); 420 return ((const Vec*)(const void *)Data.buffer)->NumElts; 421 } 422 423 APValue &getArrayInitializedElt(unsigned I) { 424 assert(isArray() && "Invalid accessor"); 425 assert(I < getArrayInitializedElts() && "Index out of range"); 426 return ((Arr*)(char*)Data.buffer)->Elts[I]; 427 } 428 const APValue &getArrayInitializedElt(unsigned I) const { 429 return const_cast<APValue*>(this)->getArrayInitializedElt(I); 430 } 431 bool hasArrayFiller() const { 432 return getArrayInitializedElts() != getArraySize(); 433 } 434 APValue &getArrayFiller() { 435 assert(isArray() && "Invalid accessor"); 436 assert(hasArrayFiller() && "No array filler"); 437 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; 438 } 439 const APValue &getArrayFiller() const { 440 return const_cast<APValue*>(this)->getArrayFiller(); 441 } 442 unsigned getArrayInitializedElts() const { 443 assert(isArray() && "Invalid accessor"); 444 return ((const Arr*)(const void *)Data.buffer)->NumElts; 445 } 446 unsigned getArraySize() const { 447 assert(isArray() && "Invalid accessor"); 448 return ((const Arr*)(const void *)Data.buffer)->ArrSize; 449 } 450 451 unsigned getStructNumBases() const { 452 assert(isStruct() && "Invalid accessor"); 453 return ((const StructData*)(const char*)Data.buffer)->NumBases; 454 } 455 unsigned getStructNumFields() const { 456 assert(isStruct() && "Invalid accessor"); 457 return ((const StructData*)(const char*)Data.buffer)->NumFields; 458 } 459 APValue &getStructBase(unsigned i) { 460 assert(isStruct() && "Invalid accessor"); 461 return ((StructData*)(char*)Data.buffer)->Elts[i]; 462 } 463 APValue &getStructField(unsigned i) { 464 assert(isStruct() && "Invalid accessor"); 465 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; 466 } 467 const APValue &getStructBase(unsigned i) const { 468 return const_cast<APValue*>(this)->getStructBase(i); 469 } 470 const APValue &getStructField(unsigned i) const { 471 return const_cast<APValue*>(this)->getStructField(i); 472 } 473 474 const FieldDecl *getUnionField() const { 475 assert(isUnion() && "Invalid accessor"); 476 return ((const UnionData*)(const char*)Data.buffer)->Field; 477 } 478 APValue &getUnionValue() { 479 assert(isUnion() && "Invalid accessor"); 480 return *((UnionData*)(char*)Data.buffer)->Value; 481 } 482 const APValue &getUnionValue() const { 483 return const_cast<APValue*>(this)->getUnionValue(); 484 } 485 486 const ValueDecl *getMemberPointerDecl() const; 487 bool isMemberPointerToDerivedMember() const; 488 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; 489 490 const AddrLabelExpr* getAddrLabelDiffLHS() const { 491 assert(isAddrLabelDiff() && "Invalid accessor"); 492 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; 493 } 494 const AddrLabelExpr* getAddrLabelDiffRHS() const { 495 assert(isAddrLabelDiff() && "Invalid accessor"); 496 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; 497 } 498 499 void setInt(APSInt I) { 500 assert(isInt() && "Invalid accessor"); 501 *(APSInt *)(char *)Data.buffer = std::move(I); 502 } 503 void setFloat(APFloat F) { 504 assert(isFloat() && "Invalid accessor"); 505 *(APFloat *)(char *)Data.buffer = std::move(F); 506 } 507 void setFixedPoint(APFixedPoint FX) { 508 assert(isFixedPoint() && "Invalid accessor"); 509 *(APFixedPoint *)(char *)Data.buffer = std::move(FX); 510 } 511 void setVector(const APValue *E, unsigned N) { 512 assert(isVector() && "Invalid accessor"); 513 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; 514 ((Vec*)(char*)Data.buffer)->NumElts = N; 515 for (unsigned i = 0; i != N; ++i) 516 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; 517 } 518 void setComplexInt(APSInt R, APSInt I) { 519 assert(R.getBitWidth() == I.getBitWidth() && 520 "Invalid complex int (type mismatch)."); 521 assert(isComplexInt() && "Invalid accessor"); 522 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); 523 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); 524 } 525 void setComplexFloat(APFloat R, APFloat I) { 526 assert(&R.getSemantics() == &I.getSemantics() && 527 "Invalid complex float (type mismatch)."); 528 assert(isComplexFloat() && "Invalid accessor"); 529 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); 530 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); 531 } 532 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, 533 bool IsNullPtr); 534 void setLValue(LValueBase B, const CharUnits &O, 535 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, 536 bool IsNullPtr); 537 void setUnion(const FieldDecl *Field, const APValue &Value) { 538 assert(isUnion() && "Invalid accessor"); 539 ((UnionData*)(char*)Data.buffer)->Field = Field; 540 *((UnionData*)(char*)Data.buffer)->Value = Value; 541 } 542 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, 543 const AddrLabelExpr* RHSExpr) { 544 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; 545 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; 546 } 547 548 /// Assign by swapping from a copy of the RHS. 549 APValue &operator=(APValue RHS) { 550 swap(RHS); 551 return *this; 552 } 553 554 private: 555 void DestroyDataAndMakeUninit(); 556 void MakeInt() { 557 assert(isAbsent() && "Bad state change"); 558 new ((void*)Data.buffer) APSInt(1); 559 Kind = Int; 560 } 561 void MakeFloat() { 562 assert(isAbsent() && "Bad state change"); 563 new ((void*)(char*)Data.buffer) APFloat(0.0); 564 Kind = Float; 565 } 566 void MakeFixedPoint(APFixedPoint &&FX) { 567 assert(isAbsent() && "Bad state change"); 568 new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); 569 Kind = FixedPoint; 570 } 571 void MakeVector() { 572 assert(isAbsent() && "Bad state change"); 573 new ((void*)(char*)Data.buffer) Vec(); 574 Kind = Vector; 575 } 576 void MakeComplexInt() { 577 assert(isAbsent() && "Bad state change"); 578 new ((void*)(char*)Data.buffer) ComplexAPSInt(); 579 Kind = ComplexInt; 580 } 581 void MakeComplexFloat() { 582 assert(isAbsent() && "Bad state change"); 583 new ((void*)(char*)Data.buffer) ComplexAPFloat(); 584 Kind = ComplexFloat; 585 } 586 void MakeLValue(); 587 void MakeArray(unsigned InitElts, unsigned Size); 588 void MakeStruct(unsigned B, unsigned M) { 589 assert(isAbsent() && "Bad state change"); 590 new ((void*)(char*)Data.buffer) StructData(B, M); 591 Kind = Struct; 592 } 593 void MakeUnion() { 594 assert(isAbsent() && "Bad state change"); 595 new ((void*)(char*)Data.buffer) UnionData(); 596 Kind = Union; 597 } 598 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, 599 ArrayRef<const CXXRecordDecl*> Path); 600 void MakeAddrLabelDiff() { 601 assert(isAbsent() && "Bad state change"); 602 new ((void*)(char*)Data.buffer) AddrLabelDiffData(); 603 Kind = AddrLabelDiff; 604 } 605 }; 606 607 } // end namespace clang. 608 609 namespace llvm { 610 template<> struct DenseMapInfo<clang::APValue::LValueBase> { 611 static clang::APValue::LValueBase getEmptyKey(); 612 static clang::APValue::LValueBase getTombstoneKey(); 613 static unsigned getHashValue(const clang::APValue::LValueBase &Base); 614 static bool isEqual(const clang::APValue::LValueBase &LHS, 615 const clang::APValue::LValueBase &RHS); 616 }; 617 } 618 619 #endif 620