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 typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase; 57 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; 58 union LValuePathEntry { 59 /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item 60 /// in the path. An opaque value of type BaseOrMemberType. 61 void *BaseOrMember; 62 /// ArrayIndex - The array index of the next item in the path. 63 uint64_t ArrayIndex; 64 }; 65 struct NoLValuePath {}; 66 struct UninitArray {}; 67 struct UninitStruct {}; 68 private: 69 ValueKind Kind; 70 71 struct ComplexAPSInt { 72 APSInt Real, Imag; ComplexAPSIntComplexAPSInt73 ComplexAPSInt() : Real(1), Imag(1) {} 74 }; 75 struct ComplexAPFloat { 76 APFloat Real, Imag; ComplexAPFloatComplexAPFloat77 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 78 }; 79 struct LV; 80 struct Vec { 81 APValue *Elts; 82 unsigned NumElts; VecVec83 Vec() : Elts(nullptr), NumElts(0) {} ~VecVec84 ~Vec() { delete[] Elts; } 85 }; 86 struct Arr { 87 APValue *Elts; 88 unsigned NumElts, ArrSize; 89 Arr(unsigned NumElts, unsigned ArrSize); 90 ~Arr(); 91 }; 92 struct StructData { 93 APValue *Elts; 94 unsigned NumBases; 95 unsigned NumFields; 96 StructData(unsigned NumBases, unsigned NumFields); 97 ~StructData(); 98 }; 99 struct UnionData { 100 const FieldDecl *Field; 101 APValue *Value; 102 UnionData(); 103 ~UnionData(); 104 }; 105 struct AddrLabelDiffData { 106 const AddrLabelExpr* LHSExpr; 107 const AddrLabelExpr* RHSExpr; 108 }; 109 struct MemberPointerData; 110 111 // We ensure elsewhere that Data is big enough for LV and MemberPointerData. 112 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, 113 ComplexAPFloat, Vec, Arr, StructData, 114 UnionData, AddrLabelDiffData> DataType; 115 static const size_t DataSize = sizeof(DataType); 116 117 DataType Data; 118 119 public: APValue()120 APValue() : Kind(Uninitialized) {} APValue(APSInt I)121 explicit APValue(APSInt I) : Kind(Uninitialized) { 122 MakeInt(); setInt(std::move(I)); 123 } APValue(APFloat F)124 explicit APValue(APFloat F) : Kind(Uninitialized) { 125 MakeFloat(); setFloat(std::move(F)); 126 } APValue(const APValue * E,unsigned N)127 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { 128 MakeVector(); setVector(E, N); 129 } APValue(APSInt R,APSInt I)130 APValue(APSInt R, APSInt I) : Kind(Uninitialized) { 131 MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); 132 } APValue(APFloat R,APFloat I)133 APValue(APFloat R, APFloat I) : Kind(Uninitialized) { 134 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); 135 } 136 APValue(const APValue &RHS); APValue(APValue && RHS)137 APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } APValue(LValueBase B,const CharUnits & O,NoLValuePath N,unsigned CallIndex)138 APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex) 139 : Kind(Uninitialized) { 140 MakeLValue(); setLValue(B, O, N, CallIndex); 141 } APValue(LValueBase B,const CharUnits & O,ArrayRef<LValuePathEntry> Path,bool OnePastTheEnd,unsigned CallIndex)142 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, 143 bool OnePastTheEnd, unsigned CallIndex) 144 : Kind(Uninitialized) { 145 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex); 146 } APValue(UninitArray,unsigned InitElts,unsigned Size)147 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { 148 MakeArray(InitElts, Size); 149 } APValue(UninitStruct,unsigned B,unsigned M)150 APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { 151 MakeStruct(B, M); 152 } 153 explicit APValue(const FieldDecl *D, const APValue &V = APValue()) Kind(Uninitialized)154 : Kind(Uninitialized) { 155 MakeUnion(); setUnion(D, V); 156 } APValue(const ValueDecl * Member,bool IsDerivedMember,ArrayRef<const CXXRecordDecl * > Path)157 APValue(const ValueDecl *Member, bool IsDerivedMember, 158 ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { 159 MakeMemberPointer(Member, IsDerivedMember, Path); 160 } APValue(const AddrLabelExpr * LHSExpr,const AddrLabelExpr * RHSExpr)161 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) 162 : Kind(Uninitialized) { 163 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); 164 } 165 ~APValue()166 ~APValue() { 167 MakeUninit(); 168 } 169 170 /// \brief Returns whether the object performed allocations. 171 /// 172 /// If APValues are constructed via placement new, \c needsCleanup() 173 /// indicates whether the destructor must be called in order to correctly 174 /// free all allocated memory. 175 bool needsCleanup() const; 176 177 /// \brief Swaps the contents of this and the given APValue. 178 void swap(APValue &RHS); 179 getKind()180 ValueKind getKind() const { return Kind; } isUninit()181 bool isUninit() const { return Kind == Uninitialized; } isInt()182 bool isInt() const { return Kind == Int; } isFloat()183 bool isFloat() const { return Kind == Float; } isComplexInt()184 bool isComplexInt() const { return Kind == ComplexInt; } isComplexFloat()185 bool isComplexFloat() const { return Kind == ComplexFloat; } isLValue()186 bool isLValue() const { return Kind == LValue; } isVector()187 bool isVector() const { return Kind == Vector; } isArray()188 bool isArray() const { return Kind == Array; } isStruct()189 bool isStruct() const { return Kind == Struct; } isUnion()190 bool isUnion() const { return Kind == Union; } isMemberPointer()191 bool isMemberPointer() const { return Kind == MemberPointer; } isAddrLabelDiff()192 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } 193 194 void dump() const; 195 void dump(raw_ostream &OS) const; 196 197 void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; 198 std::string getAsString(ASTContext &Ctx, QualType Ty) const; 199 getInt()200 APSInt &getInt() { 201 assert(isInt() && "Invalid accessor"); 202 return *(APSInt*)(char*)Data.buffer; 203 } getInt()204 const APSInt &getInt() const { 205 return const_cast<APValue*>(this)->getInt(); 206 } 207 getFloat()208 APFloat &getFloat() { 209 assert(isFloat() && "Invalid accessor"); 210 return *(APFloat*)(char*)Data.buffer; 211 } getFloat()212 const APFloat &getFloat() const { 213 return const_cast<APValue*>(this)->getFloat(); 214 } 215 getComplexIntReal()216 APSInt &getComplexIntReal() { 217 assert(isComplexInt() && "Invalid accessor"); 218 return ((ComplexAPSInt*)(char*)Data.buffer)->Real; 219 } getComplexIntReal()220 const APSInt &getComplexIntReal() const { 221 return const_cast<APValue*>(this)->getComplexIntReal(); 222 } 223 getComplexIntImag()224 APSInt &getComplexIntImag() { 225 assert(isComplexInt() && "Invalid accessor"); 226 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; 227 } getComplexIntImag()228 const APSInt &getComplexIntImag() const { 229 return const_cast<APValue*>(this)->getComplexIntImag(); 230 } 231 getComplexFloatReal()232 APFloat &getComplexFloatReal() { 233 assert(isComplexFloat() && "Invalid accessor"); 234 return ((ComplexAPFloat*)(char*)Data.buffer)->Real; 235 } getComplexFloatReal()236 const APFloat &getComplexFloatReal() const { 237 return const_cast<APValue*>(this)->getComplexFloatReal(); 238 } 239 getComplexFloatImag()240 APFloat &getComplexFloatImag() { 241 assert(isComplexFloat() && "Invalid accessor"); 242 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; 243 } getComplexFloatImag()244 const APFloat &getComplexFloatImag() const { 245 return const_cast<APValue*>(this)->getComplexFloatImag(); 246 } 247 248 const LValueBase getLValueBase() const; 249 CharUnits &getLValueOffset(); getLValueOffset()250 const CharUnits &getLValueOffset() const { 251 return const_cast<APValue*>(this)->getLValueOffset(); 252 } 253 bool isLValueOnePastTheEnd() const; 254 bool hasLValuePath() const; 255 ArrayRef<LValuePathEntry> getLValuePath() const; 256 unsigned getLValueCallIndex() const; 257 getVectorElt(unsigned I)258 APValue &getVectorElt(unsigned I) { 259 assert(isVector() && "Invalid accessor"); 260 assert(I < getVectorLength() && "Index out of range"); 261 return ((Vec*)(char*)Data.buffer)->Elts[I]; 262 } getVectorElt(unsigned I)263 const APValue &getVectorElt(unsigned I) const { 264 return const_cast<APValue*>(this)->getVectorElt(I); 265 } getVectorLength()266 unsigned getVectorLength() const { 267 assert(isVector() && "Invalid accessor"); 268 return ((const Vec*)(const void *)Data.buffer)->NumElts; 269 } 270 getArrayInitializedElt(unsigned I)271 APValue &getArrayInitializedElt(unsigned I) { 272 assert(isArray() && "Invalid accessor"); 273 assert(I < getArrayInitializedElts() && "Index out of range"); 274 return ((Arr*)(char*)Data.buffer)->Elts[I]; 275 } getArrayInitializedElt(unsigned I)276 const APValue &getArrayInitializedElt(unsigned I) const { 277 return const_cast<APValue*>(this)->getArrayInitializedElt(I); 278 } hasArrayFiller()279 bool hasArrayFiller() const { 280 return getArrayInitializedElts() != getArraySize(); 281 } getArrayFiller()282 APValue &getArrayFiller() { 283 assert(isArray() && "Invalid accessor"); 284 assert(hasArrayFiller() && "No array filler"); 285 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; 286 } getArrayFiller()287 const APValue &getArrayFiller() const { 288 return const_cast<APValue*>(this)->getArrayFiller(); 289 } getArrayInitializedElts()290 unsigned getArrayInitializedElts() const { 291 assert(isArray() && "Invalid accessor"); 292 return ((const Arr*)(const void *)Data.buffer)->NumElts; 293 } getArraySize()294 unsigned getArraySize() const { 295 assert(isArray() && "Invalid accessor"); 296 return ((const Arr*)(const void *)Data.buffer)->ArrSize; 297 } 298 getStructNumBases()299 unsigned getStructNumBases() const { 300 assert(isStruct() && "Invalid accessor"); 301 return ((const StructData*)(const char*)Data.buffer)->NumBases; 302 } getStructNumFields()303 unsigned getStructNumFields() const { 304 assert(isStruct() && "Invalid accessor"); 305 return ((const StructData*)(const char*)Data.buffer)->NumFields; 306 } getStructBase(unsigned i)307 APValue &getStructBase(unsigned i) { 308 assert(isStruct() && "Invalid accessor"); 309 return ((StructData*)(char*)Data.buffer)->Elts[i]; 310 } getStructField(unsigned i)311 APValue &getStructField(unsigned i) { 312 assert(isStruct() && "Invalid accessor"); 313 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; 314 } getStructBase(unsigned i)315 const APValue &getStructBase(unsigned i) const { 316 return const_cast<APValue*>(this)->getStructBase(i); 317 } getStructField(unsigned i)318 const APValue &getStructField(unsigned i) const { 319 return const_cast<APValue*>(this)->getStructField(i); 320 } 321 getUnionField()322 const FieldDecl *getUnionField() const { 323 assert(isUnion() && "Invalid accessor"); 324 return ((const UnionData*)(const char*)Data.buffer)->Field; 325 } getUnionValue()326 APValue &getUnionValue() { 327 assert(isUnion() && "Invalid accessor"); 328 return *((UnionData*)(char*)Data.buffer)->Value; 329 } getUnionValue()330 const APValue &getUnionValue() const { 331 return const_cast<APValue*>(this)->getUnionValue(); 332 } 333 334 const ValueDecl *getMemberPointerDecl() const; 335 bool isMemberPointerToDerivedMember() const; 336 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; 337 getAddrLabelDiffLHS()338 const AddrLabelExpr* getAddrLabelDiffLHS() const { 339 assert(isAddrLabelDiff() && "Invalid accessor"); 340 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; 341 } getAddrLabelDiffRHS()342 const AddrLabelExpr* getAddrLabelDiffRHS() const { 343 assert(isAddrLabelDiff() && "Invalid accessor"); 344 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; 345 } 346 setInt(APSInt I)347 void setInt(APSInt I) { 348 assert(isInt() && "Invalid accessor"); 349 *(APSInt *)(char *)Data.buffer = std::move(I); 350 } setFloat(APFloat F)351 void setFloat(APFloat F) { 352 assert(isFloat() && "Invalid accessor"); 353 *(APFloat *)(char *)Data.buffer = std::move(F); 354 } setVector(const APValue * E,unsigned N)355 void setVector(const APValue *E, unsigned N) { 356 assert(isVector() && "Invalid accessor"); 357 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; 358 ((Vec*)(char*)Data.buffer)->NumElts = N; 359 for (unsigned i = 0; i != N; ++i) 360 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; 361 } setComplexInt(APSInt R,APSInt I)362 void setComplexInt(APSInt R, APSInt I) { 363 assert(R.getBitWidth() == I.getBitWidth() && 364 "Invalid complex int (type mismatch)."); 365 assert(isComplexInt() && "Invalid accessor"); 366 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); 367 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); 368 } setComplexFloat(APFloat R,APFloat I)369 void setComplexFloat(APFloat R, APFloat I) { 370 assert(&R.getSemantics() == &I.getSemantics() && 371 "Invalid complex float (type mismatch)."); 372 assert(isComplexFloat() && "Invalid accessor"); 373 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); 374 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); 375 } 376 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, 377 unsigned CallIndex); 378 void setLValue(LValueBase B, const CharUnits &O, 379 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, 380 unsigned CallIndex); setUnion(const FieldDecl * Field,const APValue & Value)381 void setUnion(const FieldDecl *Field, const APValue &Value) { 382 assert(isUnion() && "Invalid accessor"); 383 ((UnionData*)(char*)Data.buffer)->Field = Field; 384 *((UnionData*)(char*)Data.buffer)->Value = Value; 385 } setAddrLabelDiff(const AddrLabelExpr * LHSExpr,const AddrLabelExpr * RHSExpr)386 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, 387 const AddrLabelExpr* RHSExpr) { 388 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; 389 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; 390 } 391 392 /// Assign by swapping from a copy of the RHS. 393 APValue &operator=(APValue RHS) { 394 swap(RHS); 395 return *this; 396 } 397 398 private: 399 void DestroyDataAndMakeUninit(); MakeUninit()400 void MakeUninit() { 401 if (Kind != Uninitialized) 402 DestroyDataAndMakeUninit(); 403 } MakeInt()404 void MakeInt() { 405 assert(isUninit() && "Bad state change"); 406 new ((void*)Data.buffer) APSInt(1); 407 Kind = Int; 408 } MakeFloat()409 void MakeFloat() { 410 assert(isUninit() && "Bad state change"); 411 new ((void*)(char*)Data.buffer) APFloat(0.0); 412 Kind = Float; 413 } MakeVector()414 void MakeVector() { 415 assert(isUninit() && "Bad state change"); 416 new ((void*)(char*)Data.buffer) Vec(); 417 Kind = Vector; 418 } MakeComplexInt()419 void MakeComplexInt() { 420 assert(isUninit() && "Bad state change"); 421 new ((void*)(char*)Data.buffer) ComplexAPSInt(); 422 Kind = ComplexInt; 423 } MakeComplexFloat()424 void MakeComplexFloat() { 425 assert(isUninit() && "Bad state change"); 426 new ((void*)(char*)Data.buffer) ComplexAPFloat(); 427 Kind = ComplexFloat; 428 } 429 void MakeLValue(); 430 void MakeArray(unsigned InitElts, unsigned Size); MakeStruct(unsigned B,unsigned M)431 void MakeStruct(unsigned B, unsigned M) { 432 assert(isUninit() && "Bad state change"); 433 new ((void*)(char*)Data.buffer) StructData(B, M); 434 Kind = Struct; 435 } MakeUnion()436 void MakeUnion() { 437 assert(isUninit() && "Bad state change"); 438 new ((void*)(char*)Data.buffer) UnionData(); 439 Kind = Union; 440 } 441 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, 442 ArrayRef<const CXXRecordDecl*> Path); MakeAddrLabelDiff()443 void MakeAddrLabelDiff() { 444 assert(isUninit() && "Bad state change"); 445 new ((void*)(char*)Data.buffer) AddrLabelDiffData(); 446 Kind = AddrLabelDiff; 447 } 448 }; 449 450 } // end namespace clang. 451 452 #endif 453