• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tudasc / TypeART / 24397737785

14 Apr 2026 12:00PM UTC coverage: 90.264% (+1.3%) from 88.924%
24397737785

Pull #187

github

web-flow
Merge 278119205 into de3bc148a
Pull Request #187: Release v2.2

880 of 935 new or added lines in 31 files covered. (94.12%)

17 existing lines in 3 files now uncovered.

4886 of 5413 relevant lines covered (90.26%)

38873.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/lib/runtime/TypeResolution.cpp
1
// TypeART library
2
//
3
// Copyright (c) 2017-2026 TypeART Authors
4
// Distributed under the BSD 3-Clause license.
5
// (See accompanying file LICENSE.txt or copy at
6
// https://opensource.org/licenses/BSD-3-Clause)
7
//
8
// Project home: https://github.com/tudasc/TypeART
9
//
10
// SPDX-License-Identifier: BSD-3-Clause
11
//
12

13
#include "TypeResolution.h"
14

15
#include "AllocationTracking.h"
16
#include "Runtime.h"
17
#include "RuntimeData.h"
18
#include "RuntimeInterface.h"
19
#include "TypeDB.h"
20
#include "TypeInterface.h"
21
#include "support/Logger.h"
22
#include "support/System.h"
23

24
#include <cassert>
25
#include <charconv>
26
#include <cstddef>
27
#include <utility>
28
#include <vector>
29

