APValue.h revision 9a17a680c74ef661bf3d864029adf7e74d9cb5b8
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 21namespace clang { 22 class CharUnits; 23 class DiagnosticBuilder; 24 class Expr; 25 class Decl; 26 27/// APValue - This class implements a discriminated union of [uninitialized] 28/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. 29class APValue { 30 typedef llvm::APSInt APSInt; 31 typedef llvm::APFloat APFloat; 32public: 33 enum ValueKind { 34 Uninitialized, 35 Int, 36 Float, 37 ComplexInt, 38 ComplexFloat, 39 LValue, 40 Vector 41 }; 42 union LValuePathEntry { 43 const Decl *BaseOrMember; 44 uint64_t ArrayIndex; 45 }; 46 struct NoLValuePath {}; 47private: 48 ValueKind Kind; 49 50 struct ComplexAPSInt { 51 APSInt Real, Imag; 52 ComplexAPSInt() : Real(1), Imag(1) {} 53 }; 54 struct ComplexAPFloat { 55 APFloat Real, Imag; 56 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 57 }; 58 59 struct Vec { 60 APValue *Elts; 61 unsigned NumElts; 62 Vec() : Elts(0), NumElts(0) {} 63 ~Vec() { delete[] Elts; } 64 }; 65 66 struct LV; 67 68 enum { 69 MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? 70 sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) 71 }; 72 73 union { 74 void *Aligner; 75 char Data[MaxSize]; 76 }; 77 78public: 79 APValue() : Kind(Uninitialized) {} 80 explicit APValue(const APSInt &I) : Kind(Uninitialized) { 81 MakeInt(); setInt(I); 82 } 83 explicit APValue(const APFloat &F) : Kind(Uninitialized) { 84 MakeFloat(); setFloat(F); 85 } 86 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { 87 MakeVector(); setVector(E, N); 88 } 89 APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) { 90 MakeComplexInt(); setComplexInt(R, I); 91 } 92 APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { 93 MakeComplexFloat(); setComplexFloat(R, I); 94 } 95 APValue(const APValue &RHS) : Kind(Uninitialized) { 96 *this = RHS; 97 } 98 APValue(const Expr *B, const CharUnits &O, NoLValuePath N) 99 : Kind(Uninitialized) { 100 MakeLValue(); setLValue(B, O, N); 101 } 102 APValue(const Expr *B, const CharUnits &O, ArrayRef<LValuePathEntry> Path) 103 : Kind(Uninitialized) { 104 MakeLValue(); setLValue(B, O, Path); 105 } 106 APValue(const Expr *B); 107 108 ~APValue() { 109 MakeUninit(); 110 } 111 112 ValueKind getKind() const { return Kind; } 113 bool isUninit() const { return Kind == Uninitialized; } 114 bool isInt() const { return Kind == Int; } 115 bool isFloat() const { return Kind == Float; } 116 bool isComplexInt() const { return Kind == ComplexInt; } 117 bool isComplexFloat() const { return Kind == ComplexFloat; } 118 bool isLValue() const { return Kind == LValue; } 119 bool isVector() const { return Kind == Vector; } 120 121 void print(raw_ostream &OS) const; 122 void dump() const; 123 124 APSInt &getInt() { 125 assert(isInt() && "Invalid accessor"); 126 return *(APSInt*)(char*)Data; 127 } 128 const APSInt &getInt() const { 129 return const_cast<APValue*>(this)->getInt(); 130 } 131 132 APFloat &getFloat() { 133 assert(isFloat() && "Invalid accessor"); 134 return *(APFloat*)(char*)Data; 135 } 136 const APFloat &getFloat() const { 137 return const_cast<APValue*>(this)->getFloat(); 138 } 139 140 APValue &getVectorElt(unsigned i) { 141 assert(isVector() && "Invalid accessor"); 142 return ((Vec*)(char*)Data)->Elts[i]; 143 } 144 const APValue &getVectorElt(unsigned i) const { 145 assert(isVector() && "Invalid accessor"); 146 return ((const Vec*)(const char*)Data)->Elts[i]; 147 } 148 unsigned getVectorLength() const { 149 assert(isVector() && "Invalid accessor"); 150 return ((const Vec*)(const void *)Data)->NumElts; 151 } 152 153 APSInt &getComplexIntReal() { 154 assert(isComplexInt() && "Invalid accessor"); 155 return ((ComplexAPSInt*)(char*)Data)->Real; 156 } 157 const APSInt &getComplexIntReal() const { 158 return const_cast<APValue*>(this)->getComplexIntReal(); 159 } 160 161 APSInt &getComplexIntImag() { 162 assert(isComplexInt() && "Invalid accessor"); 163 return ((ComplexAPSInt*)(char*)Data)->Imag; 164 } 165 const APSInt &getComplexIntImag() const { 166 return const_cast<APValue*>(this)->getComplexIntImag(); 167 } 168 169 APFloat &getComplexFloatReal() { 170 assert(isComplexFloat() && "Invalid accessor"); 171 return ((ComplexAPFloat*)(char*)Data)->Real; 172 } 173 const APFloat &getComplexFloatReal() const { 174 return const_cast<APValue*>(this)->getComplexFloatReal(); 175 } 176 177 APFloat &getComplexFloatImag() { 178 assert(isComplexFloat() && "Invalid accessor"); 179 return ((ComplexAPFloat*)(char*)Data)->Imag; 180 } 181 const APFloat &getComplexFloatImag() const { 182 return const_cast<APValue*>(this)->getComplexFloatImag(); 183 } 184 185 const Expr* getLValueBase() const; 186 CharUnits &getLValueOffset(); 187 const CharUnits &getLValueOffset() const { 188 return const_cast<APValue*>(this)->getLValueOffset(); 189 } 190 bool hasLValuePath() const; 191 ArrayRef<LValuePathEntry> getLValuePath() const; 192 193 void setInt(const APSInt &I) { 194 assert(isInt() && "Invalid accessor"); 195 *(APSInt*)(char*)Data = I; 196 } 197 void setFloat(const APFloat &F) { 198 assert(isFloat() && "Invalid accessor"); 199 *(APFloat*)(char*)Data = F; 200 } 201 void setVector(const APValue *E, unsigned N) { 202 assert(isVector() && "Invalid accessor"); 203 ((Vec*)(char*)Data)->Elts = new APValue[N]; 204 ((Vec*)(char*)Data)->NumElts = N; 205 for (unsigned i = 0; i != N; ++i) 206 ((Vec*)(char*)Data)->Elts[i] = E[i]; 207 } 208 void setComplexInt(const APSInt &R, const APSInt &I) { 209 assert(R.getBitWidth() == I.getBitWidth() && 210 "Invalid complex int (type mismatch)."); 211 assert(isComplexInt() && "Invalid accessor"); 212 ((ComplexAPSInt*)(char*)Data)->Real = R; 213 ((ComplexAPSInt*)(char*)Data)->Imag = I; 214 } 215 void setComplexFloat(const APFloat &R, const APFloat &I) { 216 assert(&R.getSemantics() == &I.getSemantics() && 217 "Invalid complex float (type mismatch)."); 218 assert(isComplexFloat() && "Invalid accessor"); 219 ((ComplexAPFloat*)(char*)Data)->Real = R; 220 ((ComplexAPFloat*)(char*)Data)->Imag = I; 221 } 222 void setLValue(const Expr *B, const CharUnits &O, NoLValuePath); 223 void setLValue(const Expr *B, const CharUnits &O, 224 ArrayRef<LValuePathEntry> Path); 225 226 const APValue &operator=(const APValue &RHS); 227 228private: 229 void MakeUninit(); 230 void MakeInt() { 231 assert(isUninit() && "Bad state change"); 232 new ((void*)Data) APSInt(1); 233 Kind = Int; 234 } 235 void MakeFloat() { 236 assert(isUninit() && "Bad state change"); 237 new ((void*)(char*)Data) APFloat(0.0); 238 Kind = Float; 239 } 240 void MakeVector() { 241 assert(isUninit() && "Bad state change"); 242 new ((void*)(char*)Data) Vec(); 243 Kind = Vector; 244 } 245 void MakeComplexInt() { 246 assert(isUninit() && "Bad state change"); 247 new ((void*)(char*)Data) ComplexAPSInt(); 248 Kind = ComplexInt; 249 } 250 void MakeComplexFloat() { 251 assert(isUninit() && "Bad state change"); 252 new ((void*)(char*)Data) ComplexAPFloat(); 253 Kind = ComplexFloat; 254 } 255 void MakeLValue(); 256}; 257 258inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) { 259 V.print(OS); 260 return OS; 261} 262 263// Writes a concise representation of V to DB, in a single << operation. 264const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 265 const APValue &V); 266 267} // end namespace clang. 268 269#endif 270