From a1e0fb8c7be58a3ba019063641fac402e5514bbf Mon Sep 17 00:00:00 2001 From: Richard Smith <richard-llvm@metafoo.co.uk> Date: Thu, 9 Jan 2014 03:29:54 +0000 Subject: [PATCH] PR18427: Use an appropriately-aligned buffer in APValue, to avoid a crash on SPARC, where uint64_t apparently requires higher alignment than void*. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198845 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/APValue.h | 95 ++++++++++++++++++------------------- lib/AST/APValue.cpp | 74 ++++++++++++++++------------- 2 files changed, 85 insertions(+), 84 deletions(-) diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index b4fd2affa65..7bec1d0843e 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -108,15 +108,10 @@ private: }; struct MemberPointerData; - enum { - MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? - sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat)) - }; - - union { - void *Aligner; - char Data[MaxSize]; - }; + // We ensure elsewhere that Data is big enough for LV and MemberPointerData. + llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, + ComplexAPFloat, Vec, Arr, StructData, UnionData, + AddrLabelDiffData> Data; public: APValue() : Kind(Uninitialized) {} @@ -200,7 +195,7 @@ public: APSInt &getInt() { assert(isInt() && "Invalid accessor"); - return *(APSInt*)(char*)Data; + return *(APSInt*)(char*)Data.buffer; } const APSInt &getInt() const { return const_cast<APValue*>(this)->getInt(); @@ -208,7 +203,7 @@ public: APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); - return *(APFloat*)(char*)Data; + return *(APFloat*)(char*)Data.buffer; } const APFloat &getFloat() const { return const_cast<APValue*>(this)->getFloat(); @@ -216,7 +211,7 @@ public: APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data)->Real; + return ((ComplexAPSInt*)(char*)Data.buffer)->Real; } const APSInt &getComplexIntReal() const { return const_cast<APValue*>(this)->getComplexIntReal(); @@ -224,7 +219,7 @@ public: APSInt &getComplexIntImag() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data)->Imag; + return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; } const APSInt &getComplexIntImag() const { return const_cast<APValue*>(this)->getComplexIntImag(); @@ -232,7 +227,7 @@ public: APFloat &getComplexFloatReal() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data)->Real; + return ((ComplexAPFloat*)(char*)Data.buffer)->Real; } const APFloat &getComplexFloatReal() const { return const_cast<APValue*>(this)->getComplexFloatReal(); @@ -240,7 +235,7 @@ public: APFloat &getComplexFloatImag() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data)->Imag; + return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; } const APFloat &getComplexFloatImag() const { return const_cast<APValue*>(this)->getComplexFloatImag(); @@ -259,20 +254,20 @@ public: APValue &getVectorElt(unsigned I) { assert(isVector() && "Invalid accessor"); assert(I < getVectorLength() && "Index out of range"); - return ((Vec*)(char*)Data)->Elts[I]; + return ((Vec*)(char*)Data.buffer)->Elts[I]; } const APValue &getVectorElt(unsigned I) const { return const_cast<APValue*>(this)->getVectorElt(I); } unsigned getVectorLength() const { assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const void *)Data)->NumElts; + return ((const Vec*)(const void *)Data.buffer)->NumElts; } APValue &getArrayInitializedElt(unsigned I) { assert(isArray() && "Invalid accessor"); assert(I < getArrayInitializedElts() && "Index out of range"); - return ((Arr*)(char*)Data)->Elts[I]; + return ((Arr*)(char*)Data.buffer)->Elts[I]; } const APValue &getArrayInitializedElt(unsigned I) const { return const_cast<APValue*>(this)->getArrayInitializedElt(I); @@ -283,35 +278,35 @@ public: APValue &getArrayFiller() { assert(isArray() && "Invalid accessor"); assert(hasArrayFiller() && "No array filler"); - return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()]; + return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; } const APValue &getArrayFiller() const { return const_cast<APValue*>(this)->getArrayFiller(); } unsigned getArrayInitializedElts() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data)->NumElts; + return ((const Arr*)(const void *)Data.buffer)->NumElts; } unsigned getArraySize() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data)->ArrSize; + return ((const Arr*)(const void *)Data.buffer)->ArrSize; } unsigned getStructNumBases() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data)->NumBases; + return ((const StructData*)(const char*)Data.buffer)->NumBases; } unsigned getStructNumFields() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data)->NumFields; + return ((const StructData*)(const char*)Data.buffer)->NumFields; } APValue &getStructBase(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data)->Elts[i]; + return ((StructData*)(char*)Data.buffer)->Elts[i]; } APValue &getStructField(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i]; + return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; } const APValue &getStructBase(unsigned i) const { return const_cast<APValue*>(this)->getStructBase(i); @@ -322,11 +317,11 @@ public: const FieldDecl *getUnionField() const { assert(isUnion() && "Invalid accessor"); - return ((const UnionData*)(const char*)Data)->Field; + return ((const UnionData*)(const char*)Data.buffer)->Field; } APValue &getUnionValue() { assert(isUnion() && "Invalid accessor"); - return *((UnionData*)(char*)Data)->Value; + return *((UnionData*)(char*)Data.buffer)->Value; } const APValue &getUnionValue() const { return const_cast<APValue*>(this)->getUnionValue(); @@ -338,41 +333,41 @@ public: const AddrLabelExpr* getAddrLabelDiffLHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr; + return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; } const AddrLabelExpr* getAddrLabelDiffRHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr; + return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; } void setInt(const APSInt &I) { assert(isInt() && "Invalid accessor"); - *(APSInt*)(char*)Data = I; + *(APSInt*)(char*)Data.buffer = I; } void setFloat(const APFloat &F) { assert(isFloat() && "Invalid accessor"); - *(APFloat*)(char*)Data = F; + *(APFloat*)(char*)Data.buffer = F; } void setVector(const APValue *E, unsigned N) { assert(isVector() && "Invalid accessor"); - ((Vec*)(char*)Data)->Elts = new APValue[N]; - ((Vec*)(char*)Data)->NumElts = N; + ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; + ((Vec*)(char*)Data.buffer)->NumElts = N; for (unsigned i = 0; i != N; ++i) - ((Vec*)(char*)Data)->Elts[i] = E[i]; + ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; } void setComplexInt(const APSInt &R, const APSInt &I) { assert(R.getBitWidth() == I.getBitWidth() && "Invalid complex int (type mismatch)."); assert(isComplexInt() && "Invalid accessor"); - ((ComplexAPSInt*)(char*)Data)->Real = R; - ((ComplexAPSInt*)(char*)Data)->Imag = I; + ((ComplexAPSInt*)(char*)Data.buffer)->Real = R; + ((ComplexAPSInt*)(char*)Data.buffer)->Imag = I; } void setComplexFloat(const APFloat &R, const APFloat &I) { assert(&R.getSemantics() == &I.getSemantics() && "Invalid complex float (type mismatch)."); assert(isComplexFloat() && "Invalid accessor"); - ((ComplexAPFloat*)(char*)Data)->Real = R; - ((ComplexAPFloat*)(char*)Data)->Imag = I; + ((ComplexAPFloat*)(char*)Data.buffer)->Real = R; + ((ComplexAPFloat*)(char*)Data.buffer)->Imag = I; } void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, unsigned CallIndex); @@ -381,13 +376,13 @@ public: unsigned CallIndex); void setUnion(const FieldDecl *Field, const APValue &Value) { assert(isUnion() && "Invalid accessor"); - ((UnionData*)(char*)Data)->Field = Field; - *((UnionData*)(char*)Data)->Value = Value; + ((UnionData*)(char*)Data.buffer)->Field = Field; + *((UnionData*)(char*)Data.buffer)->Value = Value; } void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) { - ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr; - ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr; + ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; + ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; } /// Assign by swapping from a copy of the RHS. @@ -404,46 +399,46 @@ private: } void MakeInt() { assert(isUninit() && "Bad state change"); - new ((void*)Data) APSInt(1); + new ((void*)Data.buffer) APSInt(1); Kind = Int; } void MakeFloat() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) APFloat(0.0); + new ((void*)(char*)Data.buffer) APFloat(0.0); Kind = Float; } void MakeVector() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) Vec(); + new ((void*)(char*)Data.buffer) Vec(); Kind = Vector; } void MakeComplexInt() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) ComplexAPSInt(); + new ((void*)(char*)Data.buffer) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) ComplexAPFloat(); + new ((void*)(char*)Data.buffer) ComplexAPFloat(); Kind = ComplexFloat; } 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); + new ((void*)(char*)Data.buffer) StructData(B, M); Kind = Struct; } void MakeUnion() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) UnionData(); + new ((void*)(char*)Data.buffer) UnionData(); Kind = Union; } void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef<const CXXRecordDecl*> Path); void MakeAddrLabelDiff() { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) AddrLabelDiffData(); + new ((void*)(char*)Data.buffer) AddrLabelDiffData(); Kind = AddrLabelDiff; } }; diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index 541836b21b7..0d0e5612cef 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -34,7 +34,7 @@ namespace { struct APValue::LV : LVBase { static const unsigned InlinePathSpace = - (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry); + (sizeof(Data.buffer) - 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 @@ -75,7 +75,8 @@ namespace { struct APValue::MemberPointerData : MemberPointerBase { static const unsigned InlinePathSpace = - (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); + (sizeof(Data.buffer) - sizeof(MemberPointerBase)) / + sizeof(const CXXRecordDecl *); typedef const CXXRecordDecl *PathElem; union { PathElem Path[InlinePathSpace]; @@ -136,7 +137,7 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { break; case Vector: MakeVector(); - setVector(((const Vec *)(const char *)RHS.Data)->Elts, + setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, RHS.getVectorLength()); break; case ComplexInt: @@ -188,27 +189,27 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { void APValue::DestroyDataAndMakeUninit() { if (Kind == Int) - ((APSInt*)(char*)Data)->~APSInt(); + ((APSInt*)(char*)Data.buffer)->~APSInt(); else if (Kind == Float) - ((APFloat*)(char*)Data)->~APFloat(); + ((APFloat*)(char*)Data.buffer)->~APFloat(); else if (Kind == Vector) - ((Vec*)(char*)Data)->~Vec(); + ((Vec*)(char*)Data.buffer)->~Vec(); else if (Kind == ComplexInt) - ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt(); + ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); else if (Kind == ComplexFloat) - ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat(); + ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); else if (Kind == LValue) - ((LV*)(char*)Data)->~LV(); + ((LV*)(char*)Data.buffer)->~LV(); else if (Kind == Array) - ((Arr*)(char*)Data)->~Arr(); + ((Arr*)(char*)Data.buffer)->~Arr(); else if (Kind == Struct) - ((StructData*)(char*)Data)->~StructData(); + ((StructData*)(char*)Data.buffer)->~StructData(); else if (Kind == Union) - ((UnionData*)(char*)Data)->~UnionData(); + ((UnionData*)(char*)Data.buffer)->~UnionData(); else if (Kind == MemberPointer) - ((MemberPointerData*)(char*)Data)->~MemberPointerData(); + ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); else if (Kind == AddrLabelDiff) - ((AddrLabelDiffData*)(char*)Data)->~AddrLabelDiffData(); + ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); Kind = Uninitialized; } @@ -239,19 +240,21 @@ bool APValue::needsCleanup() const { "same size."); return getComplexIntReal().needsCleanup(); case LValue: - return reinterpret_cast<const LV *>(Data)->hasPathPtr(); + return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); case MemberPointer: - return reinterpret_cast<const MemberPointerData *>(Data)->hasPathPtr(); + return reinterpret_cast<const MemberPointerData *>(Data.buffer) + ->hasPathPtr(); } llvm_unreachable("Unknown APValue kind!"); } void APValue::swap(APValue &RHS) { std::swap(Kind, RHS.Kind); + const unsigned MaxSize = sizeof(Data.buffer); char TmpData[MaxSize]; - memcpy(TmpData, Data, MaxSize); - memcpy(Data, RHS.Data, MaxSize); - memcpy(RHS.Data, TmpData, MaxSize); + memcpy(TmpData, Data.buffer, MaxSize); + memcpy(Data.buffer, RHS.Data.buffer, MaxSize); + memcpy(RHS.Data.buffer, TmpData, MaxSize); } void APValue::dump() const { @@ -546,39 +549,39 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer(); + return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer(); } bool APValue::isLValueOnePastTheEnd() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt(); + return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt(); } CharUnits &APValue::getLValueOffset() { assert(isLValue() && "Invalid accessor"); - return ((LV*)(void*)Data)->Offset; + return ((LV*)(void*)Data.buffer)->Offset; } bool APValue::hasLValuePath() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data)->hasPath(); + return ((const LV*)(const char*)Data.buffer)->hasPath(); } ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { assert(isLValue() && hasLValuePath() && "Invalid accessor"); - const LV &LVal = *((const LV*)(const char*)Data); + const LV &LVal = *((const LV*)(const char*)Data.buffer); return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength); } unsigned APValue::getLValueCallIndex() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data)->CallIndex; + return ((const LV*)(const char*)Data.buffer)->CallIndex; } void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data); + LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); LVal.BaseAndIsOnePastTheEnd.setInt(false); LVal.Offset = O; @@ -590,7 +593,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data); + LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd); LVal.Offset = O; @@ -601,39 +604,42 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, const ValueDecl *APValue::getMemberPointerDecl() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return MPD.MemberAndIsDerivedMember.getPointer(); } bool APValue::isMemberPointerToDerivedMember() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return MPD.MemberAndIsDerivedMember.getInt(); } ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength); } void APValue::MakeLValue() { assert(isUninit() && "Bad state change"); - assert(sizeof(LV) <= MaxSize && "LV too big"); - new ((void*)(char*)Data) LV(); + assert(sizeof(LV) <= sizeof(Data.buffer) && "LV too big"); + new ((void*)(char*)Data.buffer) LV(); Kind = LValue; } void APValue::MakeArray(unsigned InitElts, unsigned Size) { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) Arr(InitElts, Size); + new ((void*)(char*)Data.buffer) Arr(InitElts, Size); Kind = Array; } void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef<const CXXRecordDecl*> Path) { assert(isUninit() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData; + MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer(Member); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); -- GitLab