30
namespace typeart {
31

32
namespace detail {
33

34
template <typename P, typename T>
35
inline const void* add_byte_offset(const P* addr, T offset) {
4,252 ✔
36
  assert(addr != nullptr);
4,252 ✔
37
  return static_cast<const P*>(static_cast<const char*>(addr) + offset);
4,252 ✔
38
}
39

40
template <typename T>
41
inline std::ptrdiff_t substract_pointer(const T* addr_a, const T* addr_b) {
2,989 ✔
42
  assert(addr_a != nullptr);
2,989 ✔
43
  assert(addr_b != nullptr);
2,989 ✔
44
  return static_cast<const char*>(addr_a) - static_cast<const char*>(addr_b);
2,989 ✔
45
}
46

47
inline size_t get_member_index_at(const typeart_struct_layout& structInfo, size_t offset) {
726 ✔
48
  const size_t num_members = structInfo.num_members;
726 ✔
49

50
  if (num_members == 0) {
726 ✔
51
    return 0;
×
52
  }
53

54
  const auto* struct_offsets = structInfo.offsets;
726 ✔
55

56
  if (offset > struct_offsets[num_members - 1]) {
726 ✔
57
    return num_members - 1;
24 ✔
58
  }
59

60
  size_t member_index{0};
702 ✔
61
  while (member_index < (num_members - 1) && offset >= struct_offsets[member_index + 1]) {
1,536 ✔
62
    ++member_index;
834 ✔
63
  }
64
  return member_index;
702 ✔
65
}
726 ✔
66

67
}  // namespace detail
68

69
TypeResolution::TypeResolution(const TypeDB& type_db, Recorder& recorder)
1,421 ✔
70
    : type_database{type_db}, runtime_recorder{recorder} {
1,421 ✔
71
}
1,421 ✔
72

73
TypeResolution::TypeArtStatus TypeResolution::getSubTypeInfo(const void* baseAddr, size_t offset,
768 ✔
74
                                                             const typeart_struct_layout& containerInfo, int* subType,
408 ✔
75
                                                             const void** subTypeBaseAddr, size_t* subTypeOffset,
76
                                                             size_t* subTypeCount) const {
77
  if (containerInfo.type_id < 0) {
768 ✔
78
    return TYPEART_ERROR;
21 ✔
79
  }
80

81
  if (offset >= containerInfo.extent) {
747 ✔
82
    return TYPEART_BAD_OFFSET;
21 ✔
83
  }
84

85
  // Get index of the struct member at the address
86
  const size_t memberIndex = detail::get_member_index_at(containerInfo, offset);
726 ✔
87
  const int memberType     = containerInfo.member_types[memberIndex];
726 ✔
88
  const size_t baseOffset  = containerInfo.offsets[memberIndex];
726 ✔
89

90
  const size_t internalOffset = offset - baseOffset;
726 ✔
91
  const size_t typeSize       = type_database.getTypeSize(memberType);
726 ✔
92
  if (typeSize == 0) {
726 ✔
93
    return TYPEART_INVALID_ID;
×
94
  }
95
  const size_t offsetInTypeSize = internalOffset / typeSize;
726 ✔
96
  const size_t newOffset        = internalOffset % typeSize;
726 ✔
97

98
  // If newOffset != 0, the subtype cannot be atomic, i.e. must be a struct
99
  if (newOffset != 0) {
726 ✔
100
    if (type_database.isReservedType(memberType)) {
42 ✔
101
      return TYPEART_BAD_ALIGNMENT;
42 ✔
102
    }
103
  }
×
104

105
  // Ensure that the array index is in bounds
106
  if (offsetInTypeSize >= containerInfo.count[memberIndex]) {
684 ✔
107
    // Address points to padding
108
    return TYPEART_BAD_ALIGNMENT;
105 ✔
109
  }
110

111
  *subType         = memberType;
579 ✔
112
  *subTypeBaseAddr = detail::add_byte_offset(baseAddr, baseOffset);
579 ✔
113
  *subTypeOffset   = newOffset;
579 ✔
114
  *subTypeCount    = containerInfo.count[memberIndex] - offsetInTypeSize;
579 ✔
115

116
  return TYPEART_OK;
579 ✔
117
}
768 ✔
118

119
TypeResolution::TypeArtStatus TypeResolution::getTypeInfoInternal(const void* baseAddr, size_t offset,
684 ✔
120
                                                                  const StructTypeInfo& containerInfo, int* type,
121
                                                                  size_t* count) const {
122
  assert(offset < containerInfo.extent && "Something went wrong with the base address computation");
1,368 ✔
123

124
  int subType{-1};
684 ✔
125
  const void* subTypeBaseAddr;
684 ✔
126
  size_t subTypeOffset{0};
684 ✔
127
  size_t subTypeCount{0};
684 ✔
128

129
  const StructTypeInfo* structInfo = &containerInfo;
684 ✔
130

131
  const auto to_struct_layout_info = [](const auto& struct_type_info) {
1,368 ✔
132
    typeart_struct_layout struct_layout;
684 ✔
133
    struct_layout.type_id      = struct_type_info.type_id;
684 ✔
134
    struct_layout.name         = struct_type_info.name.c_str();
684 ✔
135
    struct_layout.num_members  = struct_type_info.num_members;
684 ✔
136
    struct_layout.extent       = struct_type_info.extent;
684 ✔
137
    struct_layout.offsets      = &struct_type_info.offsets[0];
684 ✔
138
    struct_layout.member_types = &struct_type_info.member_types[0];
684 ✔
139
    struct_layout.count        = &struct_type_info.array_sizes[0];
684 ✔
140
    return struct_layout;
684 ✔
141
  };
684 ✔
142

143
  // Resolve type recursively, until the address matches exactly
144
  bool resolve{true};
684 ✔
145
  while (resolve) {
1,242 ✔
146
    const auto status_subtype_info = getSubTypeInfo(baseAddr, offset, to_struct_layout_info(*structInfo), &subType,
684 ✔
147
                                                    &subTypeBaseAddr, &subTypeOffset, &subTypeCount);
148

149
    if (status_subtype_info != TYPEART_OK) {
684 ✔
150
      return status_subtype_info;
126 ✔
151
    }
152

153
    baseAddr = subTypeBaseAddr;
558 ✔
154
    offset   = subTypeOffset;
558 ✔
155

156
    // Continue as long as there is a byte offset
157
    resolve = offset != 0;
558 ✔
158

159
    // Get layout of the nested struct
160
    if (resolve) {
558 ✔
161
      const auto status_struct_info = getStructInfo(subType, &structInfo);
×
162
      if (status_struct_info != TYPEART_OK) {
×
163
        return status_struct_info;
×
164
      }
165
    }
×
166
  }
684 ✔
167
  *type  = subType;
558 ✔
168
  *count = subTypeCount;
558 ✔
169
  return TYPEART_OK;
558 ✔
170
}
684 ✔
171

172
TypeResolution::TypeArtStatus TypeResolution::getTypeInfo(const void* addr, const void* basePtr,
14,669 ✔
173
                                                          const PointerInfo& ptrInfo, int* type, size_t* count) const {
174
  const int containing_type = ptrInfo.typeId;
14,669 ✔
175
  size_t containing_type_count{0};
14,669 ✔
176
  size_t internal_byte_offset{0};
14,669 ✔
177

178
  // First, retrieve the containing type
179
  TypeArtStatus status = getContainingTypeInfo(addr, basePtr, ptrInfo, &containing_type_count, &internal_byte_offset);
14,669 ✔
180
  if (status != TYPEART_OK) {
14,669 ✔
181
    if (status == TYPEART_UNKNOWN_ADDRESS) {
1,123 ✔
182
      runtime_recorder.incAddrMissing(addr);
1,123 ✔
183
    }
1,123 ✔
184
    return status;
1,123 ✔
185
  }
186

187
  // Check for exact address match
188
  if (internal_byte_offset == 0) {
13,546 ✔
189
    *type  = containing_type;
12,442 ✔
190
    *count = containing_type_count;
12,442 ✔
191
    return TYPEART_OK;
12,442 ✔
192
  }
193

194
  if (type_database.isBuiltinType(containing_type)) {
1,104 ✔
195
    // Address points to the middle of a builtin type
196
    return TYPEART_BAD_ALIGNMENT;
420 ✔
197
  }
198

199
  // Resolve struct recursively
200
  const auto* structInfo = type_database.getStructInfo(containing_type);
684 ✔
201
  if (structInfo != nullptr) {
684 ✔
202
    const void* containingTypeAddr = detail::add_byte_offset(addr, -std::ptrdiff_t(internal_byte_offset));
684 ✔
203
    return getTypeInfoInternal(containingTypeAddr, internal_byte_offset, *structInfo, type, count);
684 ✔
204
  }
684 ✔
205

206
  return TYPEART_INVALID_ID;
×
207
}
14,669 ✔
208

209
TypeResolution::TypeArtStatus TypeResolution::getContainingTypeInfo(const void* addr, const void* basePtr,
14,759 ✔
210
                                                                    const PointerInfo& ptrInfo, size_t* count,
211
                                                                    size_t* offset) const {
212
  const auto& basePtrInfo = ptrInfo;
14,759 ✔
213
  size_t typeSize         = type_database.getTypeSize(basePtrInfo.typeId);
14,759 ✔
214
  if (basePtrInfo.typeId == TYPEART_VOID || basePtrInfo.typeId == TYPEART_POINTER) {
14,759 ✔
215
    // typeSize = 1;
216
  }
189 ✔
217

218
  // Check for exact match -> no further checks and offsets calculations needed
219
  if (basePtr == addr) {
14,759 ✔
220
    *count  = ptrInfo.count;
11,770 ✔
221
    *offset = 0;
11,770 ✔
222
    return TYPEART_OK;
11,770 ✔
223
  }
224

225
  if (typeSize == 0) {
2,989 ✔
226
    return TYPEART_ERROR;
×
227
  }
228

229
  // The address points inside a known array
230
  const void* blockEnd = detail::add_byte_offset(basePtr, basePtrInfo.count * typeSize);
2,989 ✔
231

232
  // Ensure that the given address is in bounds and points to the start of an element
233
  if (addr >= blockEnd) {
2,989 ✔
234
    const std::ptrdiff_t byte_offset_to_base = detail::substract_pointer(addr, basePtr);
1,123 ✔
235

236
    const auto elements  = byte_offset_to_base / typeSize;
1,123 ✔
237
    const auto oob_index = elements - basePtrInfo.count + 1;
1,123 ✔
238
    LOG_WARNING("Out of bounds for the lookup: (" << debug::toString(addr, basePtrInfo)
1,292 ✔
239
                                                  << ") #Elements too far: " << oob_index);
169 ✔
240
    return TYPEART_UNKNOWN_ADDRESS;
1,123 ✔
241
  }
1,123 ✔
242

243
  assert(addr >= basePtr && "Error in base address computation");
3,732 ✔
244

245
  const std::ptrdiff_t addrDif = detail::substract_pointer(addr, basePtr);
1,866 ✔
246

247
  // Offset of the pointer w.r.t. the start of the containing type
248
  const size_t internalOffset = addrDif % typeSize;
1,866 ✔
249

250
  // Array index
251
  const size_t typeOffset = addrDif / typeSize;
1,866 ✔
252
  const size_t typeCount  = basePtrInfo.count - typeOffset;
1,866 ✔
253

254
  // Retrieve and return type information
255
  *count  = typeCount;
1,866 ✔
256
  *offset = internalOffset;
1,866 ✔
257
  return TYPEART_OK;
1,866 ✔
258
}
14,759 ✔
259

260
TypeResolution::TypeArtStatus TypeResolution::getStructInfo(int type_id, const StructTypeInfo** structInfo) const {
630 ✔
261
  // Requested ID must correspond to a struct
262
  if (!type_database.isStructType(type_id)) {
630 ✔
263
    return TYPEART_WRONG_KIND;
×
264
  }
265

266
  const auto* result = type_database.getStructInfo(type_id);
630 ✔
267

268
  if (result != nullptr) {
630 ✔
269
    *structInfo = result;
588 ✔
270
    return TYPEART_OK;
588 ✔
271
  }
272
  return TYPEART_INVALID_ID;
42 ✔
273
}
630 ✔
274

275
// const TypeDB& TypeResolution::db() const {
276
//   return type_database;
277
// }
278

279
namespace detail {
280
// inline typeart_status query_type(const void* addr, int* type, size_t* count) {
281
//   auto alloc = typeart::RuntimeSystem::get().allocTracker.findBaseAlloc(addr);
282
//   typeart::RuntimeSystem::get().recorder.incUsedInRequest(addr);
283
//   if (alloc) {
284
//     return typeart::RuntimeSystem::get().getTypeResolution().getTypeInfo(addr, alloc->first, alloc->second, type,
285
//     count);
286
//   }
287
//   return TYPEART_UNKNOWN_ADDRESS;
288
// }
289

290
inline typeart_status query_type(const void* addr, typeart_type_info& info) {
15,020 ✔
291
  auto alloc = typeart::RuntimeSystem::get().allocation_tracker().findBaseAlloc(addr);
15,020 ✔
292
  typeart::RuntimeSystem::get().recorder.incUsedInRequest(addr);
15,020 ✔
293
  if (alloc) {
15,020 ✔
294
    typeart_base_type_info base;
14,669 ✔
295
    base.address        = alloc->first;
14,669 ✔
296
    base.type_id        = alloc->second.typeId;
14,669 ✔
297
    base.count          = alloc->second.count;
14,669 ✔
298
    info.base_type_info = base;
14,669 ✔
299
    info.address        = addr;
14,669 ✔
300

301
    const auto result = typeart::RuntimeSystem::get().get_type_resolution().getTypeInfo(
29,338 ✔
302
        addr, alloc->first, alloc->second, &info.type_id, &info.count);
14,669 ✔
303

304
    typeart::RuntimeSystem::get().recorder.incTypeQuery(base.type_id);
14,669 ✔
305
    return result;
14,669 ✔
306
  }
14,669 ✔
307
  return TYPEART_UNKNOWN_ADDRESS;
351 ✔
308
}
15,020 ✔
309

310
inline typeart_status query_struct_layout(int type_id, typeart_struct_layout* struct_layout) {
630 ✔
311
  const typeart::StructTypeInfo* struct_info;
630 ✔
312
  typeart_status status = typeart::RuntimeSystem::get().get_type_resolution().getStructInfo(type_id, &struct_info);
630 ✔
313
  if (status == TYPEART_OK) {
630 ✔
314
    struct_layout->type_id      = struct_info->type_id;
588 ✔
315
    struct_layout->name         = struct_info->name.c_str();
588 ✔
316
    struct_layout->num_members  = struct_info->num_members;
588 ✔
317
    struct_layout->extent       = struct_info->extent;
588 ✔
318
    struct_layout->offsets      = (struct_info->offsets).data();
588 ✔
319
    struct_layout->member_types = (struct_info->member_types).data();
588 ✔
320
    struct_layout->count        = (struct_info->array_sizes).data();
588 ✔
321
  } else {
588 ✔
322
    struct_layout->type_id      = std::numeric_limits<decltype(typeart_struct_layout::type_id)>::min();
42 ✔
323
    struct_layout->name         = "";
42 ✔
324
    struct_layout->num_members  = 0;
42 ✔
325
    struct_layout->extent       = 0;
42 ✔
326
    struct_layout->offsets      = nullptr;
42 ✔
327
    struct_layout->member_types = nullptr;
42 ✔
328
    struct_layout->count        = nullptr;
42 ✔
329
  }
330
  return status;
630 ✔
331
}
630 ✔
332

333
char* string2char(std::string_view src) {
42 ✔
334
  // const void* ret_addr       = __builtin_return_address(0);
335
  const size_t source_length = src.size() + 1;  // +1 for '\0'
42 ✔
336
  char* string_copy          = (char*)malloc(sizeof(char) * source_length);
42 ✔
337

338
  if (string_copy == nullptr) {
42 ✔
339
    return nullptr;
×
340
  }
341

342
  // typeart::RuntimeSystem::get().allocTracker.onAlloc(string_copy, TYPEART_CHAR_8, source_length, ret_addr);
343

344
  memcpy(string_copy, src.data(), source_length);
42 ✔
345

346
  return string_copy;
42 ✔
347
}
42 ✔
348

349
}  // namespace detail
350
}  // namespace typeart
351

