diff options
Diffstat (limited to 'include/clang/AST/APValue.h')
-rw-r--r-- | include/clang/AST/APValue.h | 245 |
1 files changed, 174 insertions, 71 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index d4057c9da5f38..6943479831ecf 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -1,9 +1,8 @@ //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #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/APFloat.h" #include "llvm/ADT/APSInt.h" @@ -24,14 +24,52 @@ namespace clang { class AddrLabelExpr; class ASTContext; class CharUnits; + class CXXRecordDecl; + class Decl; class DiagnosticBuilder; class Expr; class FieldDecl; - class Decl; + struct PrintingPolicy; + class Type; class ValueDecl; - class CXXRecordDecl; - class QualType; +/// Symbolic representation of typeid(T) for some type T. +class TypeInfoLValue { + const Type *T; + +public: + TypeInfoLValue() : T() {} + explicit TypeInfoLValue(const Type *T); + + const Type *getType() const { return T; } + explicit operator bool() const { return T; } + + void *getOpaqueValue() { return const_cast<Type*>(T); } + static TypeInfoLValue getFromOpaqueValue(void *Value) { + TypeInfoLValue V; + V.T = reinterpret_cast<const Type*>(Value); + return V; + } + + void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; +}; +} + +namespace llvm { +template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> { + static void *getAsVoidPointer(clang::TypeInfoLValue V) { + return V.getOpaqueValue(); + } + static clang::TypeInfoLValue getFromVoidPointer(void *P) { + return clang::TypeInfoLValue::getFromOpaqueValue(P); + } + // Validated by static_assert in APValue.cpp; hardcoded to avoid needing + // to include Type.h. + static constexpr int NumLowBitsAvailable = 3; +}; +} + +namespace clang { /// APValue - This class implements a discriminated union of [uninitialized] /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], /// [Vector: N * APValue], [Array: N * APValue] @@ -40,9 +78,13 @@ class APValue { typedef llvm::APFloat APFloat; public: enum ValueKind { - Uninitialized, + /// There is no such object (it's outside its lifetime). + None, + /// This object has an indeterminate value (C++ [basic.indet]). + Indeterminate, Int, Float, + FixedPoint, ComplexInt, ComplexFloat, LValue, @@ -55,14 +97,14 @@ public: }; class LValueBase { - public: - typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy; + typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue> + PtrTy; - LValueBase() : CallIndex(0), Version(0) {} - - template <class T> - LValueBase(T P, unsigned I = 0, unsigned V = 0) - : Ptr(P), CallIndex(I), Version(V) {} + public: + LValueBase() : Local{} {} + LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0); + LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0); + static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); template <class T> bool is() const { return Ptr.is<T>(); } @@ -77,45 +119,73 @@ public: bool isNull() const; - explicit operator bool () const; + explicit operator bool() const; - PtrTy getPointer() const { - return Ptr; - } + unsigned getCallIndex() const; + unsigned getVersion() const; + QualType getTypeInfoType() const; - unsigned getCallIndex() const { - return CallIndex; - } - - void setCallIndex(unsigned Index) { - CallIndex = Index; - } - - unsigned getVersion() const { - return Version; - } - - bool operator==(const LValueBase &Other) const { - return Ptr == Other.Ptr && CallIndex == Other.CallIndex && - Version == Other.Version; + 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); private: PtrTy Ptr; - unsigned CallIndex, Version; + struct LocalState { + unsigned CallIndex, Version; + }; + union { + LocalState Local; + /// The type std::type_info, if this is a TypeInfoLValue. + void *TypeInfoType; + }; }; + /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we + /// mean a virtual or non-virtual base class subobject. typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; - union LValuePathEntry { - /// 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; + + /// A non-discriminated union of a base, field, or array index. + class LValuePathEntry { + static_assert(sizeof(uintptr_t) <= sizeof(uint64_t), + "pointer doesn't fit in 64 bits?"); + uint64_t Value; + + public: + LValuePathEntry() : Value() {} + LValuePathEntry(BaseOrMemberType BaseOrMember) + : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {} + static LValuePathEntry ArrayIndex(uint64_t Index) { + LValuePathEntry Result; + Result.Value = Index; + return Result; + } + + BaseOrMemberType getAsBaseOrMember() const { + return BaseOrMemberType::getFromOpaqueValue( + reinterpret_cast<void *>(Value)); + } + uint64_t getAsArrayIndex() const { return Value; } + + friend bool operator==(LValuePathEntry A, LValuePathEntry B) { + return A.Value == B.Value; + } + friend bool operator!=(LValuePathEntry A, LValuePathEntry B) { + return A.Value != B.Value; + } + friend llvm::hash_code hash_value(LValuePathEntry A) { + return llvm::hash_value(A.Value); + } }; struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; + + friend class ASTReader; + friend class ASTWriter; + private: ValueKind Kind; @@ -168,55 +238,64 @@ private: DataType Data; public: - APValue() : Kind(Uninitialized) {} - explicit APValue(APSInt I) : Kind(Uninitialized) { + APValue() : Kind(None) {} + explicit APValue(APSInt I) : Kind(None) { MakeInt(); setInt(std::move(I)); } - explicit APValue(APFloat F) : Kind(Uninitialized) { + explicit APValue(APFloat F) : Kind(None) { MakeFloat(); setFloat(std::move(F)); } - explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { + explicit APValue(APFixedPoint FX) : Kind(None) { + MakeFixedPoint(std::move(FX)); + } + explicit APValue(const APValue *E, unsigned N) : Kind(None) { MakeVector(); setVector(E, N); } - APValue(APSInt R, APSInt I) : Kind(Uninitialized) { + APValue(APSInt R, APSInt I) : Kind(None) { MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); } - APValue(APFloat R, APFloat I) : Kind(Uninitialized) { + APValue(APFloat R, APFloat I) : Kind(None) { MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); } APValue(const APValue &RHS); - APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } + APValue(APValue &&RHS) : Kind(None) { swap(RHS); } APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) - : Kind(Uninitialized) { + : Kind(None) { MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, bool IsNullPtr = false) - : Kind(Uninitialized) { + : Kind(None) { MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } - APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { + APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { MakeArray(InitElts, Size); } - APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { + APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { MakeStruct(B, M); } explicit APValue(const FieldDecl *D, const APValue &V = APValue()) - : Kind(Uninitialized) { + : Kind(None) { MakeUnion(); setUnion(D, V); } APValue(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { + ArrayRef<const CXXRecordDecl*> Path) : Kind(None) { MakeMemberPointer(Member, IsDerivedMember, Path); } APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) - : Kind(Uninitialized) { + : Kind(None) { MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); } + static APValue IndeterminateValue() { + APValue Result; + Result.Kind = Indeterminate; + return Result; + } ~APValue() { - MakeUninit(); + if (Kind != None && Kind != Indeterminate) + DestroyDataAndMakeUninit(); } /// Returns whether the object performed allocations. @@ -230,9 +309,14 @@ public: void swap(APValue &RHS); ValueKind getKind() const { return Kind; } - bool isUninit() const { return Kind == Uninitialized; } + + bool isAbsent() const { return Kind == None; } + bool isIndeterminate() const { return Kind == Indeterminate; } + bool hasValue() const { return Kind != None && Kind != Indeterminate; } + bool isInt() const { return Kind == Int; } bool isFloat() const { return Kind == Float; } + bool isFixedPoint() const { return Kind == FixedPoint; } bool isComplexInt() const { return Kind == ComplexInt; } bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } @@ -246,8 +330,8 @@ public: void dump() const; void dump(raw_ostream &OS) const; - void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; - std::string getAsString(ASTContext &Ctx, QualType Ty) const; + void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; + std::string getAsString(const ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { assert(isInt() && "Invalid accessor"); @@ -257,6 +341,12 @@ public: return const_cast<APValue*>(this)->getInt(); } + /// Try to convert this value to an integral constant. This works if it's an + /// integer, null pointer, or offset from a null pointer. Returns true on + /// success. + bool toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const; + APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); return *(APFloat*)(char*)Data.buffer; @@ -265,6 +355,14 @@ public: return const_cast<APValue*>(this)->getFloat(); } + APFixedPoint &getFixedPoint() { + assert(isFixedPoint() && "Invalid accessor"); + return *(APFixedPoint *)(char *)Data.buffer; + } + const APFixedPoint &getFixedPoint() const { + return const_cast<APValue *>(this)->getFixedPoint(); + } + APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); return ((ComplexAPSInt*)(char*)Data.buffer)->Real; @@ -406,6 +504,10 @@ public: assert(isFloat() && "Invalid accessor"); *(APFloat *)(char *)Data.buffer = std::move(F); } + void setFixedPoint(APFixedPoint FX) { + assert(isFixedPoint() && "Invalid accessor"); + *(APFixedPoint *)(char *)Data.buffer = std::move(FX); + } void setVector(const APValue *E, unsigned N) { assert(isVector() && "Invalid accessor"); ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; @@ -451,51 +553,52 @@ public: private: void DestroyDataAndMakeUninit(); - void MakeUninit() { - if (Kind != Uninitialized) - DestroyDataAndMakeUninit(); - } void MakeInt() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)Data.buffer) APSInt(1); Kind = Int; } void MakeFloat() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) APFloat(0.0); Kind = Float; } + void MakeFixedPoint(APFixedPoint &&FX) { + assert(isAbsent() && "Bad state change"); + new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); + Kind = FixedPoint; + } void MakeVector() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) Vec(); Kind = Vector; } void MakeComplexInt() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); 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"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) StructData(B, M); Kind = Struct; } void MakeUnion() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); 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"); + assert(isAbsent() && "Bad state change"); new ((void*)(char*)Data.buffer) AddrLabelDiffData(); Kind = AddrLabelDiff; } |