summaryrefslogtreecommitdiff
path: root/include/clang/AST/APValue.h
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-11-10 06:34:14 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-11-10 06:34:14 +0000
commit180f47959a066795cc0f409433023af448bb0328 (patch)
treee5a8c5e3c47c68d4ee460e09489ebac5cf60b8a4 /include/clang/AST/APValue.h
parent64b4b43a23aa8b8009470e3cc451333f623d7d58 (diff)
downloadclang-180f47959a066795cc0f409433023af448bb0328.tar.gz
clang-180f47959a066795cc0f409433023af448bb0328.tar.bz2
clang-180f47959a066795cc0f409433023af448bb0328.tar.xz
Constant expression evaluation: support for evaluation of structs and unions of
literal types, as well as derived-to-base casts for lvalues and derived-to-virtual-base casts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144265 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/AST/APValue.h')
-rw-r--r--include/clang/AST/APValue.h85
1 files changed, 83 insertions, 2 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index 57c89d62be..177d7baf4a 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -17,11 +17,13 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/PointerIntPair.h"
namespace clang {
class CharUnits;
class DiagnosticBuilder;
class Expr;
+ class FieldDecl;
class Decl;
/// APValue - This class implements a discriminated union of [uninitialized]
@@ -39,14 +41,21 @@ public:
ComplexFloat,
LValue,
Vector,
- Array
+ Array,
+ Struct,
+ Union
};
+ typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
union LValuePathEntry {
- const Decl *BaseOrMember;
+ /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
+ /// in the path. An opaque value of type BaseOrMemberType.
+ void *BaseOrMember;
+ /// ArrayIndex - The array index of the next item in the path.
uint64_t ArrayIndex;
};
struct NoLValuePath {};
struct UninitArray {};
+ struct UninitStruct {};
private:
ValueKind Kind;
@@ -71,6 +80,19 @@ private:
Arr(unsigned NumElts, unsigned ArrSize);
~Arr();
};
+ struct StructData {
+ APValue *Elts;
+ unsigned NumBases;
+ unsigned NumFields;
+ StructData(unsigned NumBases, unsigned NumFields);
+ ~StructData();
+ };
+ struct UnionData {
+ const FieldDecl *Field;
+ APValue *Value;
+ UnionData();
+ ~UnionData();
+ };
enum {
MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
@@ -114,6 +136,13 @@ public:
APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
MakeArray(InitElts, Size);
}
+ APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
+ MakeStruct(B, M);
+ }
+ explicit APValue(const FieldDecl *D, const APValue &V = APValue())
+ : Kind(Uninitialized) {
+ MakeUnion(); setUnion(D, V);
+ }
~APValue() {
MakeUninit();
@@ -128,6 +157,8 @@ public:
bool isLValue() const { return Kind == LValue; }
bool isVector() const { return Kind == Vector; }
bool isArray() const { return Kind == Array; }
+ bool isStruct() const { return Kind == Struct; }
+ bool isUnion() const { return Kind == Union; }
void print(raw_ostream &OS) const;
void dump() const;
@@ -229,6 +260,41 @@ public:
return ((const Arr*)(const void *)Data)->ArrSize;
}
+ unsigned getStructNumBases() const {
+ assert(isStruct() && "Invalid accessor");
+ return ((StructData*)(char*)Data)->NumBases;
+ }
+ unsigned getStructNumFields() const {
+ assert(isStruct() && "Invalid accessor");
+ return ((StructData*)(char*)Data)->NumFields;
+ }
+ APValue &getStructBase(unsigned i) {
+ assert(isStruct() && "Invalid accessor");
+ return ((StructData*)(char*)Data)->Elts[i];
+ }
+ APValue &getStructField(unsigned i) {
+ assert(isStruct() && "Invalid accessor");
+ return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i];
+ }
+ const APValue &getStructBase(unsigned i) const {
+ return const_cast<APValue*>(this)->getStructBase(i);
+ }
+ const APValue &getStructField(unsigned i) const {
+ return const_cast<APValue*>(this)->getStructField(i);
+ }
+
+ const FieldDecl *getUnionField() const {
+ assert(isUnion() && "Invalid accessor");
+ return ((UnionData*)(char*)Data)->Field;
+ }
+ APValue &getUnionValue() {
+ assert(isUnion() && "Invalid accessor");
+ return *((UnionData*)(char*)Data)->Value;
+ }
+ const APValue &getUnionValue() const {
+ return const_cast<APValue*>(this)->getUnionValue();
+ }
+
void setInt(const APSInt &I) {
assert(isInt() && "Invalid accessor");
*(APSInt*)(char*)Data = I;
@@ -261,6 +327,11 @@ public:
void setLValue(const Expr *B, const CharUnits &O, NoLValuePath);
void setLValue(const Expr *B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path);
+ void setUnion(const FieldDecl *Field, const APValue &Value) {
+ assert(isUnion() && "Invalid accessor");
+ ((UnionData*)(char*)Data)->Field = Field;
+ *((UnionData*)(char*)Data)->Value = Value;
+ }
const APValue &operator=(const APValue &RHS);
@@ -293,6 +364,16 @@ private:
}
void MakeLValue();
void MakeArray(unsigned InitElts, unsigned Size);
+ void MakeStruct(unsigned B, unsigned M) {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) StructData(B, M);
+ Kind = Struct;
+ }
+ void MakeUnion() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) UnionData();
+ Kind = Union;
+ }
};
inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) {