GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/QualType.cpp
Date: 2025-10-09 06:28:01
Coverage Exec Excl Total
Lines: 97.1% 269 0 277
Functions: 96.5% 83 0 86
Branches: 61.3% 228 0 372

Line Branch Exec Source
1 // Copyright (c) 2021-2025 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 4725560 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), qualifiers(TypeQualifiers::of(superType)) {}
19 1700 QualType::QualType(SuperType superType, const std::string &subType)
20 1700 : type(TypeRegistry::getOrInsert(superType, subType)), qualifiers(TypeQualifiers::of(superType)) {}
21 60637 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 859525 SuperType QualType::getSuperType() const { return type->getSuperType(); }
29
30 /**
31 * Get the subtype of the underlying type
32 *
33 * @return Subtype
34 */
35 194324 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 431 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 144532 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 50 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 123 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 76907 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 14912 Struct *QualType::getStruct(const ASTNode *node, const QualTypeList &templateTypes) const {
94
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 14912 times.
14912 assert(is(TY_STRUCT));
95 14912 Scope *structDefScope = getBodyScope()->parent;
96 14912 const std::string &structName = getSubType();
97 14912 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 8425 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 288 Struct *QualType::getStructAndAdjustType(const ASTNode *node, const QualTypeList &templateTypes) {
117 288 Struct *spiceStruct = getStruct(node, templateTypes);
118
2/4
✓ Branch 4 → 5 taken 288 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 288 times.
✗ Branch 5 → 9 not taken.
288 type = type->getWithBodyScope(spiceStruct->scope)->getWithTemplateTypes(spiceStruct->getTemplateTypes());
119 288 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 1294 Interface *QualType::getInterface(const ASTNode *node, const QualTypeList &templateTypes) const {
139
2/4
✓ Branch 2 → 3 taken 1294 times.
✗ Branch 2 → 15 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1294 times.
1294 assert(is(TY_INTERFACE));
140
1/2
✓ Branch 5 → 6 taken 1294 times.
✗ Branch 5 → 15 not taken.
1294 Scope *interfaceDefScope = getBodyScope()->parent;
141
2/4
✓ Branch 6 → 7 taken 1294 times.
✗ Branch 6 → 15 not taken.
✓ Branch 7 → 8 taken 1294 times.
✗ Branch 7 → 15 not taken.
1294 const std::string structName = getSubType();
142
1/2
✓ Branch 8 → 9 taken 1294 times.
✗ Branch 8 → 13 not taken.
2588 return InterfaceManager::match(interfaceDefScope, structName, templateTypes, node);
143 1294 }
144
145 /**
146 * Get the interface instance for an interface type
147 *
148 * @param node Accessing AST node
149 * @return Interface instance
150 */
151 738 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 2761266 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 549475 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 650106 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 1165 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 79805 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 161645 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 25673 times.
✗ Branch 2 → 12 not taken.
✓ Branch 3 → 4 taken 244 times.
✓ Branch 3 → 8 taken 25429 times.
✓ Branch 4 → 5 taken 244 times.
✗ Branch 4 → 12 not taken.
✓ Branch 5 → 6 taken 244 times.
✗ Branch 5 → 12 not taken.
✓ Branch 6 → 7 taken 16 times.
✓ Branch 6 → 8 taken 228 times.
25673 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 448004 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 32715 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 327 times.
✓ Branch 2 → 6 taken 271 times.
✓ Branch 4 → 5 taken 323 times.
✓ Branch 4 → 6 taken 4 times.
598 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 114 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 114 times.
✗ Branch 2 → 47 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 113 times.
114 if (!is(TY_STRUCT))
257 1 return false;
258
259
2/4
✓ Branch 7 → 8 taken 113 times.
✗ Branch 7 → 30 not taken.
✓ Branch 8 → 9 taken 113 times.
✗ Branch 8 → 28 not taken.
113 const QualType genericType(TY_GENERIC, "T");
260 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
261
3/6
✓ Branch 13 → 14 taken 113 times.
✗ Branch 13 → 42 not taken.
✓ Branch 16 → 17 taken 113 times.
✗ Branch 16 → 36 not taken.
✓ Branch 17 → 18 taken 113 times.
✗ Branch 17 → 34 not taken.
452 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERATOR_INTERFACE, data, {genericType});
262
1/2
✓ Branch 22 → 23 taken 113 times.
✗ Branch 22 → 47 not taken.
113 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
263
1/2
✓ Branch 24 → 25 taken 113 times.
✗ Branch 24 → 47 not taken.
113 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 116 bool QualType::isIterable(const ASTNode *node) const {
275 // Arrays are always considered iterable
276
3/4
✓ Branch 2 → 3 taken 116 times.
✗ Branch 2 → 50 not taken.
✓ Branch 3 → 4 taken 8 times.
✓ Branch 3 → 5 taken 108 times.
116 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 108 times.
✗ Branch 5 → 50 not taken.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 107 times.
108 if (!is(TY_STRUCT))
280 1 return false;
281
282
2/4
✓ Branch 10 → 11 taken 107 times.
✗ Branch 10 → 33 not taken.
✓ Branch 11 → 12 taken 107 times.
✗ Branch 11 → 31 not taken.
107 const QualType genericType(TY_GENERIC, "T");
283 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
284
3/6
✓ Branch 16 → 17 taken 107 times.
✗ Branch 16 → 45 not taken.
✓ Branch 19 → 20 taken 107 times.
✗ Branch 19 → 39 not taken.
✓ Branch 20 → 21 taken 107 times.
✗ Branch 20 → 37 not taken.
428 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERABLE_INTERFACE, data, {genericType});
285
1/2
✓ Branch 25 → 26 taken 107 times.
✗ Branch 25 → 50 not taken.
107 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
286
1/2
✓ Branch 27 → 28 taken 107 times.
✗ Branch 27 → 50 not taken.
107 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 678 bool QualType::isStringObj() const {
295
4/6
✓ Branch 3 → 4 taken 116 times.
✓ Branch 3 → 10 taken 562 times.
✓ Branch 6 → 7 taken 116 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 116 times.
✗ Branch 8 → 10 not taken.
678 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 672 bool QualType::isErrorObj() const {
304
3/6
✓ Branch 3 → 4 taken 672 times.
✗ Branch 3 → 10 not taken.
✓ Branch 6 → 7 taken 672 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 672 times.
✗ Branch 8 → 10 not taken.
672 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 318839 bool QualType::hasAnyGenericParts() const { return type->hasAnyGenericParts(); }
313
314 /**
315 * Check if copying an instance of the current type would require a call to the copy ctor.
316 * If this function return true, the type can be copied by calling memcpy.
317 *
318 * @param node Accessing ASTNode
319 * @return Trivially copyable or not
320 */
321 695 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
322
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 695 times.
695 assert(!hasAnyGenericParts());
323
324 // Heap-allocated values may not be copied via memcpy
325
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 695 times.
695 if (qualifiers.isHeap)
326 return false;
327
328 // References can't be copied at all
329
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 695 times.
695 if (isRef())
330 return false;
331
332 // In case of an array, the item type is determining the copy triviality
333
2/2
✓ Branch 11 → 12 taken 8 times.
✓ Branch 11 → 16 taken 687 times.
695 if (isArray())
334
2/4
✓ Branch 12 → 13 taken 8 times.
✗ Branch 12 → 39 not taken.
✓ Branch 13 → 14 taken 8 times.
✗ Branch 13 → 39 not taken.
8 return getBase().isTriviallyCopyable(node);
335
336 // In case of a struct, the member types determine the copy triviality
337
2/2
✓ Branch 17 → 18 taken 203 times.
✓ Branch 17 → 37 taken 484 times.
687 if (is(TY_STRUCT)) {
338 // If the struct has a copy ctor, it is a non-trivially copyable one
339
1/2
✓ Branch 18 → 19 taken 203 times.
✗ Branch 18 → 54 not taken.
203 const Struct *spiceStruct = getStruct(node);
340
2/4
✓ Branch 19 → 20 taken 203 times.
✗ Branch 19 → 43 not taken.
✓ Branch 23 → 24 taken 203 times.
✗ Branch 23 → 40 not taken.
609 const std::vector args = {Arg(toConstRef(node), false)};
341
2/4
✓ Branch 27 → 28 taken 203 times.
✗ Branch 27 → 48 not taken.
✓ Branch 28 → 29 taken 203 times.
✗ Branch 28 → 46 not taken.
203 const Function *copyCtor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, args, true);
342
2/2
✓ Branch 31 → 32 taken 84 times.
✓ Branch 31 → 33 taken 119 times.
203 if (copyCtor != nullptr)
343 84 return false;
344
345 // Check if all member types are trivially copyable
346 236 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
347
1/2
✓ Branch 33 → 34 taken 119 times.
✗ Branch 33 → 52 not taken.
119 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
348 203 }
349
350 484 return true;
351 }
352
353 /**
354 * Check if destructing an instance of the current type would require calling other dtors.
355 * If this function return true, the type does not need to be destructed
356 *
357 * @param node Accessing ASTNode
358 * @return Trivially destructible or not
359 */
360 7756 bool QualType::isTriviallyDestructible(const ASTNode *node) const {
361
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 7756 times.
7756 assert(!hasAnyGenericParts());
362
363 // Heap-allocated values require manual de-allocation, which is done in the default/explicit dtor
364
2/2
✓ Branch 5 → 6 taken 520 times.
✓ Branch 5 → 7 taken 7236 times.
7756 if (qualifiers.isHeap)
365 520 return false;
366
367 // In case of an array, the item type is determining the destructing triviality
368
2/2
✓ Branch 8 → 9 taken 5 times.
✓ Branch 8 → 13 taken 7231 times.
7236 if (isArray())
369
2/4
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 31 not taken.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 31 not taken.
5 return getBase().isTriviallyDestructible(node);
370
371 // In case of a struct, the member types determine the destructing triviality
372
2/2
✓ Branch 14 → 15 taken 4015 times.
✓ Branch 14 → 29 taken 3216 times.
7231 if (is(TY_STRUCT)) {
373 // If the struct has a dtor, it is a non-trivially destructible one
374
1/2
✓ Branch 15 → 16 taken 4015 times.
✗ Branch 15 → 41 not taken.
4015 const Struct *spiceStruct = getStruct(node);
375
2/4
✓ Branch 19 → 20 taken 4015 times.
✗ Branch 19 → 34 not taken.
✓ Branch 20 → 21 taken 4015 times.
✗ Branch 20 → 32 not taken.
12045 const Function *dtor = FunctionManager::lookup(spiceStruct->scope, DTOR_FUNCTION_NAME, *this, {}, true);
376
2/2
✓ Branch 24 → 25 taken 1641 times.
✓ Branch 24 → 26 taken 2374 times.
4015 if (dtor != nullptr)
377 1641 return false;
378
379 // Check if all member types are trivially destructible
380 4162 const auto pred = [&](const QualType &fieldType) {
381 4162 return fieldType.isTriviallyDestructible(node);
382 2374 }; // NOLINT(*-no-recursion)
383
1/2
✓ Branch 26 → 27 taken 2374 times.
✗ Branch 26 → 41 not taken.
2374 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
384 }
385
386 3216 return true;
387 }
388
389 /**
390 * Check if the current type implements the given interface type
391 *
392 * @param implementedInterfaceType Interface type
393 * @param node Accessing ASTNode
394 * @return Struct implements interface or not
395 */
396 220 bool QualType::doesImplement(const QualType &implementedInterfaceType, const ASTNode *node) const {
397
2/4
✓ Branch 3 → 4 taken 220 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 220 times.
✗ Branch 5 → 7 not taken.
220 assert(is(TY_STRUCT) && implementedInterfaceType.is(TY_INTERFACE));
398 220 const Struct *spiceStruct = getStruct(node);
399
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 220 times.
220 assert(spiceStruct != nullptr);
400 220 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
401
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 220 times.
220 assert(interfaceType.is(TY_INTERFACE));
402 220 return implementedInterfaceType.matches(interfaceType, false, false, true);
403 220 });
404 }
405
406 /**
407 * Check if a certain input type can be bound (assigned) to the current type->
408 *
409 * @param inputType Qualified type, which should be bound to the current type
410 * @param isTemporary Is the input type a temporary type
411 * @return Can be bound or not
412 */
413 12105 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
414
8/8
✓ Branch 2 → 3 taken 3468 times.
✓ Branch 2 → 9 taken 8637 times.
✓ Branch 4 → 5 taken 3249 times.
✓ Branch 4 → 9 taken 219 times.
✓ Branch 6 → 7 taken 301 times.
✓ Branch 6 → 9 taken 2948 times.
✓ Branch 8 → 9 taken 299 times.
✓ Branch 8 → 10 taken 2 times.
12105 return !isTemporary || inputType.type->isRef() || !type->isRef() || isConstRef();
415 }
416
417 /**
418 * Check for the matching compatibility of two types.
419 * Useful for struct and function matching as well as assignment type validation and function arg matching.
420 *
421 * @param otherType Type to compare against
422 * @param ignoreArraySize Ignore array sizes
423 * @param ignoreQualifiers Ignore qualifiers, except for pointer and reference types
424 * @param allowConstify Match when the types are the same, but the lhs type is more const restrictive than the rhs type
425 * @return Matching or not
426 */
427 109950 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
428 // Compare type
429
2/2
✓ Branch 3 → 4 taken 46118 times.
✓ Branch 3 → 5 taken 63832 times.
109950 if (!type->matches(otherType.type, ignoreArraySize))
430 46118 return false;
431
432 // Ignore or compare qualifiers
433
4/4
✓ Branch 5 → 6 taken 13265 times.
✓ Branch 5 → 8 taken 50567 times.
✓ Branch 7 → 8 taken 13088 times.
✓ Branch 7 → 9 taken 177 times.
63832 return ignoreQualifiers || qualifiers.match(otherType.qualifiers, allowConstify);
434 }
435
436 /**
437 * Check for the matching compatibility of two types in terms of interface implementation.
438 * Useful for function matching as well as assignment type validation and function arg matching.
439 *
440 * @param structType Type to compare against
441 * @return Matching or not
442 */
443 54886 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
444
8/10
✓ Branch 2 → 3 taken 54886 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 200 times.
✓ Branch 3 → 6 taken 54686 times.
✓ Branch 4 → 5 taken 200 times.
✗ Branch 4 → 17 not taken.
✓ Branch 5 → 6 taken 37 times.
✓ Branch 5 → 7 taken 163 times.
✓ Branch 8 → 9 taken 54723 times.
✓ Branch 8 → 10 taken 163 times.
54886 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
445 54723 return false;
446
447 // Check if the rhs is a struct type that implements the lhs interface type
448
1/2
✓ Branch 10 → 11 taken 163 times.
✗ Branch 10 → 17 not taken.
163 const Struct *spiceStruct = structType.getStruct(nullptr);
449
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 163 times.
163 assert(spiceStruct != nullptr);
450 159 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
451
1/2
✓ Branch 13 → 14 taken 163 times.
✗ Branch 13 → 17 not taken.
163 return std::ranges::any_of(spiceStruct->interfaceTypes, pred);
452 }
453
454 /**
455 * Check if the current type is the same container type as another type.
456 * Container types include arrays, pointers, and references.
457 *
458 * @param other Other type
459 * @return Same container type or not
460 */
461 2453 bool QualType::isSameContainerTypeAs(const QualType &other) const { return type->isSameContainerTypeAs(other.type); }
462
463 /**
464 * Check if the current type is a self-referencing struct type
465 *
466 * @return Self-referencing struct type or not
467 */
468 21931 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
469
2/2
✓ Branch 3 → 4 taken 16111 times.
✓ Branch 3 → 5 taken 5820 times.
21931 if (!is(TY_STRUCT))
470 16111 return false;
471
472 // If no type was set by a previous iteration, we set it to the current type
473
2/2
✓ Branch 5 → 6 taken 4273 times.
✓ Branch 5 → 7 taken 1547 times.
5820 if (typeToCompareWith == nullptr)
474 4273 typeToCompareWith = this;
475
476 5820 Scope *baseTypeBodyScope = getBodyScope();
477
2/2
✓ Branch 24 → 9 taken 17592 times.
✓ Branch 24 → 25 taken 5482 times.
23074 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
478
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 17592 times.
17592 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
479 17592 const QualType &fieldType = field->getQualType();
480 // Check if the base type of the field matches with the current type, which is also a base type
481 // If yes, this is a self-referencing struct type
482
3/4
✓ Branch 15 → 16 taken 17592 times.
✗ Branch 15 → 27 not taken.
✓ Branch 17 → 18 taken 338 times.
✓ Branch 17 → 19 taken 17254 times.
17592 if (fieldType.getBase() == *typeToCompareWith)
483 338 return true;
484
485 // If the field is a struct, check if it is a self-referencing struct type
486
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 17254 times.
17254 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
487 return true;
488 }
489 5482 return false;
490 }
491
492 /**
493 * Check if the given generic type list has a substantiation for the current (generic) type
494 *
495 * @param genericTypeList Generic type list
496 * @return Has substantiation or not
497 */
498 23967 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
499
1/2
✓ Branch 2 → 3 taken 23967 times.
✗ Branch 2 → 19 not taken.
23967 const QualType baseType = getBase();
500 // Check if the symbol type itself is generic
501
3/4
✓ Branch 3 → 4 taken 23967 times.
✗ Branch 3 → 19 not taken.
✓ Branch 4 → 5 taken 4486 times.
✓ Branch 4 → 7 taken 19481 times.
23967 if (baseType.is(TY_GENERIC)) {
502
1/2
✓ Branch 5 → 6 taken 4486 times.
✗ Branch 5 → 19 not taken.
4486 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
503
2/2
✓ Branch 3 → 4 taken 4478 times.
✓ Branch 3 → 5 taken 788 times.
5266 if (baseType.matches(t, true, true, true)) {
504 4478 t.used = true;
505 4478 return true;
506 }
507 788 return false;
508 4486 });
509 }
510
511 // If the type is non-generic check template types
512 19481 bool covered = true;
513 // Check template types
514
1/2
✓ Branch 7 → 8 taken 19481 times.
✗ Branch 7 → 19 not taken.
19481 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
515 1885 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
516 1885 return templateType.isCoveredByGenericTypeList(genericTypeList);
517 19481 };
518
1/2
✓ Branch 8 → 9 taken 19481 times.
✗ Branch 8 → 19 not taken.
19481 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
519
520 // If function/procedure, check param and return types
521
3/4
✓ Branch 9 → 10 taken 19481 times.
✗ Branch 9 → 17 not taken.
✓ Branch 10 → 11 taken 29 times.
✓ Branch 10 → 14 taken 19452 times.
19481 if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
522
1/2
✓ Branch 11 → 12 taken 29 times.
✗ Branch 11 → 18 not taken.
29 const QualTypeList &paramAndReturnTypes = baseType.getFunctionParamAndReturnTypes();
523 46 const auto innerPred = [&](const QualType &paramType) { // NOLINT(*-no-recursion)
524 46 return paramType.isCoveredByGenericTypeList(genericTypeList);
525 29 };
526
1/2
✓ Branch 12 → 13 taken 29 times.
✗ Branch 12 → 18 not taken.
29 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
527 }
528
529 19481 return covered;
530 }
531
532 /**
533 * Check if the current type needs de-allocation
534 *
535 * @return Needs de-allocation or not
536 */
537 1272 bool QualType::needsDeAllocation() const {
538
2/2
✓ Branch 3 → 4 taken 1207 times.
✓ Branch 3 → 5 taken 65 times.
1272 if (!isHeap())
539 1207 return false;
540 // We only need de-allocation, if we directly point to a heap-allocated type
541 // e.g. for heap TestStruct** we don't need to de-allocate, since it is a non-owning pointer to an owning pointer
542
2/4
✓ Branch 6 → 7 taken 65 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 65 times.
✗ Branch 8 → 10 not taken.
65 return isPtr() && !isPtrTo(TY_PTR);
543 }
544
545 /**
546 * Get the name of the symbol type as a string
547 *
548 * @param name Name stream
549 * @param withSize Include the array size for sized types
550 * @param ignorePublic Ignore any potential public qualifier
551 */
552 423265 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic) const {
553 // Append the qualifiers
554
3/6
✓ Branch 2 → 3 taken 423265 times.
✗ Branch 2 → 31 not taken.
✓ Branch 3 → 4 taken 423265 times.
✗ Branch 3 → 31 not taken.
✓ Branch 4 → 5 taken 423265 times.
✗ Branch 4 → 31 not taken.
423265 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
555
5/6
✓ Branch 5 → 6 taken 277866 times.
✓ Branch 5 → 9 taken 145399 times.
✓ Branch 6 → 7 taken 97620 times.
✓ Branch 6 → 9 taken 180246 times.
✓ Branch 7 → 8 taken 97620 times.
✗ Branch 7 → 9 not taken.
423265 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
556
1/2
✓ Branch 8 → 9 taken 97620 times.
✗ Branch 8 → 32 not taken.
97620 name << "public ";
557
3/4
✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 12 taken 423261 times.
✓ Branch 10 → 11 taken 4 times.
✗ Branch 10 → 12 not taken.
423265 if (qualifiers.isComposition && !defaultForSuperType.isComposition)
558
1/2
✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 32 not taken.
4 name << "compose ";
559
8/8
✓ Branch 12 → 13 taken 47176 times.
✓ Branch 12 → 17 taken 376089 times.
✓ Branch 13 → 14 taken 45957 times.
✓ Branch 13 → 17 taken 1219 times.
✓ Branch 15 → 16 taken 36279 times.
✓ Branch 15 → 17 taken 9678 times.
✓ Branch 18 → 19 taken 36279 times.
✓ Branch 18 → 20 taken 386986 times.
423265 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
560
1/2
✓ Branch 19 → 20 taken 36279 times.
✗ Branch 19 → 32 not taken.
36279 name << "const ";
561
3/4
✓ Branch 20 → 21 taken 17660 times.
✓ Branch 20 → 23 taken 405605 times.
✓ Branch 21 → 22 taken 17660 times.
✗ Branch 21 → 23 not taken.
423265 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
562
1/2
✓ Branch 22 → 23 taken 17660 times.
✗ Branch 22 → 32 not taken.
17660 name << "heap ";
563
4/4
✓ Branch 23 → 24 taken 42067 times.
✓ Branch 23 → 26 taken 381198 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 26 taken 42066 times.
423265 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
564
1/2
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 32 not taken.
1 name << "signed ";
565
4/4
✓ Branch 26 → 27 taken 381198 times.
✓ Branch 26 → 29 taken 42067 times.
✓ Branch 27 → 28 taken 40136 times.
✓ Branch 27 → 29 taken 341062 times.
423265 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
566
1/2
✓ Branch 28 → 29 taken 40136 times.
✗ Branch 28 → 32 not taken.
40136 name << "unsigned ";
567
568 // Loop through all chain elements
569
1/2
✓ Branch 29 → 30 taken 423265 times.
✗ Branch 29 → 32 not taken.
423265 type->getName(name, withSize, ignorePublic);
570 423265 }
571
572 /**
573 * Get the name of the symbol type as a string
574 *
575 * @param withSize Include the array size for sized types
576 * @param ignorePublic Ignore any potential public qualifier
577 * @return Symbol type name
578 */
579 243487 std::string QualType::getName(bool withSize, bool ignorePublic) const {
580
1/2
✓ Branch 2 → 3 taken 243487 times.
✗ Branch 2 → 11 not taken.
243487 std::stringstream name;
581
1/2
✓ Branch 3 → 4 taken 243487 times.
✗ Branch 3 → 9 not taken.
243487 getName(name, withSize, ignorePublic);
582
1/2
✓ Branch 4 → 5 taken 243487 times.
✗ Branch 4 → 9 not taken.
486974 return name.str();
583 243487 }
584
585 /**
586 * Convert the type to an LLVM type
587 *
588 * @param sourceFile Source file
589 * @return LLVM type
590 */
591 223818 llvm::Type *QualType::toLLVMType(SourceFile *sourceFile) const { return sourceFile->getLLVMType(type); }
592
593 /**
594 * Retrieve the pointer type to this type
595 *
596 * @param node ASTNode
597 * @return New type
598 */
599 15203 QualType QualType::toPtr(const ASTNode *node) const {
600 15203 QualType newType = *this;
601
2/2
✓ Branch 2 → 3 taken 15201 times.
✓ Branch 2 → 5 taken 2 times.
15203 newType.type = type->toPtr(node);
602 15201 return newType;
603 }
604
605 /**
606 * Retrieve the reference type to this type
607 *
608 * @param node ASTNode
609 * @return New type
610 */
611 11667 QualType QualType::toRef(const ASTNode *node) const {
612 11667 QualType newType = *this;
613
1/2
✓ Branch 2 → 3 taken 11667 times.
✗ Branch 2 → 5 not taken.
11667 newType.type = type->toRef(node);
614 11667 return newType;
615 }
616
617 /**
618 * Retrieve the const reference type of this type
619 *
620 * @param node ASTNode
621 * @return New type
622 */
623 3848 QualType QualType::toConstRef(const ASTNode *node) const {
624
1/2
✓ Branch 2 → 3 taken 3848 times.
✗ Branch 2 → 6 not taken.
3848 QualType newType = toRef(node);
625 3848 newType.makeConst();
626 3848 return newType;
627 }
628
629 /**
630 * Retrieve the array type of this type
631 *
632 * @param node ASTNode
633 * @param size Array size
634 * @param skipDynCheck Skip dynamic check
635 * @return New type
636 */
637 218 QualType QualType::toArr(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
638 218 QualType newType = *this;
639
2/2
✓ Branch 2 → 3 taken 217 times.
✓ Branch 2 → 5 taken 1 time.
218 newType.type = type->toArr(node, size, skipDynCheck);
640 217 return newType;
641 }
642
643 /**
644 * Retrieve the non-const type of this type
645 *
646 * @return New type
647 */
648 1883 QualType QualType::toNonConst() const {
649 1883 QualType newType = *this;
650 1883 newType.qualifiers.isConst = false;
651 1883 return newType;
652 }
653
654 /**
655 * Retrieve the contained type of this type
656 * This works on pointers, arrays, references and strings (which alias with char*)
657 *
658 * @return New type
659 */
660 58542 QualType QualType::getContained() const {
661
2/4
✓ Branch 2 → 3 taken 58542 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 58542 times.
58542 assert(isOneOf({TY_PTR, TY_REF, TY_ARRAY, TY_STRING}));
662 58542 QualType newType = *this;
663
1/2
✓ Branch 5 → 6 taken 58542 times.
✗ Branch 5 → 9 not taken.
58542 newType.type = type->getContained();
664 58542 return newType;
665 }
666
667 /**
668 * Retrieve the base type of this type
669 *
670 * @return New type
671 */
672 749775 QualType QualType::getBase() const {
673 749775 QualType newType = *this;
674
1/2
✓ Branch 2 → 3 taken 749775 times.
✗ Branch 2 → 5 not taken.
749775 newType.type = type->getBase();
675 749775 return newType;
676 }
677
678 /**
679 * Get aliased type for an alias type
680 *
681 * @param aliasEntry Entry of the alias definition
682 * @return Aliased type
683 */
684 983 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
685
2/4
✓ Branch 2 → 3 taken 983 times.
✗ Branch 2 → 18 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 983 times.
983 assert(is(TY_ALIAS));
686 // Get type of aliased type container entry
687
1/2
✓ Branch 5 → 6 taken 983 times.
✗ Branch 5 → 18 not taken.
983 const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
688
1/2
✓ Branch 6 → 7 taken 983 times.
✗ Branch 6 → 16 not taken.
983 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
689
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 983 times.
983 assert(aliasedTypeContainerEntry != nullptr);
690
1/2
✓ Branch 11 → 12 taken 983 times.
✗ Branch 11 → 16 not taken.
1966 return aliasedTypeContainerEntry->getQualType();
691 983 }
692
693 /**
694 * Remove reference of this type, if it is a reference
695 *
696 * @return New type
697 */
698
2/2
✓ Branch 3 → 4 taken 4907 times.
✓ Branch 3 → 5 taken 190816 times.
195723 QualType QualType::removeReferenceWrapper() const { return isRef() ? getContained() : *this; }
699
700 /**
701 * Auto-dereference the given symbol type (peeling off all ptr/ref wrappers).
702 * This process is NOT equivalent with getBase() because getBase() also removes e.g. array wrappers
703 *
704 * @return New type
705 */
706 21842 QualType QualType::autoDeReference() const {
707 21842 QualType newType = *this;
708
3/4
✓ Branch 5 → 6 taken 40383 times.
✗ Branch 5 → 10 not taken.
✓ Branch 6 → 3 taken 18541 times.
✓ Branch 6 → 7 taken 21842 times.
40383 while (newType.isOneOf({TY_PTR, TY_REF}))
709
1/2
✓ Branch 3 → 4 taken 18541 times.
✗ Branch 3 → 9 not taken.
18541 newType = newType.getContained();
710 21842 return newType;
711 }
712
713 /**
714 * Replace the base type with another one
715 *
716 * @param newBaseType New base type
717 * @return New type
718 */
719 16003 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
720 // Create new type
721
1/2
✓ Branch 3 → 4 taken 16003 times.
✗ Branch 3 → 9 not taken.
16003 const Type *newType = type->replaceBase(newBaseType.getType());
722 // Create new qualifiers
723
1/2
✓ Branch 4 → 5 taken 16003 times.
✗ Branch 4 → 9 not taken.
16003 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
724 // Return the new qualified type
725 16003 return {newType, newQualifiers};
726 }
727
728 /**
729 * Retrieve the same type, but with lambda captures enabled
730 *
731 * @return Same type with lambda captures
732 */
733 45 QualType QualType::getWithLambdaCaptures(bool enabled /*=true*/) const {
734 // Create new type
735 45 const Type *newType = type->getWithLambdaCaptures(enabled);
736 // Return the new qualified type
737 45 return {newType, qualifiers};
738 }
739
740 /**
741 * Retrieve the same type, but with a new body scope
742 *
743 * @return Same type with body scope
744 */
745 22337 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
746 // Create new type
747 22337 const Type *newType = type->getWithBodyScope(bodyScope);
748 // Return the new qualified type
749 22337 return {newType, qualifiers};
750 }
751
752 /**
753 * Retrieve the same type, but with new template types
754 *
755 * @param templateTypes New template types
756 * @return Same type with new template types
757 */
758 3513 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
759 // Create new type
760 3513 const Type *newType = type->getWithTemplateTypes(templateTypes);
761 // Return the new qualified type
762 3513 return {newType, qualifiers};
763 }
764
765 /**
766 * Retrieve the same type, but with new base template types
767 *
768 * @param templateTypes New base template types
769 * @return Same type with new base template types
770 */
771 4677 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
772 // Create new type
773 4677 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
774 // Return the new qualified type
775 4677 return {newType, qualifiers};
776 }
777
778 /**
779 * Retrieve the same type, but with new function parameter and return types
780 *
781 * @param paramAndReturnTypes New parameter types
782 * @return Same type with new parameter types
783 */
784 12950 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
785 // Create new type
786 12950 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
787 // Return the new qualified type
788 12950 return {newType, qualifiers};
789 }
790
791 12931 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
792
1/2
✓ Branch 2 → 3 taken 12931 times.
✗ Branch 2 → 15 not taken.
12931 QualTypeList paramAndReturnTypes = paramTypes;
793
1/2
✓ Branch 5 → 6 taken 12931 times.
✗ Branch 5 → 11 not taken.
12931 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
794
1/2
✓ Branch 6 → 7 taken 12931 times.
✗ Branch 6 → 13 not taken.
25862 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
795 12931 }
796
797 /**
798 * Check if the current type is const
799 *
800 * Examples for const types:
801 * - const int
802 * - const TestStruct
803 * - const string
804 *
805 * Examples for non-const types:
806 * - double (reason: not marked const)
807 * - const int* (reason: pointer to const int is not const itself)
808 * - const TestStruct& (reason: reference to const TestStruct is not const itself)
809 *
810 * @return Is const or not
811 */
812
4/4
✓ Branch 3 → 4 taken 26576 times.
✓ Branch 3 → 6 taken 2747 times.
✓ Branch 4 → 5 taken 4079 times.
✓ Branch 4 → 6 taken 22497 times.
29323 bool QualType::isConst() const { return isExtendedPrimitive() && qualifiers.isConst; }
813
814 /**
815 * Check if the current type is marked signed
816 *
817 * @return Is signed or not
818 */
819 14277 bool QualType::isSigned() const {
820
2/4
✓ Branch 2 → 3 taken 14277 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 14277 times.
14277 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
821 14277 return qualifiers.isSigned;
822 }
823
824 /**
825 * Check if the current type is marked unsigned
826 *
827 * @return Is unsigned or not
828 */
829 bool QualType::isUnsigned() const {
830 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
831 return qualifiers.isUnsigned;
832 }
833
834 /**
835 * Check if the current type is marked inline
836 *
837 * @return Is inline or not
838 */
839 9602 bool QualType::isInline() const {
840
2/4
✓ Branch 2 → 3 taken 9602 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 9602 times.
9602 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
841 9602 return qualifiers.isInline;
842 }
843
844 /**
845 * Check if the current type is marked public
846 *
847 * @return Is public or not
848 */
849 20100 bool QualType::isPublic() const {
850
5/8
✓ Branch 2 → 3 taken 20100 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 18796 times.
✓ Branch 3 → 7 taken 1304 times.
✓ Branch 4 → 5 taken 18796 times.
✗ Branch 4 → 9 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 18796 times.
20100 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
851 20100 return qualifiers.isPublic;
852 }
853
854 /**
855 * Check if the current type is marked heap
856 *
857 * @return Is heap or not
858 */
859 11850 bool QualType::isHeap() const { return qualifiers.isHeap; }
860
861 /**
862 * Check if the current type is marked as composition
863 *
864 * @return Is composition or not
865 */
866 41 bool QualType::isComposition() const { return qualifiers.isComposition; }
867
868 /**
869 * Make the current type const
870 *
871 * @param isConst Is const or not
872 */
873 3848 void QualType::makeConst(bool isConst) { qualifiers.isConst = isConst; }
874
875 /**
876 * Make the current type unsigned
877 *
878 * @param isUnsigned Is unsigned or not
879 */
880 14 void QualType::makeUnsigned(bool isUnsigned) {
881
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}));
882 14 qualifiers.isSigned = !isUnsigned;
883 14 qualifiers.isUnsigned = isUnsigned;
884 14 }
885
886 /**
887 * Make the current type public
888 *
889 * @param isPublic Is public or not
890 */
891 360 void QualType::makePublic(bool isPublic) {
892
4/8
✓ Branch 2 → 3 taken 360 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 360 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 360 times.
✗ Branch 4 → 8 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 360 times.
360 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
893 360 qualifiers.isPublic = isPublic;
894 360 }
895
896 /**
897 * Make the current type heap
898 *
899 * @param isHeap Is heap or not
900 */
901 63 void QualType::makeHeap(bool isHeap) { qualifiers.isHeap = isHeap; }
902
903 /**
904 * Check if two types are equal
905 *
906 * @param lhs Left-hand side type
907 * @param rhs Right-hand side type
908 * @return Equal or not
909 */
910 30596 bool operator==(const QualType &lhs, const QualType &rhs) { return lhs.type == rhs.type; }
911
912 /**
913 * Check if two types are not equal
914 *
915 * @param lhs Left-hand side type
916 * @param rhs Right-hand side type
917 * @return Not equal or not
918 */
919 1732 bool operator!=(const QualType &lhs, const QualType &rhs) { return !(lhs == rhs); }
920
921 /**
922 * Remove pointers / arrays / references if both types have them as far as possible.
923 * Furthermore, remove reference wrappers if possible.
924 *
925 * @param typeA Candidate type
926 * @param typeB Requested type
927 */
928 82075 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
929
930 } // namespace spice::compiler
931