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