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