diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST/APValue.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/AST/APValue.h | 163 |
1 files changed, 103 insertions, 60 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/APValue.h b/contrib/llvm-project/clang/include/clang/AST/APValue.h index cca92b5f8235..5f4ac02f53c9 100644 --- a/contrib/llvm-project/clang/include/clang/AST/APValue.h +++ b/contrib/llvm-project/clang/include/clang/AST/APValue.h @@ -13,14 +13,20 @@ #ifndef LLVM_CLANG_AST_APVALUE_H #define LLVM_CLANG_AST_APVALUE_H -#include "clang/Basic/FixedPoint.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/APFixedPoint.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/AlignOf.h" namespace clang { +namespace serialization { +template <typename T> class BasicReaderBase; +} // end namespace serialization + class AddrLabelExpr; class ASTContext; class CharUnits; @@ -32,6 +38,7 @@ namespace clang { struct PrintingPolicy; class Type; class ValueDecl; + class QualType; /// Symbolic representation of typeid(T) for some type T. class TypeInfoLValue { @@ -113,6 +120,7 @@ namespace clang { /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], /// [Vector: N * APValue], [Array: N * APValue] class APValue { + typedef llvm::APFixedPoint APFixedPoint; typedef llvm::APSInt APSInt; typedef llvm::APFloat APFloat; public: @@ -147,6 +155,8 @@ public: static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type); static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); + void Profile(llvm::FoldingSetNodeID &ID) const; + template <class T> bool is() const { return Ptr.is<T>(); } @@ -167,11 +177,14 @@ public: QualType getTypeInfoType() const; QualType getDynamicAllocType() const; + QualType getType() const; + friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { return !(LHS == RHS); } friend llvm::hash_code hash_value(const LValueBase &Base); + friend struct llvm::DenseMapInfo<LValueBase>; private: PtrTy Ptr; @@ -199,8 +212,7 @@ public: public: LValuePathEntry() : Value() {} - LValuePathEntry(BaseOrMemberType BaseOrMember) - : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {} + LValuePathEntry(BaseOrMemberType BaseOrMember); static LValuePathEntry ArrayIndex(uint64_t Index) { LValuePathEntry Result; Result.Value = Index; @@ -213,6 +225,8 @@ public: } uint64_t getAsArrayIndex() const { return Value; } + void Profile(llvm::FoldingSetNodeID &ID) const; + friend bool operator==(LValuePathEntry A, LValuePathEntry B) { return A.Value == B.Value; } @@ -223,12 +237,22 @@ public: return llvm::hash_value(A.Value); } }; + class LValuePathSerializationHelper { + const void *ElemTy; + + public: + ArrayRef<LValuePathEntry> Path; + + LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType); + QualType getType(); + }; struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; - friend class ASTReader; - friend class ASTWriter; + template <typename Impl> friend class clang::serialization::BasicReaderBase; + friend class ASTImporter; + friend class ASTNodeImporter; private: ValueKind Kind; @@ -302,7 +326,7 @@ public: MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); - APValue(APValue &&RHS) : Kind(None) { swap(RHS); } + APValue(APValue &&RHS); APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) : Kind(None) { @@ -337,6 +361,9 @@ public: return Result; } + APValue &operator=(const APValue &RHS); + APValue &operator=(APValue &&RHS); + ~APValue() { if (Kind != None && Kind != Indeterminate) DestroyDataAndMakeUninit(); @@ -352,6 +379,11 @@ public: /// Swaps the contents of this and the given APValue. void swap(APValue &RHS); + /// profile this value. There is no guarantee that values of different + /// types will not produce the same profiled value, so the type should + /// typically also be profiled if it's not implied by the context. + void Profile(llvm::FoldingSetNodeID &ID) const; + ValueKind getKind() const { return Kind; } bool isAbsent() const { return Kind == None; } @@ -375,11 +407,14 @@ public: void dump(raw_ostream &OS, const ASTContext &Context) const; void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; + void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty, + const ASTContext *Ctx = nullptr) const; + std::string getAsString(const ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { assert(isInt() && "Invalid accessor"); - return *(APSInt*)(char*)Data.buffer; + return *(APSInt *)(char *)&Data; } const APSInt &getInt() const { return const_cast<APValue*>(this)->getInt(); @@ -393,7 +428,7 @@ public: APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); - return *(APFloat*)(char*)Data.buffer; + return *(APFloat *)(char *)&Data; } const APFloat &getFloat() const { return const_cast<APValue*>(this)->getFloat(); @@ -401,7 +436,7 @@ public: APFixedPoint &getFixedPoint() { assert(isFixedPoint() && "Invalid accessor"); - return *(APFixedPoint *)(char *)Data.buffer; + return *(APFixedPoint *)(char *)&Data; } const APFixedPoint &getFixedPoint() const { return const_cast<APValue *>(this)->getFixedPoint(); @@ -409,7 +444,7 @@ public: APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data.buffer)->Real; + return ((ComplexAPSInt *)(char *)&Data)->Real; } const APSInt &getComplexIntReal() const { return const_cast<APValue*>(this)->getComplexIntReal(); @@ -417,7 +452,7 @@ public: APSInt &getComplexIntImag() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; + return ((ComplexAPSInt *)(char *)&Data)->Imag; } const APSInt &getComplexIntImag() const { return const_cast<APValue*>(this)->getComplexIntImag(); @@ -425,7 +460,7 @@ public: APFloat &getComplexFloatReal() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data.buffer)->Real; + return ((ComplexAPFloat *)(char *)&Data)->Real; } const APFloat &getComplexFloatReal() const { return const_cast<APValue*>(this)->getComplexFloatReal(); @@ -433,7 +468,7 @@ public: APFloat &getComplexFloatImag() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; + return ((ComplexAPFloat *)(char *)&Data)->Imag; } const APFloat &getComplexFloatImag() const { return const_cast<APValue*>(this)->getComplexFloatImag(); @@ -454,20 +489,20 @@ public: APValue &getVectorElt(unsigned I) { assert(isVector() && "Invalid accessor"); assert(I < getVectorLength() && "Index out of range"); - return ((Vec*)(char*)Data.buffer)->Elts[I]; + return ((Vec *)(char *)&Data)->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.buffer)->NumElts; + return ((const Vec *)(const void *)&Data)->NumElts; } APValue &getArrayInitializedElt(unsigned I) { assert(isArray() && "Invalid accessor"); assert(I < getArrayInitializedElts() && "Index out of range"); - return ((Arr*)(char*)Data.buffer)->Elts[I]; + return ((Arr *)(char *)&Data)->Elts[I]; } const APValue &getArrayInitializedElt(unsigned I) const { return const_cast<APValue*>(this)->getArrayInitializedElt(I); @@ -478,35 +513,37 @@ public: APValue &getArrayFiller() { assert(isArray() && "Invalid accessor"); assert(hasArrayFiller() && "No array filler"); - return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; + return ((Arr *)(char *)&Data)->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.buffer)->NumElts; + return ((const Arr *)(const void *)&Data)->NumElts; } unsigned getArraySize() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data.buffer)->ArrSize; + return ((const Arr *)(const void *)&Data)->ArrSize; } unsigned getStructNumBases() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data.buffer)->NumBases; + return ((const StructData *)(const char *)&Data)->NumBases; } unsigned getStructNumFields() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data.buffer)->NumFields; + return ((const StructData *)(const char *)&Data)->NumFields; } APValue &getStructBase(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data.buffer)->Elts[i]; + assert(i < getStructNumBases() && "base class index OOB"); + return ((StructData *)(char *)&Data)->Elts[i]; } APValue &getStructField(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; + assert(i < getStructNumFields() && "field index OOB"); + return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i]; } const APValue &getStructBase(unsigned i) const { return const_cast<APValue*>(this)->getStructBase(i); @@ -517,11 +554,11 @@ public: const FieldDecl *getUnionField() const { assert(isUnion() && "Invalid accessor"); - return ((const UnionData*)(const char*)Data.buffer)->Field; + return ((const UnionData *)(const char *)&Data)->Field; } APValue &getUnionValue() { assert(isUnion() && "Invalid accessor"); - return *((UnionData*)(char*)Data.buffer)->Value; + return *((UnionData *)(char *)&Data)->Value; } const APValue &getUnionValue() const { return const_cast<APValue*>(this)->getUnionValue(); @@ -533,119 +570,125 @@ public: const AddrLabelExpr* getAddrLabelDiffLHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; + return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr; } const AddrLabelExpr* getAddrLabelDiffRHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; + return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; } void setInt(APSInt I) { assert(isInt() && "Invalid accessor"); - *(APSInt *)(char *)Data.buffer = std::move(I); + *(APSInt *)(char *)&Data = std::move(I); } void setFloat(APFloat F) { assert(isFloat() && "Invalid accessor"); - *(APFloat *)(char *)Data.buffer = std::move(F); + *(APFloat *)(char *)&Data = std::move(F); } void setFixedPoint(APFixedPoint FX) { assert(isFixedPoint() && "Invalid accessor"); - *(APFixedPoint *)(char *)Data.buffer = std::move(FX); + *(APFixedPoint *)(char *)&Data = std::move(FX); } void setVector(const APValue *E, unsigned N) { - assert(isVector() && "Invalid accessor"); - ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; - ((Vec*)(char*)Data.buffer)->NumElts = N; + MutableArrayRef<APValue> InternalElts = setVectorUninit(N); for (unsigned i = 0; i != N; ++i) - ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; + InternalElts[i] = E[i]; } void setComplexInt(APSInt R, APSInt I) { assert(R.getBitWidth() == I.getBitWidth() && "Invalid complex int (type mismatch)."); assert(isComplexInt() && "Invalid accessor"); - ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); - ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); + ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R); + ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I); } void setComplexFloat(APFloat R, APFloat I) { assert(&R.getSemantics() == &I.getSemantics() && "Invalid complex float (type mismatch)."); assert(isComplexFloat() && "Invalid accessor"); - ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); - ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); + ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R); + ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I); } void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, bool IsNullPtr); void setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, bool IsNullPtr); - void setUnion(const FieldDecl *Field, const APValue &Value) { - assert(isUnion() && "Invalid accessor"); - ((UnionData*)(char*)Data.buffer)->Field = Field; - *((UnionData*)(char*)Data.buffer)->Value = Value; - } + void setUnion(const FieldDecl *Field, const APValue &Value); void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) { - ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; - ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; - } - - /// Assign by swapping from a copy of the RHS. - APValue &operator=(APValue RHS) { - swap(RHS); - return *this; + ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr; + ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr; } private: void DestroyDataAndMakeUninit(); void MakeInt() { assert(isAbsent() && "Bad state change"); - new ((void*)Data.buffer) APSInt(1); + new ((void *)&Data) APSInt(1); Kind = Int; } void MakeFloat() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) APFloat(0.0); + new ((void *)(char *)&Data) APFloat(0.0); Kind = Float; } void MakeFixedPoint(APFixedPoint &&FX) { assert(isAbsent() && "Bad state change"); - new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); + new ((void *)(char *)&Data) APFixedPoint(std::move(FX)); Kind = FixedPoint; } void MakeVector() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) Vec(); + new ((void *)(char *)&Data) Vec(); Kind = Vector; } void MakeComplexInt() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) ComplexAPSInt(); + new ((void *)(char *)&Data) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) ComplexAPFloat(); + new ((void *)(char *)&Data) ComplexAPFloat(); Kind = ComplexFloat; } void MakeLValue(); void MakeArray(unsigned InitElts, unsigned Size); void MakeStruct(unsigned B, unsigned M) { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) StructData(B, M); + new ((void *)(char *)&Data) StructData(B, M); Kind = Struct; } void MakeUnion() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) UnionData(); + new ((void *)(char *)&Data) UnionData(); Kind = Union; } void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef<const CXXRecordDecl*> Path); void MakeAddrLabelDiff() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) AddrLabelDiffData(); + new ((void *)(char *)&Data) AddrLabelDiffData(); Kind = AddrLabelDiff; } + +private: + /// The following functions are used as part of initialization, during + /// deserialization and importing. Reserve the space so that it can be + /// filled in by those steps. + MutableArrayRef<APValue> setVectorUninit(unsigned N) { + assert(isVector() && "Invalid accessor"); + Vec *V = ((Vec *)(char *)&Data); + V->Elts = new APValue[N]; + V->NumElts = N; + return {V->Elts, V->NumElts}; + } + MutableArrayRef<LValuePathEntry> + setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + MutableArrayRef<const CXXRecordDecl *> + setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size); }; } // end namespace clang. |