diff options
Diffstat (limited to 'clang/lib/AST/Interp/Pointer.cpp')
| -rw-r--r-- | clang/lib/AST/Interp/Pointer.cpp | 83 |
1 files changed, 67 insertions, 16 deletions
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 00943dc846d3..e979b99b0fdd 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -7,9 +7,14 @@ //===----------------------------------------------------------------------===// #include "Pointer.h" +#include "Boolean.h" +#include "Context.h" +#include "Floating.h" #include "Function.h" +#include "Integral.h" #include "InterpBlock.h" #include "PrimType.h" +#include "Record.h" using namespace clang; using namespace clang::interp; @@ -89,7 +94,7 @@ APValue Pointer::toAPValue() const { Offset = CharUnits::Zero(); } else { // Build the lvalue base from the block. - Descriptor *Desc = getDeclDesc(); + const Descriptor *Desc = getDeclDesc(); if (auto *VD = Desc->asValueDecl()) Base = VD; else if (auto *E = Desc->asExpr()) @@ -122,8 +127,8 @@ APValue Pointer::toAPValue() const { bool IsVirtual = false; // Create a path entry for the field. - Descriptor *Desc = Ptr.getFieldDesc(); - if (auto *BaseOrMember = Desc->asDecl()) { + const Descriptor *Desc = Ptr.getFieldDesc(); + if (const auto *BaseOrMember = Desc->asDecl()) { Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual})); Ptr = Ptr.getBase(); continue; @@ -145,6 +150,13 @@ APValue Pointer::toAPValue() const { return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr); } +std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const { + if (!Pointee) + return "nullptr"; + + return toAPValue().getAsString(Ctx, getType()); +} + bool Pointer::isInitialized() const { assert(Pointee && "Cannot check if null pointer was initialized"); const Descriptor *Desc = getFieldDesc(); @@ -152,13 +164,16 @@ bool Pointer::isInitialized() const { if (Desc->isPrimitiveArray()) { if (isStatic() && Base == 0) return true; - // Primitive array field are stored in a bitset. - InitMap *Map = getInitMap(); - if (!Map) + + InitMapPtr &IM = getInitMap(); + + if (!IM) return false; - if (Map == (InitMap *)-1) + + if (IM->first) return true; - return Map->isInitialized(getIndex()); + + return IM->second->isElementInitialized(getIndex()); } // Field has its bit in an inline descriptor. @@ -175,15 +190,20 @@ void Pointer::initialize() const { if (isStatic() && Base == 0) return; - // Primitive array initializer. - InitMap *&Map = getInitMap(); - if (Map == (InitMap *)-1) + InitMapPtr &IM = getInitMap(); + if (!IM) + IM = + std::make_pair(false, std::make_shared<InitMap>(Desc->getNumElems())); + + assert(IM); + + // All initialized. + if (IM->first) return; - if (Map == nullptr) - Map = InitMap::allocate(Desc->getNumElems()); - if (Map->initialize(getIndex())) { - free(Map); - Map = (InitMap *)-1; + + if (IM->second->initializeElement(getIndex())) { + IM->first = true; + IM->second.reset(); } return; } @@ -210,3 +230,34 @@ bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) { bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) { return hasSameBase(A, B) && A.Base == B.Base && A.getFieldDesc()->IsArray; } + +APValue Pointer::toRValue(const Context &Ctx) const { + // Primitives. + if (getFieldDesc()->isPrimitive()) { + PrimType PT = *Ctx.classify(getType()); + TYPE_SWITCH(PT, return deref<T>().toAPValue()); + llvm_unreachable("Unhandled PrimType?"); + } + + APValue Result; + // Records. + if (getFieldDesc()->isRecord()) { + const Record *R = getRecord(); + Result = + APValue(APValue::UninitStruct(), R->getNumBases(), R->getNumFields()); + + for (unsigned I = 0; I != R->getNumFields(); ++I) { + const Pointer &FieldPtr = this->atField(R->getField(I)->Offset); + Result.getStructField(I) = FieldPtr.toRValue(Ctx); + } + + for (unsigned I = 0; I != R->getNumBases(); ++I) { + const Pointer &BasePtr = this->atField(R->getBase(I)->Offset); + Result.getStructBase(I) = BasePtr.toRValue(Ctx); + } + } + + // TODO: Arrays + + return Result; +} |
