Coverage Report

Created: 2025-09-04 07:34

/src/solidity/libsmtutil/Sorts.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
19
#pragma once
20
21
#include <libsmtutil/Exceptions.h>
22
23
#include <libsolutil/Common.h>
24
25
#include <memory>
26
#include <vector>
27
28
namespace solidity::smtutil
29
{
30
31
enum class Kind
32
{
33
  Int,
34
  Bool,
35
  BitVector,
36
  Function,
37
  Array,
38
  Sort,
39
  Tuple
40
};
41
42
struct Sort
43
{
44
  Sort(Kind _kind):
45
10.6M
    kind(_kind) {}
46
10.6M
  virtual ~Sort() = default;
47
1.13M
  virtual bool operator==(Sort const& _other) const { return kind == _other.kind; }
48
49
  Kind const kind;
50
};
51
using SortPointer = std::shared_ptr<Sort>;
52
53
struct IntSort: public Sort
54
{
55
  IntSort(bool _signed):
56
    Sort(Kind::Int),
57
    isSigned(_signed)
58
24
  {}
59
60
  bool operator==(Sort const& _other) const override
61
567k
  {
62
567k
    if (!Sort::operator==(_other))
63
0
      return false;
64
65
567k
    auto otherIntSort = dynamic_cast<IntSort const*>(&_other);
66
567k
    smtAssert(otherIntSort);
67
567k
    return isSigned == otherIntSort->isSigned;
68
567k
  }
69
70
  bool isSigned;
71
};
72
73
struct BitVectorSort: public Sort
74
{
75
  BitVectorSort(unsigned _size):
76
    Sort(Kind::BitVector),
77
    size(_size)
78
6.52k
  {}
79
80
  bool operator==(Sort const& _other) const override
81
0
  {
82
0
    if (!Sort::operator==(_other))
83
0
      return false;
84
85
0
    auto otherBitVectorSort = dynamic_cast<BitVectorSort const*>(&_other);
86
0
    smtAssert(otherBitVectorSort);
87
0
    return size == otherBitVectorSort->size;
88
0
  }
89
90
  unsigned size;
91
};
92
93
struct FunctionSort: public Sort
94
{
95
  FunctionSort(std::vector<SortPointer> _domain, SortPointer _codomain):
96
394k
    Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {}
97
  bool operator==(Sort const& _other) const override
98
0
  {
99
0
    if (!Sort::operator==(_other))
100
0
      return false;
101
0
    auto _otherFunction = dynamic_cast<FunctionSort const*>(&_other);
102
0
    smtAssert(_otherFunction, "");
103
0
    if (domain.size() != _otherFunction->domain.size())
104
0
      return false;
105
0
    if (!std::equal(
106
0
      domain.begin(),
107
0
      domain.end(),
108
0
      _otherFunction->domain.begin(),
109
0
      [&](SortPointer _a, SortPointer _b) { return *_a == *_b; }
110
0
    ))
111
0
      return false;
112
0
    smtAssert(codomain, "");
113
0
    smtAssert(_otherFunction->codomain, "");
114
0
    return *codomain == *_otherFunction->codomain;
115
0
  }
116
117
  std::vector<SortPointer> domain;
118
  SortPointer codomain;
119
};
120
121
struct ArraySort: public Sort
122
{
123
  /// _domain is the sort of the indices
124
  /// _range is the sort of the values
125
  ArraySort(SortPointer _domain, SortPointer _range):
126
947k
    Sort(Kind::Array), domain(std::move(_domain)), range(std::move(_range)) {}
127
  bool operator==(Sort const& _other) const override
128
267k
  {
129
267k
    if (!Sort::operator==(_other))
130
0
      return false;
131
267k
    auto _otherArray = dynamic_cast<ArraySort const*>(&_other);
132
267k
    smtAssert(_otherArray, "");
133
267k
    smtAssert(_otherArray->domain, "");
134
267k
    smtAssert(_otherArray->range, "");
135
267k
    smtAssert(domain, "");
136
267k
    smtAssert(range, "");
137
267k
    return *domain == *_otherArray->domain && *range == *_otherArray->range;
138
267k
  }
139
140
  SortPointer domain;
141
  SortPointer range;
142
};
143
144
struct SortSort: public Sort
145
{
146
115k
  SortSort(SortPointer _inner): Sort(Kind::Sort), inner(std::move(_inner)) {}
147
  bool operator==(Sort const& _other) const override
148
0
  {
149
0
    if (!Sort::operator==(_other))
150
0
      return false;
151
0
    auto _otherSort = dynamic_cast<SortSort const*>(&_other);
152
0
    smtAssert(_otherSort, "");
153
0
    smtAssert(_otherSort->inner, "");
154
0
    smtAssert(inner, "");
155
0
    return *inner == *_otherSort->inner;
156
0
  }
157
158
  SortPointer inner;
159
};
160
161
struct TupleSort: public Sort
162
{
163
  TupleSort(
164
    std::string _name,
165
    std::vector<std::string> _members,
166
    std::vector<SortPointer> _components
167
  ):
168
    Sort(Kind::Tuple),
169
    name(std::move(_name)),
170
    members(std::move(_members)),
171
    components(std::move(_components))
172
1.02M
  {
173
3.14M
    for (size_t i = 0; i < members.size(); ++i)
174
2.12M
      memberToIndex[members.at(i)] = i;
175
1.02M
  }
176
177
  SortPointer memberSort(std::string const& _member)
178
0
  {
179
0
    return components.at(memberToIndex.at(_member));
180
0
  }
181
182
  bool operator==(Sort const& _other) const override
183
270k
  {
184
270k
    if (!Sort::operator==(_other))
185
0
      return false;
186
270k
    auto _otherTuple = dynamic_cast<TupleSort const*>(&_other);
187
270k
    smtAssert(_otherTuple, "");
188
270k
    if (name != _otherTuple->name)
189
0
      return false;
190
270k
    if (members != _otherTuple->members)
191
0
      return false;
192
270k
    if (components.size() != _otherTuple->components.size())
193
0
      return false;
194
270k
    if (!std::equal(
195
270k
      components.begin(),
196
270k
      components.end(),
197
270k
      _otherTuple->components.begin(),
198
541k
      [&](SortPointer _a, SortPointer _b) { return *_a == *_b; }
199
270k
    ))
200
0
      return false;
201
270k
    return true;
202
270k
  }
203
204
  std::string const name;
205
  std::vector<std::string> const members;
206
  std::vector<SortPointer> const components;
207
  std::map<std::string, size_t> memberToIndex;
208
};
209
210
211
/** Frequently used sorts.*/
212
struct SortProvider
213
{
214
  static std::shared_ptr<Sort> const boolSort;
215
  static std::shared_ptr<IntSort> const uintSort;
216
  static std::shared_ptr<IntSort> const sintSort;
217
  static std::shared_ptr<IntSort> intSort(bool _signed = false);
218
  static std::shared_ptr<BitVectorSort> const bitVectorSort;
219
};
220
221
}