GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.6% 289 / 0 / 296
Functions: 97.8% 88 / 0 / 90
Branches: 62.7% 252 / 0 / 402

src/symboltablebuilder/QualType.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "QualType.h"
4
5 #include <sstream>
6
7 #include <SourceFile.h>
8 #include <ast/ASTNodes.h>
9 #include <global/TypeRegistry.h>
10 #include <model/GenericType.h>
11 #include <model/Struct.h>
12 #include <symboltablebuilder/Scope.h>
13 #include <symboltablebuilder/SymbolTableBuilder.h>
14 #include <symboltablebuilder/Type.h>
15 #include <typechecker/FunctionManager.h>
16 #include <typechecker/InterfaceManager.h>
17 #include <typechecker/StructManager.h>
18
19 namespace spice::compiler {
20
21 1555348 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), qualifiers(TypeQualifiers::of(superType)) {}
22 1991 QualType::QualType(SuperType superType, const std::string &subType)
23 1991 : type(TypeRegistry::getOrInsert(superType, subType)), qualifiers(TypeQualifiers::of(superType)) {}
24 76850 QualType::QualType(const Type *type, TypeQualifiers qualifiers) : type(type), qualifiers(qualifiers) {}
25
26 /**
27 * Get the super type of the underlying type
28 *
29 * @return Super type
30 */
31 1165206 SuperType QualType::getSuperType() const { return type->getSuperType(); }
32
33 /**
34 * Get the subtype of the underlying type
35 *
36 * @return Subtype
37 */
38 334667 const std::string &QualType::getSubType() const { return type->getSubType(); }
39
40 /**
41 * Get the array size of the underlying type
42 *
43 * @return Array size
44 */
45 582 unsigned int QualType::getArraySize() const { return type->getArraySize(); }
46
47 /**
48 * Get the body scope of the underlying type
49 *
50 * @return Body scope
51 */
52 165744 Scope *QualType::getBodyScope() const { return type->getBodyScope(); }
53
54 /**
55 * Get the function parameter types of the underlying type
56 *
57 * @return Function parameter types
58 */
59 39 const QualType &QualType::getFunctionReturnType() const { return type->getFunctionReturnType(); }
60
61 /**
62 * Get the function parameter types of the underlying type
63 *
64 * @return Function parameter types
65 */
66 138 QualTypeList QualType::getFunctionParamTypes() const { return type->getFunctionParamTypes(); }
67
68 /**
69 * Get the function parameter and return types of the underlying type
70 *
71 * @return Function parameter and return types
72 */
73 62 const QualTypeList &QualType::getFunctionParamAndReturnTypes() const { return type->getFunctionParamAndReturnTypes(); }
74
75 /**
76 * Check if the underlying type has lambda captures
77 *
78 * @return Has lambda captures or not
79 */
80 151 bool QualType::hasLambdaCaptures() const { return type->hasLambdaCaptures(); }
81
82 /**
83 * Get the template types of the underlying type
84 *
85 * @return Template types
86 */
87 91754 const QualTypeList &QualType::getTemplateTypes() const { return type->getTemplateTypes(); }
88
89 /**
90 * Get the struct instance for a struct type
91 *
92 * @param node Accessing AST node
93 * @param templateTypes Custom set of template types
94 * @return Struct instance
95 */
96 18149 Struct *QualType::getStruct(const ASTNode *node, const QualTypeList &templateTypes) const {
97
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 18149 times.
18149 assert(is(TY_STRUCT));
98 18149 Scope *structDefScope = getBodyScope()->parent;
99 18149 const std::string &structName = getSubType();
100 18149 return StructManager::match(structDefScope, structName, templateTypes, node);
101 }
102
103 /**
104 * Get the struct instance for a struct type
105 *
106 * @param node Accessing AST node
107 * @return Struct instance
108 */
109 10391 Struct *QualType::getStruct(const ASTNode *node) const { return getStruct(node, type->getTemplateTypes()); }
110
111 /**
112 * Get the struct instance for a struct type
113 * Adopt information from the struct to this type.
114 *
115 * @param node Accessing AST node
116 * @param templateTypes Custom set of template types
117 * @return Struct instance
118 */
119 301 Struct *QualType::getStructAndAdjustType(const ASTNode *node, const QualTypeList &templateTypes) {
120 301 Struct *spiceStruct = getStruct(node, templateTypes);
121
2/4
✓ Branch 4 → 5 taken 301 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 301 times.
✗ Branch 5 → 9 not taken.
301 type = type->getWithBodyScope(spiceStruct->scope)->getWithTemplateTypes(spiceStruct->getTemplateTypes());
122 301 return spiceStruct;
123 }
124
125 /**
126 * Get the struct instance for a struct type
127 * Adopt information from the struct to this type.
128 *
129 * @param node Accessing AST node
130 * @return Struct instance
131 */
132 Struct *QualType::getStructAndAdjustType(const ASTNode *node) { return getStructAndAdjustType(node, type->getTemplateTypes()); }
133
134 /**
135 * Get the interface instance for an interface type
136 *
137 * @param node Accessing AST node
138 * @param templateTypes Custom set of template types
139 * @return Interface instance
140 */
141 1683 Interface *QualType::getInterface(const ASTNode *node, const QualTypeList &templateTypes) const {
142
2/4
✓ Branch 2 → 3 taken 1683 times.
✗ Branch 2 → 15 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1683 times.
1683 assert(is(TY_INTERFACE));
143
1/2
✓ Branch 5 → 6 taken 1683 times.
✗ Branch 5 → 15 not taken.
1683 Scope *interfaceDefScope = getBodyScope()->parent;
144
2/4
✓ Branch 6 → 7 taken 1683 times.
✗ Branch 6 → 15 not taken.
✓ Branch 7 → 8 taken 1683 times.
✗ Branch 7 → 15 not taken.
1683 const std::string structName = getSubType();
145
1/2
✓ Branch 8 → 9 taken 1683 times.
✗ Branch 8 → 13 not taken.
3366 return InterfaceManager::match(interfaceDefScope, structName, templateTypes, node);
146 1683 }
147
148 /**
149 * Get the interface instance for an interface type
150 *
151 * @param node Accessing AST node
152 * @return Interface instance
153 */
154 975 Interface *QualType::getInterface(const ASTNode *node) const { return getInterface(node, type->getTemplateTypes()); }
155
156 /**
157 * Check if the underlying type is of a certain super type
158 *
159 * @param superType Super type
160 * @return Is of super type or not
161 */
162 3542304 bool QualType::is(SuperType superType) const { return type->is(superType); }
163
164 /**
165 * Check if the underlying type is one of a list of super types
166 *
167 * @param superTypes List of super types
168 * @return Is one of the super types or not
169 */
170 728793 bool QualType::isOneOf(const std::initializer_list<SuperType> &superTypes) const { return type->isOneOf(superTypes); }
171
172 /**
173 * Check if the base type of the underlying type is a certain super type
174 *
175 * @param superType Super type
176 * @return Is base type or not
177 */
178 564725 bool QualType::isBase(SuperType superType) const { return type->isBase(superType); }
179
180 /**
181 * Check if the underlying type is a primitive type
182 * Note: enum types are mapped to int, so they are also count as primitive types.
183 *
184 * @return Primitive or not
185 */
186 1268 bool QualType::isPrimitive() const { return type->isPrimitive(); }
187
188 /**
189 * Check if the underlying type is an extended primitive type
190 * The definition of extended primitive types contains all primitive types plus the following:
191 * - structs
192 * - interfaces
193 * - functions/procedures
194 *
195 * @return Extended primitive or not
196 */
197 109289 bool QualType::isExtendedPrimitive() const { return type->isExtendedPrimitive(); }
198
199 /**
200 * Check if the underlying type is a pointer
201 *
202 * @return Pointer or not
203 */
204 403549 bool QualType::isPtr() const { return type->isPtr(); }
205
206 /**
207 * Check if the underlying type is a pointer to a certain super type
208 *
209 * @param superType Super type
210 * @return Pointer to super type or not
211 */
212
7/10
✓ Branch 2 → 3 taken 195287 times.
✗ Branch 2 → 12 not taken.
✓ Branch 3 → 4 taken 16390 times.
✓ Branch 3 → 8 taken 178897 times.
✓ Branch 4 → 5 taken 16390 times.
✗ Branch 4 → 12 not taken.
✓ Branch 5 → 6 taken 16390 times.
✗ Branch 5 → 12 not taken.
✓ Branch 6 → 7 taken 9385 times.
✓ Branch 6 → 8 taken 7005 times.
195287 bool QualType::isPtrTo(SuperType superType) const { return isPtr() && getContained().is(superType); }
213
214 /**
215 * Check if the underlying type is a reference
216 *
217 * @return Reference or not
218 */
219 573410 bool QualType::isRef() const { return type->isRef(); }
220
221 /**
222 * Check if the underlying type is a reference to a certain super type
223 *
224 * @param superType Super type
225 * @return Reference to super type or not
226 */
227 bool QualType::isRefTo(SuperType superType) const { return isRef() && getContained().is(superType); }
228
229 /**
230 * Check if the underlying type is an array
231 *
232 * @return Array or not
233 */
234 40291 bool QualType::isArray() const { return type->isArray(); }
235
236 /**
237 * Check if the underlying type is an array of a certain super type
238 *
239 * @param superType Super type
240 * @return Array of super type or not
241 */
242
2/10
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 12 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 8 taken 1 time.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 12 not taken.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 12 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
1 bool QualType::isArrayOf(SuperType superType) const { return isArray() && getContained().is(superType); }
243
244 /**
245 * Check if the underlying type is a const reference
246 *
247 * @return Const reference or not
248 */
249
4/4
✓ Branch 2 → 3 taken 967 times.
✓ Branch 2 → 6 taken 514 times.
✓ Branch 4 → 5 taken 753 times.
✓ Branch 4 → 6 taken 214 times.
1481 bool QualType::isConstRef() const { return qualifiers.isConst && isRef(); }
250
251 /**
252 * Check if the current type is an iterator
253 *
254 * @param node ASTNode
255 * @return Iterator or not
256 */
257 134 bool QualType::isIterator(const ASTNode *node) const {
258 // The type must be a struct that implements the iterator interface
259
3/4
✓ Branch 2 → 3 taken 134 times.
✗ Branch 2 → 47 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 133 times.
134 if (!is(TY_STRUCT))
260 1 return false;
261
262
2/4
✓ Branch 7 → 8 taken 133 times.
✗ Branch 7 → 30 not taken.
✓ Branch 8 → 9 taken 133 times.
✗ Branch 8 → 28 not taken.
133 const QualType genericType(TY_GENERIC, "T");
263 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
264
3/6
✓ Branch 13 → 14 taken 133 times.
✗ Branch 13 → 42 not taken.
✓ Branch 16 → 17 taken 133 times.
✗ Branch 16 → 36 not taken.
✓ Branch 17 → 18 taken 133 times.
✗ Branch 17 → 34 not taken.
532 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERATOR_INTERFACE, data, {genericType});
265
1/2
✓ Branch 22 → 23 taken 133 times.
✗ Branch 22 → 47 not taken.
133 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
266
1/2
✓ Branch 24 → 25 taken 133 times.
✗ Branch 24 → 47 not taken.
133 return doesImplement(iteratorQualType, node);
267 }
268
269 /**
270 * Check if the current type is an iterable
271 * - Arrays are always considered iterable
272 * - Otherwise the type must be a struct that implements the iterator interface
273 *
274 * @param node ASTNode
275 * @return Iterable or not
276 */
277 136 bool QualType::isIterable(const ASTNode *node) const {
278 // Arrays are always considered iterable
279
3/4
✓ Branch 2 → 3 taken 136 times.
✗ Branch 2 → 50 not taken.
✓ Branch 3 → 4 taken 8 times.
✓ Branch 3 → 5 taken 128 times.
136 if (isArray())
280 8 return true;
281 // Otherwise the type must be a struct that implements the iterator interface
282
3/4
✓ Branch 5 → 6 taken 128 times.
✗ Branch 5 → 50 not taken.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 127 times.
128 if (!is(TY_STRUCT))
283 1 return false;
284
285
2/4
✓ Branch 10 → 11 taken 127 times.
✗ Branch 10 → 33 not taken.
✓ Branch 11 → 12 taken 127 times.
✗ Branch 11 → 31 not taken.
127 const QualType genericType(TY_GENERIC, "T");
286 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
287
3/6
✓ Branch 16 → 17 taken 127 times.
✗ Branch 16 → 45 not taken.
✓ Branch 19 → 20 taken 127 times.
✗ Branch 19 → 39 not taken.
✓ Branch 20 → 21 taken 127 times.
✗ Branch 20 → 37 not taken.
508 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERABLE_INTERFACE, data, {genericType});
288
1/2
✓ Branch 25 → 26 taken 127 times.
✗ Branch 25 → 50 not taken.
127 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
289
1/2
✓ Branch 27 → 28 taken 127 times.
✗ Branch 27 → 50 not taken.
127 return doesImplement(iteratorQualType, node);
290 }
291
292 /**
293 * Check if the current type is a string object
294 *
295 * @return String object or not
296 */
297 752 bool QualType::isStringObj() const {
298
4/6
✓ Branch 3 → 4 taken 122 times.
✓ Branch 3 → 10 taken 630 times.
✓ Branch 6 → 7 taken 122 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 122 times.
✗ Branch 8 → 10 not taken.
752 return is(TY_STRUCT) && getSubType() == STROBJ_NAME && getBodyScope()->sourceFile->isStdFile;
299 }
300
301 /**
302 * Check if the current type is an error object
303 *
304 * @return Error object or not
305 */
306 775 bool QualType::isErrorObj() const {
307
4/6
✓ Branch 3 → 4 taken 774 times.
✓ Branch 3 → 10 taken 1 time.
✓ Branch 6 → 7 taken 774 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 774 times.
✗ Branch 8 → 10 not taken.
775 return is(TY_STRUCT) && getSubType() == ERROBJ_NAME && getBodyScope()->sourceFile->isStdFile;
308 }
309
310 /**
311 * Check if the current type has any generic parts
312 *
313 * @return Generic parts or not
314 */
315 410029 bool QualType::hasAnyGenericParts() const { return type->hasAnyGenericParts(); }
316
317 /**
318 * Check if constructing an instance of the current type would require calling a ctor.
319 * If this function return true, the type does not need to be constructed.
320 *
321 * @param node Accessing ASTNode
322 * @return Trivially constructible or not
323 */
324 390 bool QualType::isTriviallyConstructible(const ASTNode *node) const {
325 // Heap-allocated values require manual allocation, which is done in the default/explicit ctor
326
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 389 times.
390 if (qualifiers.isHeap)
327 1 return false;
328
329 // References can't be default initialized
330
2/2
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 7 taken 386 times.
389 if (isRef())
331 3 return false;
332
333 // In case of an array, the item type is determining the construction triviality
334
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 13 taken 386 times.
386 if (isArray())
335 return getBase().isTriviallyConstructible(node);
336
337 // In case of a struct, the member types determine the construction triviality
338
2/2
✓ Branch 14 → 15 taken 315 times.
✓ Branch 14 → 34 taken 71 times.
386 if (is(TY_STRUCT)) {
339 // If the struct has a ctor, it is a non-trivially constructible one
340
1/2
✓ Branch 15 → 16 taken 315 times.
✗ Branch 15 → 37 not taken.
315 const Struct *spiceStruct = getStruct(node);
341
3/4
✓ Branch 16 → 17 taken 315 times.
✗ Branch 16 → 37 not taken.
✓ Branch 17 → 18 taken 248 times.
✓ Branch 17 → 19 taken 67 times.
315 if (FunctionManager::hasAnyNonCopyCtor(spiceStruct->scope))
342 248 return false;
343
344 // If the struct emits a vtable, it is non-trivially constructible, because the vtable needs to be initialized in the ctor
345
1/2
✓ Branch 19 → 20 taken 67 times.
✗ Branch 19 → 21 not taken.
67 const auto *structDefNode = spice_pointer_cast<StructDefNode *>(spiceStruct->declNode);
346
2/2
✓ Branch 26 → 27 taken 1 time.
✓ Branch 26 → 28 taken 66 times.
67 if (structDefNode->emitVTable)
347 1 return false;
348
349 // If any field has a default value, the struct is non-trivially constructible
350 90 const auto pred1 = [&](const FieldNode *fieldNode) { return fieldNode->defaultValue != nullptr; };
351
3/4
✓ Branch 28 → 29 taken 66 times.
✗ Branch 28 → 37 not taken.
✓ Branch 29 → 30 taken 5 times.
✓ Branch 29 → 31 taken 61 times.
66 if (std::ranges::any_of(structDefNode->fields, pred1))
352 5 return false;
353
354 // Check if all member types are trivially constructible
355 85 const auto pred2 = [&](const QualType &fieldType) { return fieldType.isTriviallyConstructible(node); };
356
1/2
✓ Branch 31 → 32 taken 61 times.
✗ Branch 31 → 37 not taken.
61 return std::ranges::all_of(spiceStruct->fieldTypes, pred2);
357 }
358
359 71 return true;
360 }
361
362 /**
363 * Check if copying an instance of the current type would require a call to the copy ctor.
364 * If this function return true, the type can be copied by calling memcpy.
365 *
366 * @param node Accessing ASTNode
367 * @return Trivially copyable or not
368 */
369 1548 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
370 // Heap-allocated values may not be copied via memcpy
371
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1548 times.
1548 if (qualifiers.isHeap)
372 return false;
373
374 // In case of an array, the item type is determining the copy triviality
375
2/2
✓ Branch 5 → 6 taken 8 times.
✓ Branch 5 → 10 taken 1540 times.
1548 if (isArray())
376
2/4
✓ Branch 6 → 7 taken 8 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 8 times.
✗ Branch 7 → 21 not taken.
8 return getBase().isTriviallyCopyable(node);
377
378 // In case of a struct, the member types determine the copy triviality
379
2/2
✓ Branch 11 → 12 taken 674 times.
✓ Branch 11 → 19 taken 866 times.
1540 if (is(TY_STRUCT)) {
380 // If the struct has a copy ctor, it is a non-trivially copyable one
381
1/2
✓ Branch 12 → 13 taken 674 times.
✗ Branch 12 → 22 not taken.
674 const Struct *spiceStruct = getStruct(node);
382
3/4
✓ Branch 13 → 14 taken 674 times.
✗ Branch 13 → 22 not taken.
✓ Branch 14 → 15 taken 222 times.
✓ Branch 14 → 16 taken 452 times.
674 if (FunctionManager::hasCopyCtor(spiceStruct->scope))
383 222 return false;
384
385 // Check if all member types are trivially copyable
386 789 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
387
1/2
✓ Branch 16 → 17 taken 452 times.
✗ Branch 16 → 22 not taken.
452 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
388 }
389
390 866 return true;
391 }
392
393 /**
394 * Check if destructing an instance of the current type would require calling a dtor.
395 * If this function return true, the type does not need to be destructed.
396 *
397 * @param node Accessing ASTNode
398 * @return Trivially destructible or not
399 */
400 9034 bool QualType::isTriviallyDestructible(const ASTNode *node) const {
401 // Heap-allocated values require manual de-allocation, which is done in the default/explicit dtor
402
2/2
✓ Branch 2 → 3 taken 581 times.
✓ Branch 2 → 4 taken 8453 times.
9034 if (qualifiers.isHeap)
403 581 return false;
404
405 // In case of an array, the item type is determining the destructing triviality
406
2/2
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 10 taken 8448 times.
8453 if (isArray())
407
2/4
✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 5 times.
✗ Branch 7 → 21 not taken.
5 return getBase().isTriviallyDestructible(node);
408
409 // In case of a struct, the member types determine the destructing triviality
410
2/2
✓ Branch 11 → 12 taken 4669 times.
✓ Branch 11 → 19 taken 3779 times.
8448 if (is(TY_STRUCT)) {
411 // If the struct has a dtor, it is a non-trivially destructible one
412
1/2
✓ Branch 12 → 13 taken 4669 times.
✗ Branch 12 → 22 not taken.
4669 const Struct *spiceStruct = getStruct(node);
413
3/4
✓ Branch 13 → 14 taken 4669 times.
✗ Branch 13 → 22 not taken.
✓ Branch 14 → 15 taken 1893 times.
✓ Branch 14 → 16 taken 2776 times.
4669 if (FunctionManager::hasDtor(spiceStruct->scope))
414 1893 return false;
415
416 // Check if all member types are trivially destructible
417 4882 const auto pred = [&](const QualType &fieldType) {
418 4882 return fieldType.isTriviallyDestructible(node);
419 2776 }; // NOLINT(*-no-recursion)
420
1/2
✓ Branch 16 → 17 taken 2776 times.
✗ Branch 16 → 22 not taken.
2776 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
421 }
422
423 3779 return true;
424 }
425
426 /**
427 * Check if the current type implements the given interface type
428 *
429 * @param implementedInterfaceType Interface type
430 * @param node Accessing ASTNode
431 * @return Struct implements interface or not
432 */
433 261 bool QualType::doesImplement(const QualType &implementedInterfaceType, const ASTNode *node) const {
434
2/4
✓ Branch 3 → 4 taken 261 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 261 times.
✗ Branch 5 → 7 not taken.
261 assert(is(TY_STRUCT) && implementedInterfaceType.is(TY_INTERFACE));
435 261 const Struct *spiceStruct = getStruct(node);
436
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 261 times.
261 assert(spiceStruct != nullptr);
437 261 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
438
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 261 times.
261 assert(interfaceType.is(TY_INTERFACE));
439 261 return implementedInterfaceType.matches(interfaceType, false, false, true);
440 261 });
441 }
442
443 /**
444 * Check if a certain input type can be bound (assigned) to the current type->
445 *
446 * @param inputType Qualified type, which should be bound to the current type
447 * @param isTemporary Is the input type a temporary type
448 * @return Can be bound or not
449 */
450 17643 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
451
8/8
✓ Branch 2 → 3 taken 5831 times.
✓ Branch 2 → 9 taken 11812 times.
✓ Branch 4 → 5 taken 5557 times.
✓ Branch 4 → 9 taken 274 times.
✓ Branch 6 → 7 taken 358 times.
✓ Branch 6 → 9 taken 5199 times.
✓ Branch 8 → 9 taken 356 times.
✓ Branch 8 → 10 taken 2 times.
17643 return !isTemporary || inputType.type->isRef() || !type->isRef() || isConstRef();
452 }
453
454 /**
455 * Check for the matching compatibility of two types.
456 * Useful for struct and function matching as well as assignment type validation and function arg matching.
457 *
458 * @param otherType Type to compare against
459 * @param ignoreArraySize Ignore array sizes
460 * @param ignoreQualifiers Ignore qualifiers, except for pointer and reference types
461 * @param allowConstify Match when the types are the same, but the lhs type is more const restrictive than the rhs type
462 * @return Matching or not
463 */
464 139133 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
465 // Special case: string is equivalent to const char*
466
6/8
✓ Branch 3 → 4 taken 20791 times.
✓ Branch 3 → 9 taken 118342 times.
✓ Branch 5 → 6 taken 1536 times.
✓ Branch 5 → 9 taken 19255 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1536 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 139133 times.
139133 if (is(TY_STRING) && otherType.isPtrTo(TY_CHAR) && otherType.isConst())
467 return true;
468
4/8
✓ Branch 13 → 14 taken 6639 times.
✓ Branch 13 → 19 taken 132494 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 19 taken 6639 times.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 139133 times.
139133 if (isPtrTo(TY_CHAR) && isConst() && otherType.is(TY_STRING))
469 return true;
470
471 // Compare type
472
2/2
✓ Branch 23 → 24 taken 56108 times.
✓ Branch 23 → 25 taken 83025 times.
139133 if (!type->matches(otherType.type, ignoreArraySize))
473 56108 return false;
474
475 // Ignore or compare qualifiers
476
4/4
✓ Branch 25 → 26 taken 15130 times.
✓ Branch 25 → 28 taken 67895 times.
✓ Branch 27 → 28 taken 14952 times.
✓ Branch 27 → 29 taken 178 times.
83025 return ignoreQualifiers || qualifiers.match(otherType.qualifiers, allowConstify);
477 }
478
479 /**
480 * Check for the matching compatibility of two types in terms of interface implementation.
481 * Useful for function matching as well as assignment type validation and function arg matching.
482 *
483 * @param structType Type to compare against
484 * @return Matching or not
485 */
486 65522 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
487
8/10
✓ Branch 2 → 3 taken 65522 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 278 times.
✓ Branch 3 → 6 taken 65244 times.
✓ Branch 4 → 5 taken 278 times.
✗ Branch 4 → 17 not taken.
✓ Branch 5 → 6 taken 41 times.
✓ Branch 5 → 7 taken 237 times.
✓ Branch 8 → 9 taken 65285 times.
✓ Branch 8 → 10 taken 237 times.
65522 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
488 65285 return false;
489
490 // Check if the rhs is a struct type that implements the lhs interface type
491
1/2
✓ Branch 10 → 11 taken 237 times.
✗ Branch 10 → 17 not taken.
237 const Struct *spiceStruct = structType.getStruct(nullptr);
492
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 237 times.
237 assert(spiceStruct != nullptr);
493 233 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
494
1/2
✓ Branch 13 → 14 taken 237 times.
✗ Branch 13 → 17 not taken.
237 return std::ranges::any_of(spiceStruct->interfaceTypes, pred);
495 }
496
497 /**
498 * Check if the current type is the same container type as another type.
499 * Container types include arrays, pointers, and references.
500 *
501 * @param other Other type
502 * @return Same container type or not
503 */
504 2975 bool QualType::isSameContainerTypeAs(const QualType &other) const { return type->isSameContainerTypeAs(other.type); }
505
506 /**
507 * Check if the current type is a self-referencing struct type
508 *
509 * @return Self-referencing struct type or not
510 */
511 27391 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
512
2/2
✓ Branch 3 → 4 taken 20050 times.
✓ Branch 3 → 5 taken 7341 times.
27391 if (!is(TY_STRUCT))
513 20050 return false;
514
515 // If no type was set by a previous iteration, we set it to the current type
516
2/2
✓ Branch 5 → 6 taken 5245 times.
✓ Branch 5 → 7 taken 2096 times.
7341 if (typeToCompareWith == nullptr)
517 5245 typeToCompareWith = this;
518
519 7341 Scope *baseTypeBodyScope = getBodyScope();
520
2/2
✓ Branch 24 → 9 taken 22033 times.
✓ Branch 24 → 25 taken 6935 times.
28968 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
521
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 22033 times.
22033 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
522 22033 const QualType &fieldType = field->getQualType();
523 // Check if the base type of the field matches with the current type, which is also a base type
524 // If yes, this is a self-referencing struct type
525
3/4
✓ Branch 15 → 16 taken 22033 times.
✗ Branch 15 → 27 not taken.
✓ Branch 17 → 18 taken 406 times.
✓ Branch 17 → 19 taken 21627 times.
22033 if (fieldType.getBase() == *typeToCompareWith)
526 406 return true;
527
528 // If the field is a struct, check if it is a self-referencing struct type
529
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 21627 times.
21627 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
530 return true;
531 }
532 6935 return false;
533 }
534
535 /**
536 * Check if the given generic type list has a substantiation for the current (generic) type
537 *
538 * @param genericTypeList Generic type list
539 * @return Has substantiation or not
540 */
541 28697 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
542
1/2
✓ Branch 2 → 3 taken 28697 times.
✗ Branch 2 → 19 not taken.
28697 const QualType baseType = getBase();
543 // Check if the symbol type itself is generic
544
3/4
✓ Branch 3 → 4 taken 28697 times.
✗ Branch 3 → 19 not taken.
✓ Branch 4 → 5 taken 5447 times.
✓ Branch 4 → 7 taken 23250 times.
28697 if (baseType.is(TY_GENERIC)) {
545
1/2
✓ Branch 5 → 6 taken 5447 times.
✗ Branch 5 → 19 not taken.
5447 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
546
2/2
✓ Branch 3 → 4 taken 5439 times.
✓ Branch 3 → 5 taken 1006 times.
6445 if (baseType.matches(t, true, true, true)) {
547 5439 t.used = true;
548 5439 return true;
549 }
550 1006 return false;
551 5447 });
552 }
553
554 // If the type is non-generic check template types
555 23250 bool covered = true;
556 // Check template types
557
1/2
✓ Branch 7 → 8 taken 23250 times.
✗ Branch 7 → 19 not taken.
23250 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
558 2324 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
559 2324 return templateType.isCoveredByGenericTypeList(genericTypeList);
560 23250 };
561
1/2
✓ Branch 8 → 9 taken 23250 times.
✗ Branch 8 → 19 not taken.
23250 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
562
563 // If function/procedure, check param and return types
564
3/4
✓ Branch 9 → 10 taken 23250 times.
✗ Branch 9 → 17 not taken.
✓ Branch 10 → 11 taken 35 times.
✓ Branch 10 → 14 taken 23215 times.
23250 if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
565
1/2
✓ Branch 11 → 12 taken 35 times.
✗ Branch 11 → 18 not taken.
35 const QualTypeList &paramAndReturnTypes = baseType.getFunctionParamAndReturnTypes();
566 62 const auto innerPred = [&](const QualType &paramType) { // NOLINT(*-no-recursion)
567 62 return paramType.isCoveredByGenericTypeList(genericTypeList);
568 35 };
569
1/2
✓ Branch 12 → 13 taken 35 times.
✗ Branch 12 → 18 not taken.
35 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
570 }
571
572 23250 return covered;
573 }
574
575 /**
576 * Check if the current type needs de-allocation
577 *
578 * @return Needs de-allocation or not
579 */
580 1487 bool QualType::needsDeAllocation() const {
581
2/2
✓ Branch 3 → 4 taken 1412 times.
✓ Branch 3 → 5 taken 75 times.
1487 if (!isHeap())
582 1412 return false;
583 // We only need de-allocation, if we directly point to a heap-allocated type
584 // e.g. for heap TestStruct** we don't need to de-allocate, since it is a non-owning pointer to an owning pointer
585
2/4
✓ Branch 6 → 7 taken 75 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 75 times.
✗ Branch 8 → 10 not taken.
75 return isPtr() && !isPtrTo(TY_PTR);
586 }
587
588 /**
589 * Get the name of the symbol type as a string
590 *
591 * @param name Name stream
592 * @param withSize Include the array size for sized types
593 * @param ignorePublic Ignore any potential public qualifier
594 * @param withAliases Print aliases as is and not decompose them
595 */
596 586885 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
597 // Append the qualifiers
598
3/6
✓ Branch 2 → 3 taken 586885 times.
✗ Branch 2 → 31 not taken.
✓ Branch 3 → 4 taken 586885 times.
✗ Branch 3 → 31 not taken.
✓ Branch 4 → 5 taken 586885 times.
✗ Branch 4 → 31 not taken.
586885 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
599
5/6
✓ Branch 5 → 6 taken 371417 times.
✓ Branch 5 → 9 taken 215468 times.
✓ Branch 6 → 7 taken 130157 times.
✓ Branch 6 → 9 taken 241260 times.
✓ Branch 7 → 8 taken 130157 times.
✗ Branch 7 → 9 not taken.
586885 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
600
1/2
✓ Branch 8 → 9 taken 130157 times.
✗ Branch 8 → 32 not taken.
130157 name << "public ";
601
3/4
✓ Branch 9 → 10 taken 10 times.
✓ Branch 9 → 12 taken 586875 times.
✓ Branch 10 → 11 taken 10 times.
✗ Branch 10 → 12 not taken.
586885 if (qualifiers.isComposition && !defaultForSuperType.isComposition)
602
1/2
✓ Branch 11 → 12 taken 10 times.
✗ Branch 11 → 32 not taken.
10 name << "compose ";
603
8/8
✓ Branch 12 → 13 taken 74928 times.
✓ Branch 12 → 17 taken 511957 times.
✓ Branch 13 → 14 taken 73446 times.
✓ Branch 13 → 17 taken 1482 times.
✓ Branch 15 → 16 taken 45734 times.
✓ Branch 15 → 17 taken 27712 times.
✓ Branch 18 → 19 taken 45734 times.
✓ Branch 18 → 20 taken 541151 times.
586885 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
604
1/2
✓ Branch 19 → 20 taken 45734 times.
✗ Branch 19 → 32 not taken.
45734 name << "const ";
605
3/4
✓ Branch 20 → 21 taken 21823 times.
✓ Branch 20 → 23 taken 565062 times.
✓ Branch 21 → 22 taken 21823 times.
✗ Branch 21 → 23 not taken.
586885 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
606
1/2
✓ Branch 22 → 23 taken 21823 times.
✗ Branch 22 → 32 not taken.
21823 name << "heap ";
607
4/4
✓ Branch 23 → 24 taken 76069 times.
✓ Branch 23 → 26 taken 510816 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 26 taken 76068 times.
586885 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
608
1/2
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 32 not taken.
1 name << "signed ";
609
4/4
✓ Branch 26 → 27 taken 510816 times.
✓ Branch 26 → 29 taken 76069 times.
✓ Branch 27 → 28 taken 49067 times.
✓ Branch 27 → 29 taken 461749 times.
586885 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
610
1/2
✓ Branch 28 → 29 taken 49067 times.
✗ Branch 28 → 32 not taken.
49067 name << "unsigned ";
611
612 // Loop through all chain elements
613
1/2
✓ Branch 29 → 30 taken 586885 times.
✗ Branch 29 → 32 not taken.
586885 type->getName(name, withSize, ignorePublic, withAliases);
614 586885 }
615
616 /**
617 * Get the name of the symbol type as a string
618 *
619 * @param withSize Include the array size for sized types
620 * @param ignorePublic Ignore any potential public qualifier
621 * @param withAliases Print aliases as is and not decompose them
622 * @return Symbol type name
623 */
624 342999 std::string QualType::getName(bool withSize, bool ignorePublic, bool withAliases) const {
625
1/2
✓ Branch 2 → 3 taken 342999 times.
✗ Branch 2 → 11 not taken.
342999 std::stringstream name;
626
1/2
✓ Branch 3 → 4 taken 342999 times.
✗ Branch 3 → 9 not taken.
342999 getName(name, withSize, ignorePublic, withAliases);
627
1/2
✓ Branch 4 → 5 taken 342999 times.
✗ Branch 4 → 9 not taken.
685998 return name.str();
628 342999 }
629
630 /**
631 * Convert the type to an LLVM type
632 *
633 * @param sourceFile Source file
634 * @return LLVM type
635 */
636 391511 llvm::Type *QualType::toLLVMType(SourceFile *sourceFile) const { return sourceFile->getLLVMType(type); }
637
638 /**
639 * Retrieve the pointer type to this type
640 *
641 * @param node ASTNode
642 * @return New type
643 */
644 27629 QualType QualType::toPtr(const ASTNode *node) const {
645 27629 QualType newType = *this;
646
2/2
✓ Branch 2 → 3 taken 27627 times.
✓ Branch 2 → 5 taken 2 times.
27629 newType.type = type->toPtr(node);
647 27627 return newType;
648 }
649
650 /**
651 * Retrieve the reference type to this type
652 *
653 * @param node ASTNode
654 * @return New type
655 */
656 13889 QualType QualType::toRef(const ASTNode *node) const {
657 13889 QualType newType = *this;
658
1/2
✓ Branch 2 → 3 taken 13889 times.
✗ Branch 2 → 5 not taken.
13889 newType.type = type->toRef(node);
659 13889 return newType;
660 }
661
662 /**
663 * Retrieve the const reference type of this type
664 *
665 * @param node ASTNode
666 * @return New type
667 */
668 4208 QualType QualType::toConstRef(const ASTNode *node) const {
669
1/2
✓ Branch 2 → 3 taken 4208 times.
✗ Branch 2 → 6 not taken.
4208 QualType newType = toRef(node);
670 4208 newType.makeConst();
671 4208 return newType;
672 }
673
674 /**
675 * Retrieve the array type of this type
676 *
677 * @param node ASTNode
678 * @param size Array size
679 * @param skipDynCheck Skip dynamic check
680 * @return New type
681 */
682 239 QualType QualType::toArr(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
683 239 QualType newType = *this;
684
2/2
✓ Branch 2 → 3 taken 238 times.
✓ Branch 2 → 5 taken 1 time.
239 newType.type = type->toArr(node, size, skipDynCheck);
685 238 return newType;
686 }
687
688 /**
689 * Retrieve the non-const type of this type
690 *
691 * @return New type
692 */
693 2405 QualType QualType::toNonConst() const {
694 2405 QualType newType = *this;
695 2405 newType.qualifiers.isConst = false;
696 2405 return newType;
697 }
698
699 /**
700 * Retrieve the contained type of this type
701 * This works on pointers, arrays, references and strings (which alias with char*)
702 *
703 * @return New type
704 */
705 100765 QualType QualType::getContained() const {
706
2/4
✓ Branch 2 → 3 taken 100765 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 100765 times.
100765 assert(isOneOf({TY_PTR, TY_REF, TY_ARRAY, TY_STRING}));
707 100765 QualType newType = *this;
708
1/2
✓ Branch 5 → 6 taken 100765 times.
✗ Branch 5 → 9 not taken.
100765 newType.type = type->getContained();
709 100765 return newType;
710 }
711
712 /**
713 * Retrieve the base type of this type
714 *
715 * @return New type
716 */
717 1004373 QualType QualType::getBase() const {
718 1004373 QualType newType = *this;
719
1/2
✓ Branch 2 → 3 taken 1004373 times.
✗ Branch 2 → 5 not taken.
1004373 newType.type = type->getBase();
720 1004373 return newType;
721 }
722
723 /**
724 * Get aliased type for an alias type
725 *
726 * @param aliasEntry Entry of the alias definition
727 * @return Aliased type
728 */
729 1194 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
730
2/4
✓ Branch 2 → 3 taken 1194 times.
✗ Branch 2 → 18 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1194 times.
1194 assert(is(TY_ALIAS));
731 // Get type of aliased type container entry
732
1/2
✓ Branch 5 → 6 taken 1194 times.
✗ Branch 5 → 18 not taken.
1194 const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
733
1/2
✓ Branch 6 → 7 taken 1194 times.
✗ Branch 6 → 16 not taken.
1194 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
734
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 1194 times.
1194 assert(aliasedTypeContainerEntry != nullptr);
735
1/2
✓ Branch 11 → 12 taken 1194 times.
✗ Branch 11 → 16 not taken.
2388 return aliasedTypeContainerEntry->getQualType();
736 1194 }
737
738 /**
739 * Remove reference of this type, if it is a reference
740 *
741 * @return New type
742 */
743
2/2
✓ Branch 3 → 4 taken 6884 times.
✓ Branch 3 → 5 taken 239803 times.
246687 QualType QualType::removeReferenceWrapper() const { return isRef() ? getContained() : *this; }
744
745 /**
746 * Auto-dereference the given symbol type (peeling off all ptr/ref wrappers).
747 * This process is NOT equivalent with getBase() because getBase() also removes e.g. array wrappers
748 *
749 * @return New type
750 */
751 26568 QualType QualType::autoDeReference() const {
752 26568 QualType newType = *this;
753
3/4
✓ Branch 5 → 6 taken 49397 times.
✗ Branch 5 → 10 not taken.
✓ Branch 6 → 3 taken 22829 times.
✓ Branch 6 → 7 taken 26568 times.
49397 while (newType.isOneOf({TY_PTR, TY_REF}))
754
1/2
✓ Branch 3 → 4 taken 22829 times.
✗ Branch 3 → 9 not taken.
22829 newType = newType.getContained();
755 26568 return newType;
756 }
757
758 /**
759 * Replace the base type with another one
760 *
761 * @param newBaseType New base type
762 * @return New type
763 */
764 23029 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
765 // Create new type
766
1/2
✓ Branch 3 → 4 taken 23029 times.
✗ Branch 3 → 9 not taken.
23029 const Type *newType = type->replaceBase(newBaseType.getType());
767 // Create new qualifiers
768
1/2
✓ Branch 4 → 5 taken 23029 times.
✗ Branch 4 → 9 not taken.
23029 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
769 // Return the new qualified type
770 23029 return {newType, newQualifiers};
771 }
772
773 /**
774 * Retrieve the same type, but with lambda captures enabled
775 *
776 * @return Same type with lambda captures
777 */
778 40 QualType QualType::getWithLambdaCaptures(bool enabled /*=true*/) const {
779 // Create new type
780 40 const Type *newType = type->getWithLambdaCaptures(enabled);
781 // Return the new qualified type
782 40 return {newType, qualifiers};
783 }
784
785 /**
786 * Retrieve the same type, but with a new body scope
787 *
788 * @return Same type with body scope
789 */
790 26805 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
791 // Create new type
792 26805 const Type *newType = type->getWithBodyScope(bodyScope);
793 // Return the new qualified type
794 26805 return {newType, qualifiers};
795 }
796
797 /**
798 * Retrieve the same type, but with new template types
799 *
800 * @param templateTypes New template types
801 * @return Same type with new template types
802 */
803 4411 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
804 // Create new type
805 4411 const Type *newType = type->getWithTemplateTypes(templateTypes);
806 // Return the new qualified type
807 4411 return {newType, qualifiers};
808 }
809
810 /**
811 * Retrieve the same type, but with new base template types
812 *
813 * @param templateTypes New base template types
814 * @return Same type with new base template types
815 */
816 5764 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
817 // Create new type
818 5764 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
819 // Return the new qualified type
820 5764 return {newType, qualifiers};
821 }
822
823 /**
824 * Retrieve the same type, but with new function parameter and return types
825 *
826 * @param paramAndReturnTypes New parameter types
827 * @return Same type with new parameter types
828 */
829 15452 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
830 // Create new type
831 15452 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
832 // Return the new qualified type
833 15452 return {newType, qualifiers};
834 }
835
836 15431 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
837
1/2
✓ Branch 2 → 3 taken 15431 times.
✗ Branch 2 → 15 not taken.
15431 QualTypeList paramAndReturnTypes = paramTypes;
838
1/2
✓ Branch 5 → 6 taken 15431 times.
✗ Branch 5 → 11 not taken.
15431 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
839
1/2
✓ Branch 6 → 7 taken 15431 times.
✗ Branch 6 → 13 not taken.
30862 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
840 15431 }
841
842 /**
843 * Check if the current type is const
844 *
845 * Examples for const types:
846 * - const int
847 * - const TestStruct
848 * - const string
849 *
850 * Examples for non-const types:
851 * - double (reason: not marked const)
852 * - const int* (reason: pointer to const int is not const itself)
853 * - const TestStruct& (reason: reference to const TestStruct is not const itself)
854 *
855 * @return Is const or not
856 */
857
4/4
✓ Branch 3 → 4 taken 32825 times.
✓ Branch 3 → 6 taken 11573 times.
✓ Branch 4 → 5 taken 5252 times.
✓ Branch 4 → 6 taken 27573 times.
44398 bool QualType::isConst() const { return isExtendedPrimitive() && qualifiers.isConst; }
858
859 /**
860 * Check if the current type is marked signed
861 *
862 * @return Is signed or not
863 */
864 34891 bool QualType::isSigned() const {
865
2/4
✓ Branch 2 → 3 taken 34891 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 34891 times.
34891 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
866 34891 return qualifiers.isSigned;
867 }
868
869 /**
870 * Check if the current type is marked unsigned
871 *
872 * @return Is unsigned or not
873 */
874 2 bool QualType::isUnsigned() const {
875
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
876 2 return qualifiers.isUnsigned;
877 }
878
879 /**
880 * Check if the current type is marked inline
881 *
882 * @return Is inline or not
883 */
884 12282 bool QualType::isInline() const {
885
2/4
✓ Branch 2 → 3 taken 12282 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 12282 times.
12282 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
886 12282 return qualifiers.isInline;
887 }
888
889 /**
890 * Check if the current type is marked public
891 *
892 * @return Is public or not
893 */
894 25765 bool QualType::isPublic() const {
895
5/8
✓ Branch 2 → 3 taken 25765 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 24342 times.
✓ Branch 3 → 7 taken 1423 times.
✓ Branch 4 → 5 taken 24342 times.
✗ Branch 4 → 9 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 24342 times.
25765 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
896 25765 return qualifiers.isPublic;
897 }
898
899 /**
900 * Check if the current type is marked heap
901 *
902 * @return Is heap or not
903 */
904 14462 bool QualType::isHeap() const { return qualifiers.isHeap; }
905
906 /**
907 * Check if the current type is marked as composition
908 *
909 * @return Is composition or not
910 */
911 105 bool QualType::isComposition() const { return qualifiers.isComposition; }
912
913 /**
914 * Make the current type const
915 *
916 * @param isConst Is const or not
917 */
918 4774 void QualType::makeConst(bool isConst) { qualifiers.isConst = isConst; }
919
920 /**
921 * Make the current type unsigned
922 *
923 * @param isUnsigned Is unsigned or not
924 */
925 27 void QualType::makeUnsigned(bool isUnsigned) {
926
2/4
✓ Branch 2 → 3 taken 27 times.
✗ Branch 2 → 6 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 27 times.
27 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
927 27 qualifiers.isSigned = !isUnsigned;
928 27 qualifiers.isUnsigned = isUnsigned;
929 27 }
930
931 /**
932 * Make the current type public
933 *
934 * @param isPublic Is public or not
935 */
936 415 void QualType::makePublic(bool isPublic) {
937
4/8
✓ Branch 2 → 3 taken 415 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 415 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 415 times.
✗ Branch 4 → 8 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 415 times.
415 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
938 415 qualifiers.isPublic = isPublic;
939 415 }
940
941 /**
942 * Make the current type heap
943 *
944 * @param isHeap Is heap or not
945 */
946 89 void QualType::makeHeap(bool isHeap) { qualifiers.isHeap = isHeap; }
947
948 /**
949 * Check if two types are equal
950 *
951 * @param lhs Left-hand side type
952 * @param rhs Right-hand side type
953 * @return Equal or not
954 */
955 570661 bool operator==(const QualType &lhs, const QualType &rhs) { return lhs.type == rhs.type; }
956
957 /**
958 * Check if two types are not equal
959 *
960 * @param lhs Left-hand side type
961 * @param rhs Right-hand side type
962 * @return Not equal or not
963 */
964 130661 bool operator!=(const QualType &lhs, const QualType &rhs) { return !(lhs == rhs); }
965
966 /**
967 * Remove pointers / arrays / references if both types have them as far as possible.
968 *
969 * @param typeA Candidate type
970 * @param typeB Requested type
971 */
972 1250 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
973
974 /**
975 * Remove pointers / arrays / references if both types have them as far as possible.
976 * Furthermore, remove reference wrappers if possible.
977 *
978 * @param typeA Candidate type
979 * @param typeB Requested type
980 */
981 101199 void QualType::unwrapBothWithRefWrappers(QualType &typeA, QualType &typeB) {
982 101199 Type::unwrapBothWithRefWrappers(typeA.type, typeB.type);
983 101199 }
984
985 } // namespace spice::compiler
986