352
/**
353
 * Runtime interface implementation
354
 *
355
 */
356

357
typeart_status typeart_get_type(const void* addr, typeart_type_info* base_type) {
15,020 ✔
358
  typeart::RTGuard guard;
15,020 ✔
359
  return typeart::detail::query_type(addr, *base_type);
15,020 ✔
360
}
15,020 ✔
361

362
typeart_status typeart_get_containing_type(const typeart_type_info* type, typeart_base_type_info* containing_type,
90 ✔
363
                                           size_t* byte_offset) {
364
  typeart::RTGuard guard;
90 ✔
365
  containing_type->type_id = type->base_type_info.type_id;
90 ✔
366
  containing_type->count   = type->base_type_info.count;
90 ✔
367
  containing_type->address = type->base_type_info.address;
90 ✔
368
  const typeart::PointerInfo info{type->base_type_info.type_id, type->base_type_info.count};
90 ✔
369
  const auto result = typeart::RuntimeSystem::get().type_resolution().getContainingTypeInfo(
108 ✔
370
      type->address, containing_type->address, info, &containing_type->count, byte_offset);
54 ✔
371

372
  return result;
54 ✔
373
}
54 ✔
374

375
typeart_status typeart_get_subtype(const typeart_struct_layout* container_layout, const void* base_addr, size_t offset,
84 ✔
376
                                   typeart_base_type_info* subtype_info, size_t* subtype_byte_offset) {
377
  typeart::RTGuard guard;
84 ✔
378
  auto status = typeart::RuntimeSystem::get().get_type_resolution().getSubTypeInfo(
168 ✔
379
      base_addr, offset, *container_layout, &subtype_info->type_id, &subtype_info->address, subtype_byte_offset,
84 ✔
380
      &subtype_info->count);
84 ✔
381
  return status;
84 ✔
382
}
84 ✔
383

