summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/APValue.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-11-07 05:07:52 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-11-07 05:07:52 +0000
commit80815600487aa8194187b9a30efd27e79d8ef37c (patch)
tree292b091d5fe2de4be7cd69242422973b51f08e9e /clang/lib/AST/APValue.cpp
parentc109a259d2095dc78dfc1291bddab5c7737ce375 (diff)
downloadbcm5719-llvm-80815600487aa8194187b9a30efd27e79d8ef37c.tar.gz
bcm5719-llvm-80815600487aa8194187b9a30efd27e79d8ef37c.zip
Constant expression evaluation: preserve subobject designator when flattening a
core constant value down to an APValue. llvm-svn: 143909
Diffstat (limited to 'clang/lib/AST/APValue.cpp')
-rw-r--r--clang/lib/AST/APValue.cpp71
1 files changed, 63 insertions, 8 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 0f315bbccda..12420fd8091 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -20,14 +20,41 @@
using namespace clang;
namespace {
- struct LV {
- const Expr* Base;
+ struct LVBase {
+ const Expr *Base;
CharUnits Offset;
+ unsigned PathLength;
};
}
+struct APValue::LV : LVBase {
+ static const unsigned InlinePathSpace =
+ (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
+
+ /// Path - The sequence of base classes, fields and array indices to follow to
+ /// walk from Base to the subobject. When performing GCC-style folding, there
+ /// may not be such a path.
+ union {
+ LValuePathEntry Path[InlinePathSpace];
+ LValuePathEntry *PathPtr;
+ };
+
+ LV() { PathLength = (unsigned)-1; }
+ ~LV() { if (hasPathPtr()) delete [] PathPtr; }
+
+ void allocPath() {
+ if (hasPathPtr()) PathPtr = new LValuePathEntry[PathLength];
+ }
+
+ bool hasPath() const { return PathLength != (unsigned)-1; }
+ bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
+
+ LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
+};
+
APValue::APValue(const Expr* B) : Kind(Uninitialized) {
- MakeLValue(); setLValue(B, CharUnits::Zero());
+ MakeLValue();
+ setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>());
}
const APValue &APValue::operator=(const APValue &RHS) {
@@ -57,8 +84,12 @@ const APValue &APValue::operator=(const APValue &RHS) {
setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
else if (isComplexFloat())
setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
- else if (isLValue())
- setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
+ else if (isLValue()) {
+ if (RHS.hasLValuePath())
+ setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath());
+ else
+ setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
+ }
return *this;
}
@@ -174,14 +205,38 @@ CharUnits &APValue::getLValueOffset() {
return ((LV*)(void*)Data)->Offset;
}
-void APValue::setLValue(const Expr *B, const CharUnits &O) {
+bool APValue::hasLValuePath() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((LV*)(char*)Data)->hasPath();
+}
+
+ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
+ assert(isLValue() && hasLValuePath() && "Invalid accessor");
+ LV &LVal = *((LV*)(char*)Data);
+ return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
+}
+
+void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) {
+ assert(isLValue() && "Invalid accessor");
+ LV &LVal = *((LV*)(char*)Data);
+ LVal.Base = B;
+ LVal.Offset = O;
+ LVal.PathLength = (unsigned)-1;
+}
+
+void APValue::setLValue(const Expr *B, const CharUnits &O,
+ ArrayRef<LValuePathEntry> Path) {
assert(isLValue() && "Invalid accessor");
- ((LV*)(char*)Data)->Base = B;
- ((LV*)(char*)Data)->Offset = O;
+ LV &LVal = *((LV*)(char*)Data);
+ LVal.Base = B;
+ LVal.Offset = O;
+ LVal.PathLength = Path.size();
+ memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
}
void APValue::MakeLValue() {
assert(isUninit() && "Bad state change");
+ assert(sizeof(LV) <= MaxSize && "LV too big");
new ((void*)(char*)Data) LV();
Kind = LValue;
}
OpenPOWER on IntegriCloud