diff options
Diffstat (limited to 'lib/AST/APValue.cpp')
-rw-r--r-- | lib/AST/APValue.cpp | 166 |
1 files changed, 135 insertions, 31 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index c05b160b8e3d..1993bba9bd1a 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -1,9 +1,8 @@ //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===// // -// 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 // //===----------------------------------------------------------------------===// // @@ -21,6 +20,61 @@ #include "llvm/Support/raw_ostream.h" using namespace clang; +/// The identity of a type_info object depends on the canonical unqualified +/// type only. +TypeInfoLValue::TypeInfoLValue(const Type *T) + : T(T->getCanonicalTypeUnqualified().getTypePtr()) {} + +void TypeInfoLValue::print(llvm::raw_ostream &Out, + const PrintingPolicy &Policy) const { + Out << "typeid("; + QualType(getType(), 0).print(Out, Policy); + Out << ")"; +} + +static_assert( + 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <= + alignof(Type), + "Type is insufficiently aligned"); + +APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V) + : Ptr(P), Local{I, V} {} +APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V) + : Ptr(P), Local{I, V} {} + +APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, + QualType TypeInfo) { + LValueBase Base; + Base.Ptr = LV; + Base.TypeInfoType = TypeInfo.getAsOpaquePtr(); + return Base; +} + +unsigned APValue::LValueBase::getCallIndex() const { + return is<TypeInfoLValue>() ? 0 : Local.CallIndex; +} + +unsigned APValue::LValueBase::getVersion() const { + return is<TypeInfoLValue>() ? 0 : Local.Version; +} + +QualType APValue::LValueBase::getTypeInfoType() const { + assert(is<TypeInfoLValue>() && "not a type_info lvalue"); + return QualType::getFromOpaquePtr(TypeInfoType); +} + +namespace clang { +bool operator==(const APValue::LValueBase &LHS, + const APValue::LValueBase &RHS) { + if (LHS.Ptr != RHS.Ptr) + return false; + if (LHS.is<TypeInfoLValue>()) + return true; + return LHS.Local.CallIndex == RHS.Local.CallIndex && + LHS.Local.Version == RHS.Local.Version; +} +} + namespace { struct LVBase { APValue::LValueBase Base; @@ -46,26 +100,27 @@ APValue::LValueBase::operator bool () const { clang::APValue::LValueBase llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { return clang::APValue::LValueBase( - DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(), - DenseMapInfo<unsigned>::getEmptyKey(), - DenseMapInfo<unsigned>::getEmptyKey()); + DenseMapInfo<const ValueDecl*>::getEmptyKey()); } clang::APValue::LValueBase llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { return clang::APValue::LValueBase( - DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(), - DenseMapInfo<unsigned>::getTombstoneKey(), - DenseMapInfo<unsigned>::getTombstoneKey()); + DenseMapInfo<const ValueDecl*>::getTombstoneKey()); +} + +namespace clang { +llvm::hash_code hash_value(const APValue::LValueBase &Base) { + if (Base.is<TypeInfoLValue>()) + return llvm::hash_value(Base.getOpaqueValue()); + return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), + Base.getVersion()); +} } unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue( const clang::APValue::LValueBase &Base) { - llvm::FoldingSetNodeID ID; - ID.AddPointer(Base.getOpaqueValue()); - ID.AddInteger(Base.getCallIndex()); - ID.AddInteger(Base.getVersion()); - return ID.ComputeHash(); + return hash_value(Base); } bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual( @@ -164,9 +219,11 @@ APValue::UnionData::~UnionData () { delete Value; } -APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { +APValue::APValue(const APValue &RHS) : Kind(None) { switch (RHS.getKind()) { - case Uninitialized: + case None: + case Indeterminate: + Kind = RHS.getKind(); break; case Int: MakeInt(); @@ -176,6 +233,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { MakeFloat(); setFloat(RHS.getFloat()); break; + case FixedPoint: { + APFixedPoint FXCopy = RHS.getFixedPoint(); + MakeFixedPoint(std::move(FXCopy)); + break; + } case Vector: MakeVector(); setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, @@ -233,6 +295,8 @@ void APValue::DestroyDataAndMakeUninit() { ((APSInt*)(char*)Data.buffer)->~APSInt(); else if (Kind == Float) ((APFloat*)(char*)Data.buffer)->~APFloat(); + else if (Kind == FixedPoint) + ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); else if (Kind == Vector) ((Vec*)(char*)Data.buffer)->~Vec(); else if (Kind == ComplexInt) @@ -251,12 +315,13 @@ void APValue::DestroyDataAndMakeUninit() { ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); else if (Kind == AddrLabelDiff) ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); - Kind = Uninitialized; + Kind = None; } bool APValue::needsCleanup() const { switch (getKind()) { - case Uninitialized: + case None: + case Indeterminate: case AddrLabelDiff: return false; case Struct: @@ -268,6 +333,8 @@ bool APValue::needsCleanup() const { return getInt().needsCleanup(); case Float: return getFloat().needsCleanup(); + case FixedPoint: + return getFixedPoint().getValue().needsCleanup(); case ComplexFloat: assert(getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && @@ -312,8 +379,11 @@ static double GetApproxValue(const llvm::APFloat &F) { void APValue::dump(raw_ostream &OS) const { switch (getKind()) { - case Uninitialized: - OS << "Uninitialized"; + case None: + OS << "None"; + return; + case Indeterminate: + OS << "Indeterminate"; return; case Int: OS << "Int: " << getInt(); @@ -321,6 +391,9 @@ void APValue::dump(raw_ostream &OS) const { case Float: OS << "Float: " << GetApproxValue(getFloat()); return; + case FixedPoint: + OS << "FixedPoint : " << getFixedPoint(); + return; case Vector: OS << "Vector: "; getVectorElt(0).dump(OS); @@ -383,9 +456,13 @@ void APValue::dump(raw_ostream &OS) const { llvm_unreachable("Unknown APValue kind!"); } -void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ +void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, + QualType Ty) const { switch (getKind()) { - case APValue::Uninitialized: + case APValue::None: + Out << "<out of lifetime>"; + return; + case APValue::Indeterminate: Out << "<uninitialized>"; return; case APValue::Int: @@ -397,6 +474,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ case APValue::Float: Out << GetApproxValue(getFloat()); return; + case APValue::FixedPoint: + Out << getFixedPoint(); + return; case APValue::Vector: { Out << '{'; QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); @@ -453,7 +533,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) Out << *VD; - else { + else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { + TI.print(Out, Ctx.getPrintingPolicy()); + } else { assert(Base.get<const Expr *>() != nullptr && "Expecting non-null Expr"); Base.get<const Expr*>()->printPretty(Out, nullptr, @@ -478,6 +560,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { Out << *VD; ElemTy = VD->getType(); + } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { + TI.print(Out, Ctx.getPrintingPolicy()); + ElemTy = Base.getTypeInfoType(); } else { const Expr *E = Base.get<const Expr*>(); assert(E != nullptr && "Expecting non-null Expr"); @@ -491,8 +576,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (ElemTy->getAs<RecordType>()) { // The lvalue refers to a class type, so the next path entry is a base // or member. - const Decl *BaseOrMember = - BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer(); + const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { CastToBase = RD; ElemTy = Ctx.getRecordType(RD); @@ -506,7 +590,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ } } else { // The lvalue must refer to an array. - Out << '[' << Path[I].ArrayIndex << ']'; + Out << '[' << Path[I].getAsArrayIndex() << ']'; ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); } } @@ -592,7 +676,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ llvm_unreachable("Unknown APValue kind!"); } -std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { +std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const { std::string Result; llvm::raw_string_ostream Out(Result); printPretty(Out, Ctx, Ty); @@ -600,6 +684,26 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { return Result; } +bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const { + if (isInt()) { + Result = getInt(); + return true; + } + + if (isLValue() && isNullPointer()) { + Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); + return true; + } + + if (isLValue() && !getLValueBase()) { + Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); + return true; + } + + return false; +} + const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data.buffer)->Base; @@ -687,21 +791,21 @@ ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { } void APValue::MakeLValue() { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); static_assert(sizeof(LV) <= DataSize, "LV too big"); new ((void*)(char*)Data.buffer) LV(); Kind = LValue; } void APValue::MakeArray(unsigned InitElts, unsigned Size) { - assert(isUninit() && "Bad state change"); + assert(isAbsent() && "Bad state change"); 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"); + assert(isAbsent() && "Bad state change"); MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer(Member); |