384
typeart_status typeart_resolve_type_id(int type_id, typeart_struct_layout* struct_layout) {
630 ✔
385
  typeart::RTGuard guard;
630 ✔
386
  return typeart::detail::query_struct_layout(type_id, struct_layout);
630 ✔
387
}
630 ✔
388

389
typeart_status typeart_get_return_address(const void* addr, const void** return_addr) {
42 ✔
390
  typeart::RTGuard guard;
42 ✔
391
  auto alloc = typeart::RuntimeSystem::get().allocation_tracker().findBaseAlloc(addr);
42 ✔
392

393
  if (alloc) {
42 ✔
394
    *return_addr = alloc.value().second.debug;
21 ✔
395
    return TYPEART_OK;
21 ✔
396
  }
397
  *return_addr = nullptr;
21 ✔
398
  return TYPEART_UNKNOWN_ADDRESS;
21 ✔
399
}
42 ✔
400

401
// typeart_status_t typeart_get_source_location(const void* addr, char** file, char** function, char** line) {
402
//   using namespace typeart::detail;
403
//   typeart::RTGuard guard;
404

405
//   auto source_loc = typeart::SourceLocation::create(addr);
406

407
//   if (source_loc) {
408
//     *file     = string2char(source_loc->file);
409
//     *function = string2char(source_loc->function);
410
//     *line     = string2char(source_loc->line);
411

