APValue.h revision e24f5fc8c763f1b5536b8d70dd510ca959db3a80
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 CharUnits; 25 class DiagnosticBuilder; 26 class Expr; 27 class FieldDecl; 28 class Decl; 29 class ValueDecl; 30 class CXXRecordDecl; 31 32/// APValue - This class implements a discriminated union of [uninitialized] 33/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], 34/// [Vector: N * APValue], [Array: N * APValue] 35class APValue { 36 typedef llvm::APSInt APSInt; 37 typedef llvm::APFloat APFloat; 38public: 39 enum ValueKind { 40 Uninitialized, 41 Int, 42 Float, 43 ComplexInt, 44 ComplexFloat, 45 LValue, 46 Vector, 47 Array, 48 Struct, 49 Union, 50 MemberPointer 51 }; 52 typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase; 53 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; 54 union LValuePathEntry { 55 /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item 56 /// in the path. An opaque value of type BaseOrMemberType. 57 void *BaseOrMember; 58 /// ArrayIndex - The array index of the next item in the path. 59 uint64_t ArrayIndex; 60 }; 61 struct NoLValuePath {}; 62 struct UninitArray {}; 63 struct UninitStruct {}; 64private: 65 ValueKind Kind; 66 67 struct ComplexAPSInt { 68 APSInt Real, Imag; 69 ComplexAPSInt() : Real(1), Imag(1) {} 70 }; 71 struct ComplexAPFloat { 72 APFloat Real, Imag; 73 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 74 }; 75 struct LV; 76 struct Vec { 77 APValue *Elts; 78 unsigned NumElts; 79 Vec() : Elts(0), NumElts(0) {} 80 ~Vec() { delete[] Elts; } 81 }; 82 struct Arr { 83 APValue *Elts; 84 unsigned NumElts, ArrSize; 85 Arr(unsigned NumElts, unsigned ArrSize); 86 ~Arr(); 87 }; 88 struct StructData { 89 APValue *Elts; 90 unsigned NumBases; 91 unsigned NumFields; 92 StructData(unsigned NumBases, unsigned NumFields); 93 ~StructData(); 94 }; 95 struct UnionData { 96 const FieldDecl *Field; 97 APValue *Value; 98 UnionData(); 99 ~UnionData(); 100 }; 101 struct MemberPointerData; 102 103 enum { 104 MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? 105 sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) 106 }; 107 108 union { 109 void *Aligner; 110 char Data[MaxSize]; 111 }; 112 113public: 114 APValue() : Kind(Uninitialized) {} 115 explicit APValue(const APSInt &I) : Kind(Uninitialized) { 116 MakeInt(); setInt(I); 117 } 118 explicit APValue(const APFloat &F) : Kind(Uninitialized) { 119 MakeFloat(); setFloat(F); 120 } 121 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { 122 MakeVector(); setVector(E, N); 123 } 124 APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { 125 MakeComplexInt(); setComplexInt(R, I); 126 } 127 APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { 128 MakeComplexFloat(); setComplexFloat(R, I); 129 } 130 APValue(const APValue &RHS) : Kind(Uninitialized) { 131 *this = RHS; 132 } 133 APValue(LValueBase B, const CharUnits &O, NoLValuePath N) 134 : Kind(Uninitialized) { 135 MakeLValue(); setLValue(B, O, N); 136 } 137 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, 138 bool OnePastTheEnd) 139 : Kind(Uninitialized) { 140 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd); 141 } 142 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { 143 MakeArray(InitElts, Size); 144 } 145 APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { 146 MakeStruct(B, M); 147 } 148 explicit APValue(const FieldDecl *D, const APValue &V = APValue()) 149 : Kind(Uninitialized) { 150 MakeUnion(); setUnion(D, V); 151 } 152 APValue(const ValueDecl *Member, bool IsDerivedMember, 153 ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { 154 MakeMemberPointer(Member, IsDerivedMember, Path); 155 } 156 157 ~APValue() { 158 MakeUninit(); 159 } 160 161 ValueKind getKind() const { return Kind; } 162 bool isUninit() const { return Kind == Uninitialized; } 163 bool isInt() const { return Kind == Int; } 164 bool isFloat() const { return Kind == Float; } 165 bool isComplexInt() const { return Kind == ComplexInt; } 166 bool isComplexFloat() const { return Kind == ComplexFloat; } 167 bool isLValue() const { return Kind == LValue; } 168 bool isVector() const { return Kind == Vector; } 169 bool isArray() const { return Kind == Array; } 170 bool isStruct() const { return Kind == Struct; } 171 bool isUnion() const { return Kind == Union; } 172 bool isMemberPointer() const { return Kind == MemberPointer; } 173 174 void print(raw_ostream &OS) const; 175 void dump() const; 176 177 APSInt &getInt() { 178 assert(isInt() && "Invalid accessor"); 179 return *(APSInt*)(char*)Data; 180 } 181 const APSInt &getInt() const { 182 return const_cast<APValue*>(this)->getInt(); 183 } 184 185 APFloat &getFloat() { 186 assert(isFloat() && "Invalid accessor"); 187 return *(APFloat*)(char*)Data; 188 } 189 const APFloat &getFloat() const { 190 return const_cast<APValue*>(this)->getFloat(); 191 } 192 193 APSInt &getComplexIntReal() { 194 assert(isComplexInt() && "Invalid accessor"); 195 return ((ComplexAPSInt*)(char*)Data)->Real; 196 } 197 const APSInt &getComplexIntReal() const { 198 return const_cast<APValue*>(this)->getComplexIntReal(); 199 } 200 201 APSInt &getComplexIntImag() { 202 assert(isComplexInt() && "Invalid accessor"); 203 return ((ComplexAPSInt*)(char*)Data)->Imag; 204 } 205 const APSInt &getComplexIntImag() const { 206 return const_cast<APValue*>(this)->getComplexIntImag(); 207 } 208 209 APFloat &getComplexFloatReal() { 210 assert(isComplexFloat() && "Invalid accessor"); 211 return ((ComplexAPFloat*)(char*)Data)->Real; 212 } 213 const APFloat &getComplexFloatReal() const { 214 return const_cast<APValue*>(this)->getComplexFloatReal(); 215 } 216 217 APFloat &getComplexFloatImag() { 218 assert(isComplexFloat() && "Invalid accessor"); 219 return ((ComplexAPFloat*)(char*)Data)->Imag; 220 } 221 const APFloat &getComplexFloatImag() const { 222 return const_cast<APValue*>(this)->getComplexFloatImag(); 223 } 224 225 const LValueBase getLValueBase() const; 226 CharUnits &getLValueOffset(); 227 const CharUnits &getLValueOffset() const { 228 return const_cast<APValue*>(this)->getLValueOffset(); 229 } 230 bool isLValueOnePastTheEnd() const; 231 bool hasLValuePath() const; 232 ArrayRef<LValuePathEntry> getLValuePath() const; 233 234 APValue &getVectorElt(unsigned I) { 235 assert(isVector() && "Invalid accessor"); 236 assert(I < getVectorLength() && "Index out of range"); 237 return ((Vec*)(char*)Data)->Elts[I]; 238 } 239 const APValue &getVectorElt(unsigned I) const { 240 return const_cast<APValue*>(this)->getVectorElt(I); 241 } 242 unsigned getVectorLength() const { 243 assert(isVector() && "Invalid accessor"); 244 return ((const Vec*)(const void *)Data)->NumElts; 245 } 246 247 APValue &getArrayInitializedElt(unsigned I) { 248 assert(isArray() && "Invalid accessor"); 249 assert(I < getArrayInitializedElts() && "Index out of range"); 250 return ((Arr*)(char*)Data)->Elts[I]; 251 } 252 const APValue &getArrayInitializedElt(unsigned I) const { 253 return const_cast<APValue*>(this)->getArrayInitializedElt(I); 254 } 255 bool hasArrayFiller() const { 256 return getArrayInitializedElts() != getArraySize(); 257 } 258 APValue &getArrayFiller() { 259 assert(isArray() && "Invalid accessor"); 260 assert(hasArrayFiller() && "No array filler"); 261 return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()]; 262 } 263 const APValue &getArrayFiller() const { 264 return const_cast<APValue*>(this)->getArrayFiller(); 265 } 266 unsigned getArrayInitializedElts() const { 267 assert(isArray() && "Invalid accessor"); 268 return ((const Arr*)(const void *)Data)->NumElts; 269 } 270 unsigned getArraySize() const { 271 assert(isArray() && "Invalid accessor"); 272 return ((const Arr*)(const void *)Data)->ArrSize; 273 } 274 275 unsigned getStructNumBases() const { 276 assert(isStruct() && "Invalid accessor"); 277 return ((const StructData*)(const char*)Data)->NumBases; 278 } 279 unsigned getStructNumFields() const { 280 assert(isStruct() && "Invalid accessor"); 281 return ((const StructData*)(const char*)Data)->NumFields; 282 } 283 APValue &getStructBase(unsigned i) { 284 assert(isStruct() && "Invalid accessor"); 285 return ((StructData*)(char*)Data)->Elts[i]; 286 } 287 APValue &getStructField(unsigned i) { 288 assert(isStruct() && "Invalid accessor"); 289 return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i]; 290 } 291 const APValue &getStructBase(unsigned i) const { 292 return const_cast<APValue*>(this)->getStructBase(i); 293 } 294 const APValue &getStructField(unsigned i) const { 295 return const_cast<APValue*>(this)->getStructField(i); 296 } 297 298 const FieldDecl *getUnionField() const { 299 assert(isUnion() && "Invalid accessor"); 300 return ((const UnionData*)(const char*)Data)->Field; 301 } 302 APValue &getUnionValue() { 303 assert(isUnion() && "Invalid accessor"); 304 return *((UnionData*)(char*)Data)->Value; 305 } 306 const APValue &getUnionValue() const { 307 return const_cast<APValue*>(this)->getUnionValue(); 308 } 309 310 const ValueDecl *getMemberPointerDecl() const; 311 bool isMemberPointerToDerivedMember() const; 312 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; 313 314 void setInt(const APSInt &I) { 315 assert(isInt() && "Invalid accessor"); 316 *(APSInt*)(char*)Data = I; 317 } 318 void setFloat(const APFloat &F) { 319 assert(isFloat() && "Invalid accessor"); 320 *(APFloat*)(char*)Data = F; 321 } 322 void setVector(const APValue *E, unsigned N) { 323 assert(isVector() && "Invalid accessor"); 324 ((Vec*)(char*)Data)->Elts = new APValue[N]; 325 ((Vec*)(char*)Data)->NumElts = N; 326 for (unsigned i = 0; i != N; ++i) 327 ((Vec*)(char*)Data)->Elts[i] = E[i]; 328 } 329 void setComplexInt(const APSInt &R, const APSInt &I) { 330 assert(R.getBitWidth() == I.getBitWidth() && 331 "Invalid complex int (type mismatch)."); 332 assert(isComplexInt() && "Invalid accessor"); 333 ((ComplexAPSInt*)(char*)Data)->Real = R; 334 ((ComplexAPSInt*)(char*)Data)->Imag = I; 335 } 336 void setComplexFloat(const APFloat &R, const APFloat &I) { 337 assert(&R.getSemantics() == &I.getSemantics() && 338 "Invalid complex float (type mismatch)."); 339 assert(isComplexFloat() && "Invalid accessor"); 340 ((ComplexAPFloat*)(char*)Data)->Real = R; 341 ((ComplexAPFloat*)(char*)Data)->Imag = I; 342 } 343 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath); 344 void setLValue(LValueBase B, const CharUnits &O, 345 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd); 346 void setUnion(const FieldDecl *Field, const APValue &Value) { 347 assert(isUnion() && "Invalid accessor"); 348 ((UnionData*)(char*)Data)->Field = Field; 349 *((UnionData*)(char*)Data)->Value = Value; 350 } 351 352 const APValue &operator=(const APValue &RHS); 353 354private: 355 void MakeUninit(); 356 void MakeInt() { 357 assert(isUninit() && "Bad state change"); 358 new ((void*)Data) APSInt(1); 359 Kind = Int; 360 } 361 void MakeFloat() { 362 assert(isUninit() && "Bad state change"); 363 new ((void*)(char*)Data) APFloat(0.0); 364 Kind = Float; 365 } 366 void MakeVector() { 367 assert(isUninit() && "Bad state change"); 368 new ((void*)(char*)Data) Vec(); 369 Kind = Vector; 370 } 371 void MakeComplexInt() { 372 assert(isUninit() && "Bad state change"); 373 new ((void*)(char*)Data) ComplexAPSInt(); 374 Kind = ComplexInt; 375 } 376 void MakeComplexFloat() { 377 assert(isUninit() && "Bad state change"); 378 new ((void*)(char*)Data) ComplexAPFloat(); 379 Kind = ComplexFloat; 380 } 381 void MakeLValue(); 382 void MakeArray(unsigned InitElts, unsigned Size); 383 void MakeStruct(unsigned B, unsigned M) { 384 assert(isUninit() && "Bad state change"); 385 new ((void*)(char*)Data) StructData(B, M); 386 Kind = Struct; 387 } 388 void MakeUnion() { 389 assert(isUninit() && "Bad state change"); 390 new ((void*)(char*)Data) UnionData(); 391 Kind = Union; 392 } 393 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, 394 ArrayRef<const CXXRecordDecl*> Path); 395}; 396 397inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) { 398 V.print(OS); 399 return OS; 400} 401 402// Writes a concise representation of V to DB, in a single << operation. 403const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 404 const APValue &V); 405 406} // end namespace clang. 407 408#endif 409