Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/Pointer.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Pointer.cpp - Types for the constexpr VM ---------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "Pointer.h"
10
#include "Function.h"
11
#include "InterpBlock.h"
12
#include "PrimType.h"
13
14
using namespace clang;
15
using namespace clang::interp;
16
17
0
Pointer::Pointer(Block *Pointee) : Pointer(Pointee, 0, 0) {}
Unexecuted instantiation: clang::interp::Pointer::Pointer(clang::interp::Block*)
Unexecuted instantiation: clang::interp::Pointer::Pointer(clang::interp::Block*)
18
19
0
Pointer::Pointer(const Pointer &P) : Pointer(P.Pointee, P.Base, P.Offset) {}
Unexecuted instantiation: clang::interp::Pointer::Pointer(clang::interp::Pointer const&)
Unexecuted instantiation: clang::interp::Pointer::Pointer(clang::interp::Pointer const&)
20
21
Pointer::Pointer(Pointer &&P)
22
8
    : Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
23
8
  if (Pointee)
24
0
    Pointee->movePointer(&P, this);
25
8
}
26
27
Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
28
    : Pointee(Pointee), Base(Base), Offset(Offset) {
29
  assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
30
  if (Pointee)
31
    Pointee->addPointer(this);
32
}
33
34
16
Pointer::~Pointer() {
35
16
  if (Pointee) {
36
0
    Pointee->removePointer(this);
37
0
    Pointee->cleanup();
38
0
  }
39
16
}
40
41
0
void Pointer::operator=(const Pointer &P) {
42
0
  Block *Old = Pointee;
43
0
44
0
  if (Pointee)
45
0
    Pointee->removePointer(this);
46
0
47
0
  Offset = P.Offset;
48
0
  Base = P.Base;
49
0
50
0
  Pointee = P.Pointee;
51
0
  if (Pointee)
52
0
    Pointee->addPointer(this);
53
0
54
0
  if (Old)
55
0
    Old->cleanup();
56
0
}
57
58
0
void Pointer::operator=(Pointer &&P) {
59
0
  Block *Old = Pointee;
60
0
61
0
  if (Pointee)
62
0
    Pointee->removePointer(this);
63
0
64
0
  Offset = P.Offset;
65
0
  Base = P.Base;
66
0
67
0
  Pointee = P.Pointee;
68
0
  if (Pointee)
69
0
    Pointee->movePointer(&P, this);
70
0
71
0
  if (Old)
72
0
    Old->cleanup();
73
0
}
74
75
0
APValue Pointer::toAPValue() const {
76
0
  APValue::LValueBase Base;
77
0
  llvm::SmallVector<APValue::LValuePathEntry, 5> Path;
78
0
  CharUnits Offset;
79
0
  bool IsNullPtr;
80
0
  bool IsOnePastEnd;
81
0
82
0
  if (isZero()) {
83
0
    Base = static_cast<const Expr *>(nullptr);
84
0
    IsNullPtr = true;
85
0
    IsOnePastEnd = false;
86
0
    Offset = CharUnits::Zero();
87
0
  } else {
88
    // Build the lvalue base from the block.
89
0
    Descriptor *Desc = getDeclDesc();
90
0
    if (auto *VD = Desc->asValueDecl())
91
0
      Base = VD;
92
0
    else if (auto *E = Desc->asExpr())
93
0
      Base = E;
94
0
    else
95
0
      llvm_unreachable("Invalid allocation type");
96
0
97
    // Not a null pointer.
98
0
    IsNullPtr = false;
99
0
100
0
    if (isUnknownSizeArray()) {
101
0
      IsOnePastEnd = false;
102
0
      Offset = CharUnits::Zero();
103
0
    } else {
104
      // TODO: compute the offset into the object.
105
0
      Offset = CharUnits::Zero();
106
0
107
      // Build the path into the object.
108
0
      Pointer Ptr = *this;
109
0
      while (Ptr.isField()) {
110
0
        if (Ptr.isArrayElement()) {
111
0
          Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
112
0
          Ptr = Ptr.getArray();
113
0
        } else {
114
          // TODO: figure out if base is virtual
115
0
          bool IsVirtual = false;
116
0
117
          // Create a path entry for the field.
118
0
          Descriptor *Desc = Ptr.getFieldDesc();
119
0
          if (auto *BaseOrMember = Desc->asDecl()) {
120
0
            Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
121
0
            Ptr = Ptr.getBase();
122
0
            continue;
123
0
          }
124
0
          llvm_unreachable("Invalid field type");
125
0
        }
126
0
      }
127
0
128
0
      IsOnePastEnd = isOnePastEnd();
129
0
    }
130
0
  }
131
0
132
0
  return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr);
133
0
}
134
135
0
bool Pointer::isInitialized() const {
136
0
  assert(Pointee && "Cannot check if null pointer was initialized");
137
0
  Descriptor *Desc = getFieldDesc();
138
0
  if (Desc->isPrimitiveArray()) {
139
0
    if (Pointee->IsStatic)
140
0
      return true;
141
    // Primitive array field are stored in a bitset.
142
0
    InitMap *Map = getInitMap();
143
0
    if (!Map)
144
0
      return false;
145
0
    if (Map == (InitMap *)-1)
146
0
      return true;
147
0
    return Map->isInitialized(getIndex());
148
0
  } else {
149
    // Field has its bit in an inline descriptor.
150
0
    return Base == 0 || getInlineDesc()->IsInitialized;
151
0
  }
152
0
}
153
154
0
void Pointer::initialize() const {
155
0
  assert(Pointee && "Cannot initialize null pointer");
156
0
  Descriptor *Desc = getFieldDesc();
157
0
  if (Desc->isPrimitiveArray()) {
158
0
    if (!Pointee->IsStatic) {
159
      // Primitive array initializer.
160
0
      InitMap *&Map = getInitMap();
161
0
      if (Map == (InitMap *)-1)
162
0
        return;
163
0
      if (Map == nullptr)
164
0
        Map = InitMap::allocate(Desc->getNumElems());
165
0
      if (Map->initialize(getIndex())) {
166
0
        free(Map);
167
0
        Map = (InitMap *)-1;
168
0
      }
169
0
    }
170
0
  } else {
171
    // Field has its bit in an inline descriptor.
172
0
    assert(Base != 0 && "Only composite fields can be initialised");
173
0
    getInlineDesc()->IsInitialized = true;
174
0
  }
175
0
}
176
177
0
void Pointer::activate() const {
178
  // Field has its bit in an inline descriptor.
179
0
  assert(Base != 0 && "Only composite fields can be initialised");
180
0
  getInlineDesc()->IsActive = true;
181
0
}
182
183
0
void Pointer::deactivate() const {
184
  // TODO: this only appears in constructors, so nothing to deactivate.
185
0
}
186
187
0
bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
188
0
  return A.Pointee == B.Pointee;
189
0
}
190
191
0
bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
192
0
  return A.Base == B.Base && A.getFieldDesc()->IsArray;
193
0
}