412
//     if (*file == nullptr || *function == nullptr || *line == nullptr) {
413
//       return TYPEART_ERROR;
414
//     }
415

416
//     return TYPEART_OK;
417
//   }
418

419
//   return TYPEART_UNKNOWN_ADDRESS;
420
// }
421

422
typeart_status_t typeart_get_source_location(const void* addr, typeart_source_location* source_location) {
21 ✔
423
  using namespace typeart::detail;
424
  typeart::RTGuard guard;
21 ✔
425

426
  auto source_loc = typeart::SourceLocation::create(addr);
21 ✔
427

428
  if (source_loc) {
21 ✔
429
    source_location->file     = string2char(source_loc->file);
21 ✔
430
    source_location->function = string2char(source_loc->function);
21 ✔
431
    source_location->line     = 0;
21 ✔
432
    const auto& line          = source_loc->line;
21 ✔
433
    auto [ptr, ec]            = std::from_chars(line.data(), line.data() + line.size(), source_location->line);
36 ✔
434

435
    if (source_location->file == nullptr || source_location->function == nullptr || ec != std::errc{}) {
21 ✔
436
      return TYPEART_ERROR;
×
437
    }
438

439
    return TYPEART_OK;
21 ✔
440
  }
21 ✔
441

442
  return TYPEART_UNKNOWN_ADDRESS;
×
443
}
21 ✔
444

