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