summaryrefslogtreecommitdiff
path: root/include/clang/AST/APValue.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/APValue.h')
-rw-r--r--include/clang/AST/APValue.h245
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;
}