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