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