GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.7% 296 / 0 / 303
Functions: 97.8% 88 / 0 / 90
Branches: 62.3% 258 / 0 / 414

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 5400321 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), qualifiers(TypeQualifiers::of(superType)) {}
22 1869 QualType::QualType(SuperType superType, const std::string &subType)
23 1869 : type(TypeRegistry::getOrInsert(superType, subType)), qualifiers(TypeQualifiers::of(superType)) {}
24 70458 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 1021138 SuperType QualType::getSuperType() const { return type->getSuperType(); }
32
33 /**
34 * Get the subtype of the underlying type
35 *
36 * @return Subtype
37 */
38 302610 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 572 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 137163 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 140 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 54 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 145 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 84298 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 16626 Struct *QualType::getStruct(const ASTNode *node, const QualTypeList &templateTypes) const {
97
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 16626 times.
16626 assert(is(TY_STRUCT));
98 16626 Scope *structDefScope = getBodyScope()->parent;
99 16626 const std::string &structName = getSubType();
100 16626 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 9466 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 295 Struct *QualType::getStructAndAdjustType(const ASTNode *node, const QualTypeList &templateTypes) {
120 295 Struct *spiceStruct = getStruct(node, templateTypes);
121
2/4
✓ Branch 4 → 5 taken 295 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 295 times.
✗ Branch 5 → 9 not taken.
295 type = type->getWithBodyScope(spiceStruct->scope)->getWithTemplateTypes(spiceStruct->getTemplateTypes());
122 295 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 1416 Interface *QualType::getInterface(const ASTNode *node, const QualTypeList &templateTypes) const {
142
2/4
✓ Branch 2 → 3 taken 1416 times.
✗ Branch 2 → 15 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1416 times.
1416 assert(is(TY_INTERFACE));
143
1/2
✓ Branch 5 → 6 taken 1416 times.
✗ Branch 5 → 15 not taken.
1416 Scope *interfaceDefScope = getBodyScope()->parent;
144
2/4
✓ Branch 6 → 7 taken 1416 times.
✗ Branch 6 → 15 not taken.
✓ Branch 7 → 8 taken 1416 times.
✗ Branch 7 → 15 not taken.
1416 const std::string structName = getSubType();
145
1/2
✓ Branch 8 → 9 taken 1416 times.
✗ Branch 8 → 13 not taken.
2832 return InterfaceManager::match(interfaceDefScope, structName, templateTypes, node);
146 1416 }
147
148 /**
149 * Get the interface instance for an interface type
150 *
151 * @param node Accessing AST node
152 * @return Interface instance
153 */
154 812 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 3395169 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 676089 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 484455 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 1193 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 99467 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 374659 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 181498 times.
✗ Branch 2 → 12 not taken.
✓ Branch 3 → 4 taken 14689 times.
✓ Branch 3 → 8 taken 166809 times.
✓ Branch 4 → 5 taken 14689 times.
✗ Branch 4 → 12 not taken.
✓ Branch 5 → 6 taken 14689 times.
✗ Branch 5 → 12 not taken.
✓ Branch 6 → 7 taken 8378 times.
✓ Branch 6 → 8 taken 6311 times.
181498 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 525214 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 37068 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 350 times.
✓ Branch 2 → 6 taken 283 times.
✓ Branch 4 → 5 taken 346 times.
✓ Branch 4 → 6 taken 4 times.
633 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 119 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 119 times.
✗ Branch 2 → 47 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 118 times.
119 if (!is(TY_STRUCT))
260 1 return false;
261
262
2/4
✓ Branch 7 → 8 taken 118 times.
✗ Branch 7 → 30 not taken.
✓ Branch 8 → 9 taken 118 times.
✗ Branch 8 → 28 not taken.
118 const QualType genericType(TY_GENERIC, "T");
263 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
264
3/6
✓ Branch 13 → 14 taken 118 times.
✗ Branch 13 → 42 not taken.
✓ Branch 16 → 17 taken 118 times.
✗ Branch 16 → 36 not taken.
✓ Branch 17 → 18 taken 118 times.
✗ Branch 17 → 34 not taken.
472 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERATOR_INTERFACE, data, {genericType});
265
1/2
✓ Branch 22 → 23 taken 118 times.
✗ Branch 22 → 47 not taken.
118 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
266
1/2
✓ Branch 24 → 25 taken 118 times.
✗ Branch 24 → 47 not taken.
118 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 121 bool QualType::isIterable(const ASTNode *node) const {
278 // Arrays are always considered iterable
279
3/4
✓ Branch 2 → 3 taken 121 times.
✗ Branch 2 → 50 not taken.
✓ Branch 3 → 4 taken 8 times.
✓ Branch 3 → 5 taken 113 times.
121 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 113 times.
✗ Branch 5 → 50 not taken.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 112 times.
113 if (!is(TY_STRUCT))
283 1 return false;
284
285
2/4
✓ Branch 10 → 11 taken 112 times.
✗ Branch 10 → 33 not taken.
✓ Branch 11 → 12 taken 112 times.
✗ Branch 11 → 31 not taken.
112 const QualType genericType(TY_GENERIC, "T");
286 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
287
3/6
✓ Branch 16 → 17 taken 112 times.
✗ Branch 16 → 45 not taken.
✓ Branch 19 → 20 taken 112 times.
✗ Branch 19 → 39 not taken.
✓ Branch 20 → 21 taken 112 times.
✗ Branch 20 → 37 not taken.
448 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERABLE_INTERFACE, data, {genericType});
288
1/2
✓ Branch 25 → 26 taken 112 times.
✗ Branch 25 → 50 not taken.
112 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
289
1/2
✓ Branch 27 → 28 taken 112 times.
✗ Branch 27 → 50 not taken.
112 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 713 bool QualType::isStringObj() const {
298
4/6
✓ Branch 3 → 4 taken 122 times.
✓ Branch 3 → 10 taken 591 times.
✓ Branch 6 → 7 taken 122 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 122 times.
✗ Branch 8 → 10 not taken.
713 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 754 bool QualType::isErrorObj() const {
307
3/6
✓ Branch 3 → 4 taken 754 times.
✗ Branch 3 → 10 not taken.
✓ Branch 6 → 7 taken 754 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 754 times.
✗ Branch 8 → 10 not taken.
754 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 370927 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 367 bool QualType::isTriviallyConstructible(const ASTNode *node) const {
325 // Heap-allocated values require manual allocation, which is done in the default/explicit ctor
326
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 367 times.
367 if (qualifiers.isHeap)
327 return false;
328
329 // References can't be default initialized
330
2/2
✓ Branch 5 → 6 taken 13 times.
✓ Branch 5 → 7 taken 354 times.
367 if (isRef())
331 13 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 354 times.
354 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 278 times.
✓ Branch 14 → 41 taken 76 times.
354 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 278 times.
✗ Branch 15 → 53 not taken.
278 const Struct *spiceStruct = getStruct(node);
341
2/4
✓ Branch 19 → 20 taken 278 times.
✗ Branch 19 → 46 not taken.
✓ Branch 20 → 21 taken 278 times.
✗ Branch 20 → 44 not taken.
834 const Function *ctor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, {}, true);
342
2/2
✓ Branch 24 → 25 taken 163 times.
✓ Branch 24 → 26 taken 115 times.
278 if (ctor != nullptr)
343 163 return false;
344
345 // If the struct emits a vtable, it is non-trivially constructible, because the vtable needs to be initialized in the ctor
346
1/2
✓ Branch 26 → 27 taken 115 times.
✗ Branch 26 → 28 not taken.
115 const auto *structDefNode = spice_pointer_cast<StructDefNode *>(spiceStruct->declNode);
347
2/2
✓ Branch 33 → 34 taken 32 times.
✓ Branch 33 → 35 taken 83 times.
115 if (structDefNode->emitVTable)
348 32 return false;
349
350 // If any field has a default value, the struct is non-trivially constructible
351 235 const auto pred1 = [&](const FieldNode *fieldNode) { return fieldNode->defaultValue != nullptr; };
352
3/4
✓ Branch 35 → 36 taken 83 times.
✗ Branch 35 → 53 not taken.
✓ Branch 36 → 37 taken 16 times.
✓ Branch 36 → 38 taken 67 times.
83 if (std::ranges::any_of(structDefNode->fields, pred1))
353 16 return false;
354
355 // Check if all member types are trivially constructible
356 101 const auto pred2 = [&](const QualType &fieldType) { return fieldType.isTriviallyConstructible(node); };
357
1/2
✓ Branch 38 → 39 taken 67 times.
✗ Branch 38 → 53 not taken.
67 return std::ranges::all_of(spiceStruct->fieldTypes, pred2);
358 }
359
360 76 return true;
361 }
362
363 /**
364 * Check if copying an instance of the current type would require a call to the copy ctor.
365 * If this function return true, the type can be copied by calling memcpy.
366 *
367 * @param node Accessing ASTNode
368 * @return Trivially copyable or not
369 */
370 1391 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
371 // Heap-allocated values may not be copied via memcpy
372
2/2
✓ Branch 2 → 3 taken 16 times.
✓ Branch 2 → 4 taken 1375 times.
1391 if (qualifiers.isHeap)
373 16 return false;
374
375 // References can't be copied at all
376
2/2
✓ Branch 5 → 6 taken 21 times.
✓ Branch 5 → 7 taken 1354 times.
1375 if (isRef())
377 21 return false;
378
379 // In case of an array, the item type is determining the copy triviality
380
2/2
✓ Branch 8 → 9 taken 8 times.
✓ Branch 8 → 13 taken 1346 times.
1354 if (isArray())
381
2/4
✓ Branch 9 → 10 taken 8 times.
✗ Branch 9 → 36 not taken.
✓ Branch 10 → 11 taken 8 times.
✗ Branch 10 → 36 not taken.
8 return getBase().isTriviallyCopyable(node);
382
383 // In case of a struct, the member types determine the copy triviality
384
2/2
✓ Branch 14 → 15 taken 627 times.
✓ Branch 14 → 34 taken 719 times.
1346 if (is(TY_STRUCT)) {
385 // If the struct has a copy ctor, it is a non-trivially copyable one
386
1/2
✓ Branch 15 → 16 taken 627 times.
✗ Branch 15 → 51 not taken.
627 const Struct *spiceStruct = getStruct(node);
387
2/4
✓ Branch 16 → 17 taken 627 times.
✗ Branch 16 → 40 not taken.
✓ Branch 20 → 21 taken 627 times.
✗ Branch 20 → 37 not taken.
1881 const std::vector args = {Arg(toConstRef(node), false)};
388
2/4
✓ Branch 24 → 25 taken 627 times.
✗ Branch 24 → 45 not taken.
✓ Branch 25 → 26 taken 627 times.
✗ Branch 25 → 43 not taken.
627 const Function *copyCtor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, args, true);
389
2/2
✓ Branch 28 → 29 taken 225 times.
✓ Branch 28 → 30 taken 402 times.
627 if (copyCtor != nullptr)
390 225 return false;
391
392 // Check if all member types are trivially copyable
393 658 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
394
1/2
✓ Branch 30 → 31 taken 402 times.
✗ Branch 30 → 49 not taken.
402 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
395 627 }
396
397 719 return true;
398 }
399
400 /**
401 * Check if destructing an instance of the current type would require calling a dtor.
402 * If this function return true, the type does not need to be destructed.
403 *
404 * @param node Accessing ASTNode
405 * @return Trivially destructible or not
406 */
407 8404 bool QualType::isTriviallyDestructible(const ASTNode *node) const {
408 // Heap-allocated values require manual de-allocation, which is done in the default/explicit dtor
409
2/2
✓ Branch 2 → 3 taken 579 times.
✓ Branch 2 → 4 taken 7825 times.
8404 if (qualifiers.isHeap)
410 579 return false;
411
412 // In case of an array, the item type is determining the destructing triviality
413
2/2
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 10 taken 7820 times.
7825 if (isArray())
414
2/4
✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 28 not taken.
✓ Branch 7 → 8 taken 5 times.
✗ Branch 7 → 28 not taken.
5 return getBase().isTriviallyDestructible(node);
415
416 // In case of a struct, the member types determine the destructing triviality
417
2/2
✓ Branch 11 → 12 taken 4346 times.
✓ Branch 11 → 26 taken 3474 times.
7820 if (is(TY_STRUCT)) {
418 // If the struct has a dtor, it is a non-trivially destructible one
419
1/2
✓ Branch 12 → 13 taken 4346 times.
✗ Branch 12 → 38 not taken.
4346 const Struct *spiceStruct = getStruct(node);
420
2/4
✓ Branch 16 → 17 taken 4346 times.
✗ Branch 16 → 31 not taken.
✓ Branch 17 → 18 taken 4346 times.
✗ Branch 17 → 29 not taken.
13038 const Function *dtor = FunctionManager::lookup(spiceStruct->scope, DTOR_FUNCTION_NAME, *this, {}, true);
421
2/2
✓ Branch 21 → 22 taken 1770 times.
✓ Branch 21 → 23 taken 2576 times.
4346 if (dtor != nullptr)
422 1770 return false;
423
424 // Check if all member types are trivially destructible
425 4504 const auto pred = [&](const QualType &fieldType) {
426 4504 return fieldType.isTriviallyDestructible(node);
427 2576 }; // NOLINT(*-no-recursion)
428
1/2
✓ Branch 23 → 24 taken 2576 times.
✗ Branch 23 → 38 not taken.
2576 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
429 }
430
431 3474 return true;
432 }
433
434 /**
435 * Check if the current type implements the given interface type
436 *
437 * @param implementedInterfaceType Interface type
438 * @param node Accessing ASTNode
439 * @return Struct implements interface or not
440 */
441 230 bool QualType::doesImplement(const QualType &implementedInterfaceType, const ASTNode *node) const {
442
2/4
✓ Branch 3 → 4 taken 230 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 230 times.
✗ Branch 5 → 7 not taken.
230 assert(is(TY_STRUCT) && implementedInterfaceType.is(TY_INTERFACE));
443 230 const Struct *spiceStruct = getStruct(node);
444
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 230 times.
230 assert(spiceStruct != nullptr);
445 230 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
446
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 230 times.
230 assert(interfaceType.is(TY_INTERFACE));
447 230 return implementedInterfaceType.matches(interfaceType, false, false, true);
448 230 });
449 }
450
451 /**
452 * Check if a certain input type can be bound (assigned) to the current type->
453 *
454 * @param inputType Qualified type, which should be bound to the current type
455 * @param isTemporary Is the input type a temporary type
456 * @return Can be bound or not
457 */
458 16509 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
459
8/8
✓ Branch 2 → 3 taken 5541 times.
✓ Branch 2 → 9 taken 10968 times.
✓ Branch 4 → 5 taken 5298 times.
✓ Branch 4 → 9 taken 243 times.
✓ Branch 6 → 7 taken 324 times.
✓ Branch 6 → 9 taken 4974 times.
✓ Branch 8 → 9 taken 322 times.
✓ Branch 8 → 10 taken 2 times.
16509 return !isTemporary || inputType.type->isRef() || !type->isRef() || isConstRef();
460 }
461
462 /**
463 * Check for the matching compatibility of two types.
464 * Useful for struct and function matching as well as assignment type validation and function arg matching.
465 *
466 * @param otherType Type to compare against
467 * @param ignoreArraySize Ignore array sizes
468 * @param ignoreQualifiers Ignore qualifiers, except for pointer and reference types
469 * @param allowConstify Match when the types are the same, but the lhs type is more const restrictive than the rhs type
470 * @return Matching or not
471 */
472 130291 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
473 // Special case: string is equivalent to const char*
474
6/8
✓ Branch 3 → 4 taken 19424 times.
✓ Branch 3 → 9 taken 110867 times.
✓ Branch 5 → 6 taken 1439 times.
✓ Branch 5 → 9 taken 17985 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1439 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 130291 times.
130291 if (is(TY_STRING) && otherType.isPtrTo(TY_CHAR) && otherType.isConst())
475 return true;
476
4/8
✓ Branch 13 → 14 taken 5819 times.
✓ Branch 13 → 19 taken 124472 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 19 taken 5819 times.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 130291 times.
130291 if (isPtrTo(TY_CHAR) && isConst() && otherType.is(TY_STRING))
477 return true;
478
479 // Compare type
480
2/2
✓ Branch 23 → 24 taken 52398 times.
✓ Branch 23 → 25 taken 77893 times.
130291 if (!type->matches(otherType.type, ignoreArraySize))
481 52398 return false;
482
483 // Ignore or compare qualifiers
484
4/4
✓ Branch 25 → 26 taken 14947 times.
✓ Branch 25 → 28 taken 62946 times.
✓ Branch 27 → 28 taken 14768 times.
✓ Branch 27 → 29 taken 179 times.
77893 return ignoreQualifiers || qualifiers.match(otherType.qualifiers, allowConstify);
485 }
486
487 /**
488 * Check for the matching compatibility of two types in terms of interface implementation.
489 * Useful for function matching as well as assignment type validation and function arg matching.
490 *
491 * @param structType Type to compare against
492 * @return Matching or not
493 */
494 62343 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
495
8/10
✓ Branch 2 → 3 taken 62343 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 219 times.
✓ Branch 3 → 6 taken 62124 times.
✓ Branch 4 → 5 taken 219 times.
✗ Branch 4 → 17 not taken.
✓ Branch 5 → 6 taken 38 times.
✓ Branch 5 → 7 taken 181 times.
✓ Branch 8 → 9 taken 62162 times.
✓ Branch 8 → 10 taken 181 times.
62343 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
496 62162 return false;
497
498 // Check if the rhs is a struct type that implements the lhs interface type
499
1/2
✓ Branch 10 → 11 taken 181 times.
✗ Branch 10 → 17 not taken.
181 const Struct *spiceStruct = structType.getStruct(nullptr);
500
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 181 times.
181 assert(spiceStruct != nullptr);
501 177 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
502
1/2
✓ Branch 13 → 14 taken 181 times.
✗ Branch 13 → 17 not taken.
181 return std::ranges::any_of(spiceStruct->interfaceTypes, pred);
503 }
504
505 /**
506 * Check if the current type is the same container type as another type.
507 * Container types include arrays, pointers, and references.
508 *
509 * @param other Other type
510 * @return Same container type or not
511 */
512 2731 bool QualType::isSameContainerTypeAs(const QualType &other) const { return type->isSameContainerTypeAs(other.type); }
513
514 /**
515 * Check if the current type is a self-referencing struct type
516 *
517 * @return Self-referencing struct type or not
518 */
519 24495 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
520
2/2
✓ Branch 3 → 4 taken 17936 times.
✓ Branch 3 → 5 taken 6559 times.
24495 if (!is(TY_STRUCT))
521 17936 return false;
522
523 // If no type was set by a previous iteration, we set it to the current type
524
2/2
✓ Branch 5 → 6 taken 4738 times.
✓ Branch 5 → 7 taken 1821 times.
6559 if (typeToCompareWith == nullptr)
525 4738 typeToCompareWith = this;
526
527 6559 Scope *baseTypeBodyScope = getBodyScope();
528
2/2
✓ Branch 24 → 9 taken 19657 times.
✓ Branch 24 → 25 taken 6221 times.
25878 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
529
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 19657 times.
19657 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
530 19657 const QualType &fieldType = field->getQualType();
531 // Check if the base type of the field matches with the current type, which is also a base type
532 // If yes, this is a self-referencing struct type
533
3/4
✓ Branch 15 → 16 taken 19657 times.
✗ Branch 15 → 27 not taken.
✓ Branch 17 → 18 taken 338 times.
✓ Branch 17 → 19 taken 19319 times.
19657 if (fieldType.getBase() == *typeToCompareWith)
534 338 return true;
535
536 // If the field is a struct, check if it is a self-referencing struct type
537
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 19319 times.
19319 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
538 return true;
539 }
540 6221 return false;
541 }
542
543 /**
544 * Check if the given generic type list has a substantiation for the current (generic) type
545 *
546 * @param genericTypeList Generic type list
547 * @return Has substantiation or not
548 */
549 26553 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
550
1/2
✓ Branch 2 → 3 taken 26553 times.
✗ Branch 2 → 19 not taken.
26553 const QualType baseType = getBase();
551 // Check if the symbol type itself is generic
552
3/4
✓ Branch 3 → 4 taken 26553 times.
✗ Branch 3 → 19 not taken.
✓ Branch 4 → 5 taken 5215 times.
✓ Branch 4 → 7 taken 21338 times.
26553 if (baseType.is(TY_GENERIC)) {
553
1/2
✓ Branch 5 → 6 taken 5215 times.
✗ Branch 5 → 19 not taken.
5215 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
554
2/2
✓ Branch 3 → 4 taken 5207 times.
✓ Branch 3 → 5 taken 953 times.
6160 if (baseType.matches(t, true, true, true)) {
555 5207 t.used = true;
556 5207 return true;
557 }
558 953 return false;
559 5215 });
560 }
561
562 // If the type is non-generic check template types
563 21338 bool covered = true;
564 // Check template types
565
1/2
✓ Branch 7 → 8 taken 21338 times.
✗ Branch 7 → 19 not taken.
21338 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
566 2070 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
567 2070 return templateType.isCoveredByGenericTypeList(genericTypeList);
568 21338 };
569
1/2
✓ Branch 8 → 9 taken 21338 times.
✗ Branch 8 → 19 not taken.
21338 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
570
571 // If function/procedure, check param and return types
572
3/4
✓ Branch 9 → 10 taken 21338 times.
✗ Branch 9 → 17 not taken.
✓ Branch 10 → 11 taken 33 times.
✓ Branch 10 → 14 taken 21305 times.
21338 if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
573
1/2
✓ Branch 11 → 12 taken 33 times.
✗ Branch 11 → 18 not taken.
33 const QualTypeList &paramAndReturnTypes = baseType.getFunctionParamAndReturnTypes();
574 50 const auto innerPred = [&](const QualType &paramType) { // NOLINT(*-no-recursion)
575 50 return paramType.isCoveredByGenericTypeList(genericTypeList);
576 33 };
577
1/2
✓ Branch 12 → 13 taken 33 times.
✗ Branch 12 → 18 not taken.
33 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
578 }
579
580 21338 return covered;
581 }
582
583 /**
584 * Check if the current type needs de-allocation
585 *
586 * @return Needs de-allocation or not
587 */
588 1384 bool QualType::needsDeAllocation() const {
589
2/2
✓ Branch 3 → 4 taken 1315 times.
✓ Branch 3 → 5 taken 69 times.
1384 if (!isHeap())
590 1315 return false;
591 // We only need de-allocation, if we directly point to a heap-allocated type
592 // e.g. for heap TestStruct** we don't need to de-allocate, since it is a non-owning pointer to an owning pointer
593
2/4
✓ Branch 6 → 7 taken 69 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 69 times.
✗ Branch 8 → 10 not taken.
69 return isPtr() && !isPtrTo(TY_PTR);
594 }
595
596 /**
597 * Get the name of the symbol type as a string
598 *
599 * @param name Name stream
600 * @param withSize Include the array size for sized types
601 * @param ignorePublic Ignore any potential public qualifier
602 * @param withAliases Print aliases as is and not decompose them
603 */
604 481895 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
605 // Append the qualifiers
606
3/6
✓ Branch 2 → 3 taken 481895 times.
✗ Branch 2 → 31 not taken.
✓ Branch 3 → 4 taken 481895 times.
✗ Branch 3 → 31 not taken.
✓ Branch 4 → 5 taken 481895 times.
✗ Branch 4 → 31 not taken.
481895 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
607
5/6
✓ Branch 5 → 6 taken 305138 times.
✓ Branch 5 → 9 taken 176757 times.
✓ Branch 6 → 7 taken 104551 times.
✓ Branch 6 → 9 taken 200587 times.
✓ Branch 7 → 8 taken 104551 times.
✗ Branch 7 → 9 not taken.
481895 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
608
1/2
✓ Branch 8 → 9 taken 104551 times.
✗ Branch 8 → 32 not taken.
104551 name << "public ";
609
3/4
✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 12 taken 481891 times.
✓ Branch 10 → 11 taken 4 times.
✗ Branch 10 → 12 not taken.
481895 if (qualifiers.isComposition && !defaultForSuperType.isComposition)
610
1/2
✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 32 not taken.
4 name << "compose ";
611
8/8
✓ Branch 12 → 13 taken 66667 times.
✓ Branch 12 → 17 taken 415228 times.
✓ Branch 13 → 14 taken 65367 times.
✓ Branch 13 → 17 taken 1300 times.
✓ Branch 15 → 16 taken 39256 times.
✓ Branch 15 → 17 taken 26111 times.
✓ Branch 18 → 19 taken 39256 times.
✓ Branch 18 → 20 taken 442639 times.
481895 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
612
1/2
✓ Branch 19 → 20 taken 39256 times.
✗ Branch 19 → 32 not taken.
39256 name << "const ";
613
3/4
✓ Branch 20 → 21 taken 19542 times.
✓ Branch 20 → 23 taken 462353 times.
✓ Branch 21 → 22 taken 19542 times.
✗ Branch 21 → 23 not taken.
481895 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
614
1/2
✓ Branch 22 → 23 taken 19542 times.
✗ Branch 22 → 32 not taken.
19542 name << "heap ";
615
4/4
✓ Branch 23 → 24 taken 57808 times.
✓ Branch 23 → 26 taken 424087 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 26 taken 57807 times.
481895 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
616
1/2
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 32 not taken.
1 name << "signed ";
617
4/4
✓ Branch 26 → 27 taken 424087 times.
✓ Branch 26 → 29 taken 57808 times.
✓ Branch 27 → 28 taken 43164 times.
✓ Branch 27 → 29 taken 380923 times.
481895 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
618
1/2
✓ Branch 28 → 29 taken 43164 times.
✗ Branch 28 → 32 not taken.
43164 name << "unsigned ";
619
620 // Loop through all chain elements
621
1/2
✓ Branch 29 → 30 taken 481895 times.
✗ Branch 29 → 32 not taken.
481895 type->getName(name, withSize, ignorePublic, withAliases);
622 481895 }
623
624 /**
625 * Get the name of the symbol type as a string
626 *
627 * @param withSize Include the array size for sized types
628 * @param ignorePublic Ignore any potential public qualifier
629 * @param withAliases Print aliases as is and not decompose them
630 * @return Symbol type name
631 */
632 287072 std::string QualType::getName(bool withSize, bool ignorePublic, bool withAliases) const {
633
1/2
✓ Branch 2 → 3 taken 287072 times.
✗ Branch 2 → 11 not taken.
287072 std::stringstream name;
634
1/2
✓ Branch 3 → 4 taken 287072 times.
✗ Branch 3 → 9 not taken.
287072 getName(name, withSize, ignorePublic, withAliases);
635
1/2
✓ Branch 4 → 5 taken 287072 times.
✗ Branch 4 → 9 not taken.
574144 return name.str();
636 287072 }
637
638 /**
639 * Convert the type to an LLVM type
640 *
641 * @param sourceFile Source file
642 * @return LLVM type
643 */
644 360363 llvm::Type *QualType::toLLVMType(SourceFile *sourceFile) const { return sourceFile->getLLVMType(type); }
645
646 /**
647 * Retrieve the pointer type to this type
648 *
649 * @param node ASTNode
650 * @return New type
651 */
652 25439 QualType QualType::toPtr(const ASTNode *node) const {
653 25439 QualType newType = *this;
654
2/2
✓ Branch 2 → 3 taken 25437 times.
✓ Branch 2 → 5 taken 2 times.
25439 newType.type = type->toPtr(node);
655 25437 return newType;
656 }
657
658 /**
659 * Retrieve the reference type to this type
660 *
661 * @param node ASTNode
662 * @return New type
663 */
664 13076 QualType QualType::toRef(const ASTNode *node) const {
665 13076 QualType newType = *this;
666
1/2
✓ Branch 2 → 3 taken 13076 times.
✗ Branch 2 → 5 not taken.
13076 newType.type = type->toRef(node);
667 13076 return newType;
668 }
669
670 /**
671 * Retrieve the const reference type of this type
672 *
673 * @param node ASTNode
674 * @return New type
675 */
676 4441 QualType QualType::toConstRef(const ASTNode *node) const {
677
1/2
✓ Branch 2 → 3 taken 4441 times.
✗ Branch 2 → 6 not taken.
4441 QualType newType = toRef(node);
678 4441 newType.makeConst();
679 4441 return newType;
680 }
681
682 /**
683 * Retrieve the array type of this type
684 *
685 * @param node ASTNode
686 * @param size Array size
687 * @param skipDynCheck Skip dynamic check
688 * @return New type
689 */
690 227 QualType QualType::toArr(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
691 227 QualType newType = *this;
692
2/2
✓ Branch 2 → 3 taken 226 times.
✓ Branch 2 → 5 taken 1 time.
227 newType.type = type->toArr(node, size, skipDynCheck);
693 226 return newType;
694 }
695
696 /**
697 * Retrieve the non-const type of this type
698 *
699 * @return New type
700 */
701 2269 QualType QualType::toNonConst() const {
702 2269 QualType newType = *this;
703 2269 newType.qualifiers.isConst = false;
704 2269 return newType;
705 }
706
707 /**
708 * Retrieve the contained type of this type
709 * This works on pointers, arrays, references and strings (which alias with char*)
710 *
711 * @return New type
712 */
713 90404 QualType QualType::getContained() const {
714
2/4
✓ Branch 2 → 3 taken 90404 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 90404 times.
90404 assert(isOneOf({TY_PTR, TY_REF, TY_ARRAY, TY_STRING}));
715 90404 QualType newType = *this;
716
1/2
✓ Branch 5 → 6 taken 90404 times.
✗ Branch 5 → 9 not taken.
90404 newType.type = type->getContained();
717 90404 return newType;
718 }
719
720 /**
721 * Retrieve the base type of this type
722 *
723 * @return New type
724 */
725 853848 QualType QualType::getBase() const {
726 853848 QualType newType = *this;
727
1/2
✓ Branch 2 → 3 taken 853848 times.
✗ Branch 2 → 5 not taken.
853848 newType.type = type->getBase();
728 853848 return newType;
729 }
730
731 /**
732 * Get aliased type for an alias type
733 *
734 * @param aliasEntry Entry of the alias definition
735 * @return Aliased type
736 */
737 999 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
738
2/4
✓ Branch 2 → 3 taken 999 times.
✗ Branch 2 → 18 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 999 times.
999 assert(is(TY_ALIAS));
739 // Get type of aliased type container entry
740
1/2
✓ Branch 5 → 6 taken 999 times.
✗ Branch 5 → 18 not taken.
999 const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
741
1/2
✓ Branch 6 → 7 taken 999 times.
✗ Branch 6 → 16 not taken.
999 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
742
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 999 times.
999 assert(aliasedTypeContainerEntry != nullptr);
743
1/2
✓ Branch 11 → 12 taken 999 times.
✗ Branch 11 → 16 not taken.
1998 return aliasedTypeContainerEntry->getQualType();
744 999 }
745
746 /**
747 * Remove reference of this type, if it is a reference
748 *
749 * @return New type
750 */
751
2/2
✓ Branch 3 → 4 taken 5347 times.
✓ Branch 3 → 5 taken 223023 times.
228370 QualType QualType::removeReferenceWrapper() const { return isRef() ? getContained() : *this; }
752
753 /**
754 * Auto-dereference the given symbol type (peeling off all ptr/ref wrappers).
755 * This process is NOT equivalent with getBase() because getBase() also removes e.g. array wrappers
756 *
757 * @return New type
758 */
759 23661 QualType QualType::autoDeReference() const {
760 23661 QualType newType = *this;
761
3/4
✓ Branch 5 → 6 taken 43847 times.
✗ Branch 5 → 10 not taken.
✓ Branch 6 → 3 taken 20186 times.
✓ Branch 6 → 7 taken 23661 times.
43847 while (newType.isOneOf({TY_PTR, TY_REF}))
762
1/2
✓ Branch 3 → 4 taken 20186 times.
✗ Branch 3 → 9 not taken.
20186 newType = newType.getContained();
763 23661 return newType;
764 }
765
766 /**
767 * Replace the base type with another one
768 *
769 * @param newBaseType New base type
770 * @return New type
771 */
772 21416 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
773 // Create new type
774
1/2
✓ Branch 3 → 4 taken 21416 times.
✗ Branch 3 → 9 not taken.
21416 const Type *newType = type->replaceBase(newBaseType.getType());
775 // Create new qualifiers
776
1/2
✓ Branch 4 → 5 taken 21416 times.
✗ Branch 4 → 9 not taken.
21416 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
777 // Return the new qualified type
778 21416 return {newType, newQualifiers};
779 }
780
781 /**
782 * Retrieve the same type, but with lambda captures enabled
783 *
784 * @return Same type with lambda captures
785 */
786 53 QualType QualType::getWithLambdaCaptures(bool enabled /*=true*/) const {
787 // Create new type
788 53 const Type *newType = type->getWithLambdaCaptures(enabled);
789 // Return the new qualified type
790 53 return {newType, qualifiers};
791 }
792
793 /**
794 * Retrieve the same type, but with a new body scope
795 *
796 * @return Same type with body scope
797 */
798 24461 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
799 // Create new type
800 24461 const Type *newType = type->getWithBodyScope(bodyScope);
801 // Return the new qualified type
802 24461 return {newType, qualifiers};
803 }
804
805 /**
806 * Retrieve the same type, but with new template types
807 *
808 * @param templateTypes New template types
809 * @return Same type with new template types
810 */
811 3798 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
812 // Create new type
813 3798 const Type *newType = type->getWithTemplateTypes(templateTypes);
814 // Return the new qualified type
815 3798 return {newType, qualifiers};
816 }
817
818 /**
819 * Retrieve the same type, but with new base template types
820 *
821 * @param templateTypes New base template types
822 * @return Same type with new base template types
823 */
824 5176 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
825 // Create new type
826 5176 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
827 // Return the new qualified type
828 5176 return {newType, qualifiers};
829 }
830
831 /**
832 * Retrieve the same type, but with new function parameter and return types
833 *
834 * @param paramAndReturnTypes New parameter types
835 * @return Same type with new parameter types
836 */
837 14352 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
838 // Create new type
839 14352 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
840 // Return the new qualified type
841 14352 return {newType, qualifiers};
842 }
843
844 14333 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
845
1/2
✓ Branch 2 → 3 taken 14333 times.
✗ Branch 2 → 15 not taken.
14333 QualTypeList paramAndReturnTypes = paramTypes;
846
1/2
✓ Branch 5 → 6 taken 14333 times.
✗ Branch 5 → 11 not taken.
14333 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
847
1/2
✓ Branch 6 → 7 taken 14333 times.
✗ Branch 6 → 13 not taken.
28666 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
848 14333 }
849
850 /**
851 * Check if the current type is const
852 *
853 * Examples for const types:
854 * - const int
855 * - const TestStruct
856 * - const string
857 *
858 * Examples for non-const types:
859 * - double (reason: not marked const)
860 * - const int* (reason: pointer to const int is not const itself)
861 * - const TestStruct& (reason: reference to const TestStruct is not const itself)
862 *
863 * @return Is const or not
864 */
865
4/4
✓ Branch 3 → 4 taken 29458 times.
✓ Branch 3 → 6 taken 10239 times.
✓ Branch 4 → 5 taken 4715 times.
✓ Branch 4 → 6 taken 24743 times.
39697 bool QualType::isConst() const { return isExtendedPrimitive() && qualifiers.isConst; }
866
867 /**
868 * Check if the current type is marked signed
869 *
870 * @return Is signed or not
871 */
872 32649 bool QualType::isSigned() const {
873
2/4
✓ Branch 2 → 3 taken 32649 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 32649 times.
32649 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
874 32649 return qualifiers.isSigned;
875 }
876
877 /**
878 * Check if the current type is marked unsigned
879 *
880 * @return Is unsigned or not
881 */
882 2 bool QualType::isUnsigned() const {
883
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}));
884 2 return qualifiers.isUnsigned;
885 }
886
887 /**
888 * Check if the current type is marked inline
889 *
890 * @return Is inline or not
891 */
892 11253 bool QualType::isInline() const {
893
2/4
✓ Branch 2 → 3 taken 11253 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11253 times.
11253 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
894 11253 return qualifiers.isInline;
895 }
896
897 /**
898 * Check if the current type is marked public
899 *
900 * @return Is public or not
901 */
902 23821 bool QualType::isPublic() const {
903
5/8
✓ Branch 2 → 3 taken 23821 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 22477 times.
✓ Branch 3 → 7 taken 1344 times.
✓ Branch 4 → 5 taken 22477 times.
✗ Branch 4 → 9 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 22477 times.
23821 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
904 23821 return qualifiers.isPublic;
905 }
906
907 /**
908 * Check if the current type is marked heap
909 *
910 * @return Is heap or not
911 */
912 13293 bool QualType::isHeap() const { return qualifiers.isHeap; }
913
914 /**
915 * Check if the current type is marked as composition
916 *
917 * @return Is composition or not
918 */
919 41 bool QualType::isComposition() const { return qualifiers.isComposition; }
920
921 /**
922 * Make the current type const
923 *
924 * @param isConst Is const or not
925 */
926 4441 void QualType::makeConst(bool isConst) { qualifiers.isConst = isConst; }
927
928 /**
929 * Make the current type unsigned
930 *
931 * @param isUnsigned Is unsigned or not
932 */
933 14 void QualType::makeUnsigned(bool isUnsigned) {
934
2/4
✓ Branch 2 → 3 taken 14 times.
✗ Branch 2 → 6 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 14 times.
14 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
935 14 qualifiers.isSigned = !isUnsigned;
936 14 qualifiers.isUnsigned = isUnsigned;
937 14 }
938
939 /**
940 * Make the current type public
941 *
942 * @param isPublic Is public or not
943 */
944 374 void QualType::makePublic(bool isPublic) {
945
4/8
✓ Branch 2 → 3 taken 374 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 374 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 374 times.
✗ Branch 4 → 8 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 374 times.
374 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
946 374 qualifiers.isPublic = isPublic;
947 374 }
948
949 /**
950 * Make the current type heap
951 *
952 * @param isHeap Is heap or not
953 */
954 67 void QualType::makeHeap(bool isHeap) { qualifiers.isHeap = isHeap; }
955
956 /**
957 * Check if two types are equal
958 *
959 * @param lhs Left-hand side type
960 * @param rhs Right-hand side type
961 * @return Equal or not
962 */
963 466546 bool operator==(const QualType &lhs, const QualType &rhs) { return lhs.type == rhs.type; }
964
965 /**
966 * Check if two types are not equal
967 *
968 * @param lhs Left-hand side type
969 * @param rhs Right-hand side type
970 * @return Not equal or not
971 */
972 113235 bool operator!=(const QualType &lhs, const QualType &rhs) { return !(lhs == rhs); }
973
974 /**
975 * Remove pointers / arrays / references if both types have them as far as possible.
976 *
977 * @param typeA Candidate type
978 * @param typeB Requested type
979 */
980 1145 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
981
982 /**
983 * Remove pointers / arrays / references if both types have them as far as possible.
984 * Furthermore, remove reference wrappers if possible.
985 *
986 * @param typeA Candidate type
987 * @param typeB Requested type
988 */
989 95344 void QualType::unwrapBothWithRefWrappers(QualType &typeA, QualType &typeB) {
990 95344 Type::unwrapBothWithRefWrappers(typeA.type, typeB.type);
991 95344 }
992
993 } // namespace spice::compiler
994