445
typeart_status_t typeart_free_source_location(typeart_source_location* source_location) {
21 ✔
446
  using namespace typeart::detail;
447
  typeart::RTGuard guard;
21 ✔
448

449
  if (source_location == nullptr) {
21 ✔
450
    return TYPEART_ERROR;
×
451
  }
452

453
  free(source_location->file);
21 ✔
454
  free(source_location->function);
21 ✔
455

456
  source_location->file     = nullptr;
21 ✔
457
  source_location->function = nullptr;
21 ✔
458
  source_location->line     = 0;
21 ✔
459

460
  return TYPEART_OK;
21 ✔
461
}
21 ✔
462

463
const char* typeart_get_type_name(int type_id) {
10,105 ✔
464
  typeart::RTGuard guard;
10,105 ✔
465
  return typeart::RuntimeSystem::get().database().getTypeName(type_id).c_str();
10,105 ✔
466
}
10,105 ✔
467

468
bool typeart_is_vector_type(int type_id) {
42 ✔
469
  typeart::RTGuard guard;
42 ✔
470
  return typeart::RuntimeSystem::get().database().isVectorType(type_id);
42 ✔
471
}
42 ✔
472

473
bool typeart_is_valid_type(int type_id) {
42 ✔
474
  typeart::RTGuard guard;
42 ✔
475
  return typeart::RuntimeSystem::get().database().isValid(type_id);
42 ✔
476
}
42 ✔
477

478
bool typeart_is_reserved_type(int type_id) {
42 ✔
479
  typeart::RTGuard guard;
42 ✔
480
  return typeart::RuntimeSystem::get().database().isReservedType(type_id);
42 ✔
481
}
42 ✔
482

483
bool typeart_is_builtin_type(int type_id) {
42 ✔
484
  typeart::RTGuard guard;
42 ✔
485
  return typeart::RuntimeSystem::get().database().isBuiltinType(type_id);
42 ✔
486
}
42 ✔
487

488
bool typeart_is_struct_type(int type_id) {
42 ✔
489
  typeart::RTGuard guard;
42 ✔
490
  return typeart::RuntimeSystem::get().database().isStructType(type_id);
42 ✔
491
}
42 ✔
492

493
bool typeart_is_userdefined_type(int type_id) {
42 ✔
494
  typeart::RTGuard guard;
42 ✔
495
  return typeart::RuntimeSystem::get().database().isUserDefinedType(type_id);
42 ✔
496
}
42 ✔
497

498
bool typeart_is_union(int type_id) {
×
499
  typeart::RTGuard guard;
×
NEW
500
  return typeart::RuntimeSystem::get().database().isUnion(type_id);
×
501
}
×
502

503
size_t typeart_get_type_size(int type_id) {
42 ✔
504
  typeart::RTGuard guard;
42 ✔
505
  return typeart::RuntimeSystem::get().database().getTypeSize(type_id);
42 ✔
506
}
42 ✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc