Coverage Report

Created: 2020-02-18 08:44

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/Block.h
Line
Count
Source (jump to first uncovered line)
1
//===--- Block.h - Allocated blocks for the interpreter ---------*- 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
// Defines the classes describing allocated blocks.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H
14
#define LLVM_CLANG_AST_INTERP_BLOCK_H
15
16
#include "Descriptor.h"
17
#include "clang/AST/Decl.h"
18
#include "clang/AST/DeclCXX.h"
19
#include "clang/AST/Expr.h"
20
#include "clang/AST/ComparisonCategories.h"
21
#include "llvm/ADT/PointerUnion.h"
22
#include "llvm/Support/raw_ostream.h"
23
24
namespace clang {
25
namespace interp {
26
class Block;
27
class DeadBlock;
28
class Context;
29
class InterpState;
30
class Pointer;
31
class Function;
32
enum PrimType : unsigned;
33
34
/// A memory block, either on the stack or in the heap.
35
///
36
/// The storage described by the block immediately follows it in memory.
37
class Block {
38
public:
39
  // Creates a new block.
40
  Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc,
41
        bool IsStatic = false, bool IsExtern = false)
42
0
      : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {}
43
44
  Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
45
      : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern),
46
0
        Desc(Desc) {}
47
48
  /// Returns the block's descriptor.
49
0
  Descriptor *getDescriptor() const { return Desc; }
50
  /// Checks if the block has any live pointers.
51
0
  bool hasPointers() const { return Pointers; }
52
  /// Checks if the block is extern.
53
0
  bool isExtern() const { return IsExtern; }
54
  /// Checks if the block has static storage duration.
55
0
  bool isStatic() const { return IsStatic; }
56
  /// Checks if the block is temporary.
57
0
  bool isTemporary() const { return Desc->IsTemporary; }
58
  /// Returns the size of the block.
59
0
  InterpSize getSize() const { return Desc->getAllocSize(); }
60
  /// Returns the declaration ID.
61
0
  llvm::Optional<unsigned> getDeclID() const { return DeclID; }
62
63
  /// Returns a pointer to the stored data.
64
0
  char *data() { return reinterpret_cast<char *>(this + 1); }
65
66
  /// Returns a view over the data.
67
  template <typename T>
68
0
  T &deref() { return *reinterpret_cast<T *>(data()); }
Unexecuted instantiation: clang::interp::Integral<8u, true>& clang::interp::Block::deref<clang::interp::Integral<8u, true> >()
Unexecuted instantiation: clang::interp::Integral<8u, false>& clang::interp::Block::deref<clang::interp::Integral<8u, false> >()
Unexecuted instantiation: clang::interp::Integral<16u, true>& clang::interp::Block::deref<clang::interp::Integral<16u, true> >()
Unexecuted instantiation: clang::interp::Integral<16u, false>& clang::interp::Block::deref<clang::interp::Integral<16u, false> >()
Unexecuted instantiation: clang::interp::Integral<32u, true>& clang::interp::Block::deref<clang::interp::Integral<32u, true> >()
Unexecuted instantiation: clang::interp::Integral<32u, false>& clang::interp::Block::deref<clang::interp::Integral<32u, false> >()
Unexecuted instantiation: clang::interp::Integral<64u, true>& clang::interp::Block::deref<clang::interp::Integral<64u, true> >()
Unexecuted instantiation: clang::interp::Integral<64u, false>& clang::interp::Block::deref<clang::interp::Integral<64u, false> >()
Unexecuted instantiation: clang::interp::Boolean& clang::interp::Block::deref<clang::interp::Boolean>()
Unexecuted instantiation: clang::interp::Pointer& clang::interp::Block::deref<clang::interp::Pointer>()
69
70
  /// Invokes the constructor.
71
0
  void invokeCtor() {
72
0
    std::memset(data(), 0, getSize());
73
0
    if (Desc->CtorFn)
74
0
      Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
75
0
                   /*isActive=*/true, Desc);
76
0
  }
77
78
protected:
79
  friend class Pointer;
80
  friend class DeadBlock;
81
  friend class InterpState;
82
83
  Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
84
0
    : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
85
86
  // Deletes a dead block at the end of its lifetime.
87
  void cleanup();
88
89
  // Pointer chain management.
90
  void addPointer(Pointer *P);
91
  void removePointer(Pointer *P);
92
  void movePointer(Pointer *From, Pointer *To);
93
94
  /// Start of the chain of pointers.
95
  Pointer *Pointers = nullptr;
96
  /// Unique identifier of the declaration.
97
  llvm::Optional<unsigned> DeclID;
98
  /// Flag indicating if the block has static storage duration.
99
  bool IsStatic = false;
100
  /// Flag indicating if the block is an extern.
101
  bool IsExtern = false;
102
  /// Flag indicating if the pointer is dead.
103
  bool IsDead = false;
104
  /// Pointer to the stack slot descriptor.
105
  Descriptor *Desc;
106
};
107
108
/// Descriptor for a dead block.
109
///
110
/// Dead blocks are chained in a double-linked list to deallocate them
111
/// whenever pointers become dead.
112
class DeadBlock {
113
public:
114
  /// Copies the block.
115
  DeadBlock(DeadBlock *&Root, Block *Blk);
116
117
  /// Returns a pointer to the stored data.
118
0
  char *data() { return B.data(); }
119
120
private:
121
  friend class Block;
122
  friend class InterpState;
123
124
  void free();
125
126
  /// Root pointer of the list.
127
  DeadBlock *&Root;
128
  /// Previous block in the list.
129
  DeadBlock *Prev;
130
  /// Next block in the list.
131
  DeadBlock *Next;
132
133
  /// Actual block storing data and tracking pointers.
134
  Block B;
135
};
136
137
} // namespace interp
138
} // namespace clang
139
140
#endif