1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the APValue class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_APVALUE_H 15 #define LLVM_CLANG_AST_APVALUE_H 16 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 DiagnosticBuilder; 28 class Expr; 29 class FieldDecl; 30 class Decl; 31 class ValueDecl; 32 class CXXRecordDecl; 33 class QualType; 34 35 /// APValue - This class implements a discriminated union of [uninitialized] 36 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], 37 /// [Vector: N * APValue], [Array: N * APValue] 38 class APValue { 39 typedef llvm::APSInt APSInt; 40 typedef llvm::APFloat APFloat; 41 public: 42 enum ValueKind { 43 Uninitialized, 44 Int, 45 Float, 46 ComplexInt, 47 ComplexFloat, 48 LValue, 49 Vector, 50 Array, 51 Struct, 52 Union, 53 MemberPointer, 54 AddrLabelDiff 55 }; 56 57 class LValueBase { 58 public: 59 typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy; 60 LValueBase()61 LValueBase() : CallIndex(0), Version(0) {} 62 63 template <class T> 64 LValueBase(T P, unsigned I = 0, unsigned V = 0) Ptr(P)65 : Ptr(P), CallIndex(I), Version(V) {} 66 67 template <class T> is()68 bool is() const { return Ptr.is<T>(); } 69 70 template <class T> get()71 T get() const { return Ptr.get<T>(); } 72 73 template <class T> dyn_cast()74 T dyn_cast() const { return Ptr.dyn_cast<T>(); } 75 76 void *getOpaqueValue() const; 77 78 bool isNull() const; 79 80 explicit operator bool () const; 81 getPointer()82 PtrTy getPointer() const { 83 return Ptr; 84 } 85 getCallIndex()86 unsigned getCallIndex() const { 87 return CallIndex; 88 } 89 setCallIndex(unsigned Index)90 void setCallIndex(unsigned Index) { 91 CallIndex = Index; 92 } 93 getVersion()94 unsigned getVersion() const { 95 return Version; 96 } 97 98 bool operator==(const LValueBase &Other) const { 99 return Ptr == Other.Ptr && CallIndex == Other.CallIndex && 100 Version == Other.Version; 101 } 102 103 private: 104 PtrTy Ptr; 105 unsigned CallIndex, Version; 106 }; 107 108 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; 109 union LValuePathEntry { 110 /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item 111 /// in the path. An opaque value of type BaseOrMemberType. 112 void *BaseOrMember; 113 /// ArrayIndex - The array index of the next item in the path. 114 uint64_t ArrayIndex; 115 }; 116 struct NoLValuePath {}; 117 struct UninitArray {}; 118 struct UninitStruct {}; 119 private: 120 ValueKind Kind; 121 122 struct ComplexAPSInt { 123 APSInt Real, Imag; ComplexAPSIntComplexAPSInt124 ComplexAPSInt() : Real(1), Imag(1) {} 125 }; 126 struct ComplexAPFloat { 127 APFloat Real, Imag; ComplexAPFloatComplexAPFloat128 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 129 }; 130 struct LV; 131 struct Vec { 132 APValue *Elts; 133 unsigned NumElts; VecVec134 Vec() : Elts(nullptr), NumElts(0) {} ~VecVec135 ~Vec() { delete[] Elts; } 136 }; 137 struct Arr { 138 APValue *Elts; 139 unsigned NumElts, ArrSize; 140 Arr(unsigned NumElts, unsigned ArrSize); 141 ~Arr(); 142 }; 143 struct StructData { 144 APValue *Elts; 145 unsigned NumBases; 146 unsigned NumFields; 147 StructData(unsigned NumBases, unsigned NumFields); 148 ~StructData(); 149 }; 150 struct UnionData { 151 const FieldDecl *Field; 152 APValue *Value; 153 UnionData(); 154 ~UnionData(); 155 }; 156 struct AddrLabelDiffData { 157 const AddrLabelExpr* LHSExpr; 158 const AddrLabelExpr* RHSExpr; 159 }; 160 struct MemberPointerData; 161 162 // We ensure elsewhere that Data is big enough for LV and MemberPointerData. 163 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, 164 ComplexAPFloat, Vec, Arr, StructData, 165 UnionData, AddrLabelDiffData> DataType; 166 static const size_t DataSize = sizeof(DataType); 167 168 DataType Data; 169 170 public: APValue()171 APValue() : Kind(Uninitialized) {} APValue(APSInt I)172 explicit APValue(APSInt I) : Kind(Uninitialized) { 173 MakeInt(); setInt(std::move(I)); 174 } APValue(APFloat F)175 explicit APValue(APFloat F) : Kind(Uninitialized) { 176 MakeFloat(); setFloat(std::move(F)); 177 } APValue(const APValue * E,unsigned N)178 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { 179 MakeVector(); setVector(E, N); 180 } APValue(APSInt R,APSInt I)181 APValue(APSInt R, APSInt I) : Kind(Uninitialized) { 182 MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); 183 } APValue(APFloat R,APFloat I)184 APValue(APFloat R, APFloat I) : Kind(Uninitialized) { 185 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); 186 } 187 APValue(const APValue &RHS); APValue(APValue && RHS)188 APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } 189 APValue(LValueBase B, const CharUnits &O, NoLValuePath N, 190 bool IsNullPtr = false) Kind(Uninitialized)191 : Kind(Uninitialized) { 192 MakeLValue(); setLValue(B, O, N, IsNullPtr); 193 } 194 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, 195 bool OnePastTheEnd, bool IsNullPtr = false) Kind(Uninitialized)196 : Kind(Uninitialized) { 197 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); 198 } APValue(UninitArray,unsigned InitElts,unsigned Size)199 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { 200 MakeArray(InitElts, Size); 201 } APValue(UninitStruct,unsigned B,unsigned M)202 APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { 203 MakeStruct(B, M); 204 } 205 explicit APValue(const FieldDecl *D, const APValue &V = APValue()) Kind(Uninitialized)206 : Kind(Uninitialized) { 207 MakeUnion(); setUnion(D, V); 208 } APValue(const ValueDecl * Member,bool IsDerivedMember,ArrayRef<const CXXRecordDecl * > Path)209 APValue(const ValueDecl *Member, bool IsDerivedMember, 210 ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { 211 MakeMemberPointer(Member, IsDerivedMember, Path); 212 } APValue(const AddrLabelExpr * LHSExpr,const AddrLabelExpr * RHSExpr)213 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) 214 : Kind(Uninitialized) { 215 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); 216 } 217 ~APValue()218 ~APValue() { 219 MakeUninit(); 220 } 221 222 /// Returns whether the object performed allocations. 223 /// 224 /// If APValues are constructed via placement new, \c needsCleanup() 225 /// indicates whether the destructor must be called in order to correctly 226 /// free all allocated memory. 227 bool needsCleanup() const; 228 229 /// Swaps the contents of this and the given APValue. 230 void swap(APValue &RHS); 231 getKind()232 ValueKind getKind() const { return Kind; } isUninit()233 bool isUninit() const { return Kind == Uninitialized; } isInt()234 bool isInt() const { return Kind == Int; } isFloat()235 bool isFloat() const { return Kind == Float; } isComplexInt()236 bool isComplexInt() const { return Kind == ComplexInt; } isComplexFloat()237 bool isComplexFloat() const { return Kind == ComplexFloat; } isLValue()238 bool isLValue() const { return Kind == LValue; } isVector()239 bool isVector() const { return Kind == Vector; } isArray()240 bool isArray() const { return Kind == Array; } isStruct()241 bool isStruct() const { return Kind == Struct; } isUnion()242 bool isUnion() const { return Kind == Union; } isMemberPointer()243 bool isMemberPointer() const { return Kind == MemberPointer; } isAddrLabelDiff()244 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } 245 246 void dump() const; 247 void dump(raw_ostream &OS) const; 248 249 void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; 250 std::string getAsString(ASTContext &Ctx, QualType Ty) const; 251 getInt()252 APSInt &getInt() { 253 assert(isInt() && "Invalid accessor"); 254 return *(APSInt*)(char*)Data.buffer; 255 } getInt()256 const APSInt &getInt() const { 257 return const_cast<APValue*>(this)->getInt(); 258 } 259 260 /// Try to convert this value to an integral constant. This works if it's an 261 /// integer, null pointer, or offset from a null pointer. Returns true on 262 /// success. 263 bool toIntegralConstant(APSInt &Result, QualType SrcTy, 264 const ASTContext &Ctx) const; 265 getFloat()266 APFloat &getFloat() { 267 assert(isFloat() && "Invalid accessor"); 268 return *(APFloat*)(char*)Data.buffer; 269 } getFloat()270 const APFloat &getFloat() const { 271 return const_cast<APValue*>(this)->getFloat(); 272 } 273 getComplexIntReal()274 APSInt &getComplexIntReal() { 275 assert(isComplexInt() && "Invalid accessor"); 276 return ((ComplexAPSInt*)(char*)Data.buffer)->Real; 277 } getComplexIntReal()278 const APSInt &getComplexIntReal() const { 279 return const_cast<APValue*>(this)->getComplexIntReal(); 280 } 281 getComplexIntImag()282 APSInt &getComplexIntImag() { 283 assert(isComplexInt() && "Invalid accessor"); 284 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; 285 } getComplexIntImag()286 const APSInt &getComplexIntImag() const { 287 return const_cast<APValue*>(this)->getComplexIntImag(); 288 } 289 getComplexFloatReal()290 APFloat &getComplexFloatReal() { 291 assert(isComplexFloat() && "Invalid accessor"); 292 return ((ComplexAPFloat*)(char*)Data.buffer)->Real; 293 } getComplexFloatReal()294 const APFloat &getComplexFloatReal() const { 295 return const_cast<APValue*>(this)->getComplexFloatReal(); 296 } 297 getComplexFloatImag()298 APFloat &getComplexFloatImag() { 299 assert(isComplexFloat() && "Invalid accessor"); 300 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; 301 } getComplexFloatImag()302 const APFloat &getComplexFloatImag() const { 303 return const_cast<APValue*>(this)->getComplexFloatImag(); 304 } 305 306 const LValueBase getLValueBase() const; 307 CharUnits &getLValueOffset(); getLValueOffset()308 const CharUnits &getLValueOffset() const { 309 return const_cast<APValue*>(this)->getLValueOffset(); 310 } 311 bool isLValueOnePastTheEnd() const; 312 bool hasLValuePath() const; 313 ArrayRef<LValuePathEntry> getLValuePath() const; 314 unsigned getLValueCallIndex() const; 315 unsigned getLValueVersion() const; 316 bool isNullPointer() const; 317 getVectorElt(unsigned I)318 APValue &getVectorElt(unsigned I) { 319 assert(isVector() && "Invalid accessor"); 320 assert(I < getVectorLength() && "Index out of range"); 321 return ((Vec*)(char*)Data.buffer)->Elts[I]; 322 } getVectorElt(unsigned I)323 const APValue &getVectorElt(unsigned I) const { 324 return const_cast<APValue*>(this)->getVectorElt(I); 325 } getVectorLength()326 unsigned getVectorLength() const { 327 assert(isVector() && "Invalid accessor"); 328 return ((const Vec*)(const void *)Data.buffer)->NumElts; 329 } 330 getArrayInitializedElt(unsigned I)331 APValue &getArrayInitializedElt(unsigned I) { 332 assert(isArray() && "Invalid accessor"); 333 assert(I < getArrayInitializedElts() && "Index out of range"); 334 return ((Arr*)(char*)Data.buffer)->Elts[I]; 335 } getArrayInitializedElt(unsigned I)336 const APValue &getArrayInitializedElt(unsigned I) const { 337 return const_cast<APValue*>(this)->getArrayInitializedElt(I); 338 } hasArrayFiller()339 bool hasArrayFiller() const { 340 return getArrayInitializedElts() != getArraySize(); 341 } getArrayFiller()342 APValue &getArrayFiller() { 343 assert(isArray() && "Invalid accessor"); 344 assert(hasArrayFiller() && "No array filler"); 345 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; 346 } getArrayFiller()347 const APValue &getArrayFiller() const { 348 return const_cast<APValue*>(this)->getArrayFiller(); 349 } getArrayInitializedElts()350 unsigned getArrayInitializedElts() const { 351 assert(isArray() && "Invalid accessor"); 352 return ((const Arr*)(const void *)Data.buffer)->NumElts; 353 } getArraySize()354 unsigned getArraySize() const { 355 assert(isArray() && "Invalid accessor"); 356 return ((const Arr*)(const void *)Data.buffer)->ArrSize; 357 } 358 getStructNumBases()359 unsigned getStructNumBases() const { 360 assert(isStruct() && "Invalid accessor"); 361 return ((const StructData*)(const char*)Data.buffer)->NumBases; 362 } getStructNumFields()363 unsigned getStructNumFields() const { 364 assert(isStruct() && "Invalid accessor"); 365 return ((const StructData*)(const char*)Data.buffer)->NumFields; 366 } getStructBase(unsigned i)367 APValue &getStructBase(unsigned i) { 368 assert(isStruct() && "Invalid accessor"); 369 return ((StructData*)(char*)Data.buffer)->Elts[i]; 370 } getStructField(unsigned i)371 APValue &getStructField(unsigned i) { 372 assert(isStruct() && "Invalid accessor"); 373 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; 374 } getStructBase(unsigned i)375 const APValue &getStructBase(unsigned i) const { 376 return const_cast<APValue*>(this)->getStructBase(i); 377 } getStructField(unsigned i)378 const APValue &getStructField(unsigned i) const { 379 return const_cast<APValue*>(this)->getStructField(i); 380 } 381 getUnionField()382 const FieldDecl *getUnionField() const { 383 assert(isUnion() && "Invalid accessor"); 384 return ((const UnionData*)(const char*)Data.buffer)->Field; 385 } getUnionValue()386 APValue &getUnionValue() { 387 assert(isUnion() && "Invalid accessor"); 388 return *((UnionData*)(char*)Data.buffer)->Value; 389 } getUnionValue()390 const APValue &getUnionValue() const { 391 return const_cast<APValue*>(this)->getUnionValue(); 392 } 393 394 const ValueDecl *getMemberPointerDecl() const; 395 bool isMemberPointerToDerivedMember() const; 396 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; 397 getAddrLabelDiffLHS()398 const AddrLabelExpr* getAddrLabelDiffLHS() const { 399 assert(isAddrLabelDiff() && "Invalid accessor"); 400 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; 401 } getAddrLabelDiffRHS()402 const AddrLabelExpr* getAddrLabelDiffRHS() const { 403 assert(isAddrLabelDiff() && "Invalid accessor"); 404 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; 405 } 406 setInt(APSInt I)407 void setInt(APSInt I) { 408 assert(isInt() && "Invalid accessor"); 409 *(APSInt *)(char *)Data.buffer = std::move(I); 410 } setFloat(APFloat F)411 void setFloat(APFloat F) { 412 assert(isFloat() && "Invalid accessor"); 413 *(APFloat *)(char *)Data.buffer = std::move(F); 414 } setVector(const APValue * E,unsigned N)415 void setVector(const APValue *E, unsigned N) { 416 assert(isVector() && "Invalid accessor"); 417 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; 418 ((Vec*)(char*)Data.buffer)->NumElts = N; 419 for (unsigned i = 0; i != N; ++i) 420 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; 421 } setComplexInt(APSInt R,APSInt I)422 void setComplexInt(APSInt R, APSInt I) { 423 assert(R.getBitWidth() == I.getBitWidth() && 424 "Invalid complex int (type mismatch)."); 425 assert(isComplexInt() && "Invalid accessor"); 426 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); 427 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); 428 } setComplexFloat(APFloat R,APFloat I)429 void setComplexFloat(APFloat R, APFloat I) { 430 assert(&R.getSemantics() == &I.getSemantics() && 431 "Invalid complex float (type mismatch)."); 432 assert(isComplexFloat() && "Invalid accessor"); 433 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); 434 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); 435 } 436 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, 437 bool IsNullPtr); 438 void setLValue(LValueBase B, const CharUnits &O, 439 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, 440 bool IsNullPtr); setUnion(const FieldDecl * Field,const APValue & Value)441 void setUnion(const FieldDecl *Field, const APValue &Value) { 442 assert(isUnion() && "Invalid accessor"); 443 ((UnionData*)(char*)Data.buffer)->Field = Field; 444 *((UnionData*)(char*)Data.buffer)->Value = Value; 445 } setAddrLabelDiff(const AddrLabelExpr * LHSExpr,const AddrLabelExpr * RHSExpr)446 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, 447 const AddrLabelExpr* RHSExpr) { 448 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; 449 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; 450 } 451 452 /// Assign by swapping from a copy of the RHS. 453 APValue &operator=(APValue RHS) { 454 swap(RHS); 455 return *this; 456 } 457 458 private: 459 void DestroyDataAndMakeUninit(); MakeUninit()460 void MakeUninit() { 461 if (Kind != Uninitialized) 462 DestroyDataAndMakeUninit(); 463 } MakeInt()464 void MakeInt() { 465 assert(isUninit() && "Bad state change"); 466 new ((void*)Data.buffer) APSInt(1); 467 Kind = Int; 468 } MakeFloat()469 void MakeFloat() { 470 assert(isUninit() && "Bad state change"); 471 new ((void*)(char*)Data.buffer) APFloat(0.0); 472 Kind = Float; 473 } MakeVector()474 void MakeVector() { 475 assert(isUninit() && "Bad state change"); 476 new ((void*)(char*)Data.buffer) Vec(); 477 Kind = Vector; 478 } MakeComplexInt()479 void MakeComplexInt() { 480 assert(isUninit() && "Bad state change"); 481 new ((void*)(char*)Data.buffer) ComplexAPSInt(); 482 Kind = ComplexInt; 483 } MakeComplexFloat()484 void MakeComplexFloat() { 485 assert(isUninit() && "Bad state change"); 486 new ((void*)(char*)Data.buffer) ComplexAPFloat(); 487 Kind = ComplexFloat; 488 } 489 void MakeLValue(); 490 void MakeArray(unsigned InitElts, unsigned Size); MakeStruct(unsigned B,unsigned M)491 void MakeStruct(unsigned B, unsigned M) { 492 assert(isUninit() && "Bad state change"); 493 new ((void*)(char*)Data.buffer) StructData(B, M); 494 Kind = Struct; 495 } MakeUnion()496 void MakeUnion() { 497 assert(isUninit() && "Bad state change"); 498 new ((void*)(char*)Data.buffer) UnionData(); 499 Kind = Union; 500 } 501 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, 502 ArrayRef<const CXXRecordDecl*> Path); MakeAddrLabelDiff()503 void MakeAddrLabelDiff() { 504 assert(isUninit() && "Bad state change"); 505 new ((void*)(char*)Data.buffer) AddrLabelDiffData(); 506 Kind = AddrLabelDiff; 507 } 508 }; 509 510 } // end namespace clang. 511 512 namespace llvm { 513 template<> struct DenseMapInfo<clang::APValue::LValueBase> { 514 static clang::APValue::LValueBase getEmptyKey(); 515 static clang::APValue::LValueBase getTombstoneKey(); 516 static unsigned getHashValue(const clang::APValue::LValueBase &Base); 517 static bool isEqual(const clang::APValue::LValueBase &LHS, 518 const clang::APValue::LValueBase &RHS); 519 }; 520 } 521 522 #endif 523