GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/QualType.cpp
Date: 2025-06-14 23:29:02
Exec Total Coverage
Lines: 268 277 96.8%
Functions: 83 86 96.5%
Branches: 226 372 60.8%

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 4224074 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), qualifiers(TypeQualifiers::of(superType)) {}
19 1532 QualType::QualType(SuperType superType, const std::string &subType)
20 1532 : type(TypeRegistry::getOrInsert(superType, subType)), qualifiers(TypeQualifiers::of(superType)) {}
21 47643 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 743363 SuperType QualType::getSuperType() const { return type->getSuperType(); }
29
30 /**
31 * Get the subtype of the underlying type
32 *
33 * @return Subtype
34 */
35 192590 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 123179 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 82591 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 13251 Struct *QualType::getStruct(const ASTNode *node, const QualTypeList &templateTypes) const {
94
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 13251 times.
13251 assert(is(TY_STRUCT));
95 13251 Scope *structDefScope = getBodyScope()->parent;
96 13251 const std::string &structName = getSubType();
97 13251 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 7629 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 284 Struct *QualType::getStructAndAdjustType(const ASTNode *node, const QualTypeList &templateTypes) {
117 284 Struct *spiceStruct = getStruct(node, templateTypes);
118
2/4
✓ Branch 0 (4→5) taken 284 times.
✗ Branch 1 (4→11) not taken.
✓ Branch 2 (5→6) taken 284 times.
✗ Branch 3 (5→9) not taken.
284 type = type->getWithBodyScope(spiceStruct->scope)->getWithTemplateTypes(spiceStruct->getTemplateTypes());
119 284 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 1002 Interface *QualType::getInterface(const ASTNode *node, const QualTypeList &templateTypes) const {
139
2/4
✓ Branch 0 (2→3) taken 1002 times.
✗ Branch 1 (2→15) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 1002 times.
1002 assert(is(TY_INTERFACE));
140
1/2
✓ Branch 0 (5→6) taken 1002 times.
✗ Branch 1 (5→15) not taken.
1002 Scope *interfaceDefScope = getBodyScope()->parent;
141
2/4
✓ Branch 0 (6→7) taken 1002 times.
✗ Branch 1 (6→15) not taken.
✓ Branch 2 (7→8) taken 1002 times.
✗ Branch 3 (7→15) not taken.
1002 const std::string structName = getSubType();
142
1/2
✓ Branch 0 (8→9) taken 1002 times.
✗ Branch 1 (8→13) not taken.
2004 return InterfaceManager::match(interfaceDefScope, structName, templateTypes, node);
143 1002 }
144
145 /**
146 * Get the interface instance for an interface type
147 *
148 * @param node Accessing AST node
149 * @return Interface instance
150 */
151 590 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 2468388 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 495152 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 575894 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 1197 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 73610 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 148760 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 0 (2→3) taken 23644 times.
✗ Branch 1 (2→12) not taken.
✓ Branch 2 (3→4) taken 158 times.
✓ Branch 3 (3→8) taken 23486 times.
✓ Branch 4 (4→5) taken 158 times.
✗ Branch 5 (4→12) not taken.
✓ Branch 6 (5→6) taken 158 times.
✗ Branch 7 (5→12) not taken.
✓ Branch 8 (6→7) taken 2 times.
✓ Branch 9 (6→8) taken 156 times.
23644 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 392962 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 29503 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 0 (2→3) taken 1 times.
✗ Branch 1 (2→12) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→8) taken 1 times.
✗ Branch 4 (4→5) not taken.
✗ Branch 5 (4→12) not taken.
✗ Branch 6 (5→6) not taken.
✗ Branch 7 (5→12) not taken.
✗ Branch 8 (6→7) not taken.
✗ Branch 9 (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 0 (2→3) taken 294 times.
✓ Branch 1 (2→6) taken 267 times.
✓ Branch 2 (4→5) taken 290 times.
✓ Branch 3 (4→6) taken 4 times.
561 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 104 bool QualType::isIterator(const ASTNode *node) const {
255 // The type must be a struct that implements the iterator interface
256
3/4
✓ Branch 0 (2→3) taken 104 times.
✗ Branch 1 (2→47) not taken.
✓ Branch 2 (3→4) taken 1 times.
✓ Branch 3 (3→5) taken 103 times.
104 if (!is(TY_STRUCT))
257 1 return false;
258
259
2/4
✓ Branch 0 (7→8) taken 103 times.
✗ Branch 1 (7→30) not taken.
✓ Branch 2 (8→9) taken 103 times.
✗ Branch 3 (8→28) not taken.
103 const QualType genericType(TY_GENERIC, "T");
260 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
261
3/6
✓ Branch 0 (13→14) taken 103 times.
✗ Branch 1 (13→42) not taken.
✓ Branch 2 (16→17) taken 103 times.
✗ Branch 3 (16→36) not taken.
✓ Branch 4 (17→18) taken 103 times.
✗ Branch 5 (17→34) not taken.
412 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERATOR_INTERFACE, data, {genericType});
262
1/2
✓ Branch 0 (22→23) taken 103 times.
✗ Branch 1 (22→47) not taken.
103 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
263
1/2
✓ Branch 0 (24→25) taken 103 times.
✗ Branch 1 (24→47) not taken.
103 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 106 bool QualType::isIterable(const ASTNode *node) const {
275 // Arrays are always considered iterable
276
3/4
✓ Branch 0 (2→3) taken 106 times.
✗ Branch 1 (2→50) not taken.
✓ Branch 2 (3→4) taken 8 times.
✓ Branch 3 (3→5) taken 98 times.
106 if (isArray())
277 8 return true;
278 // Otherwise the type must be a struct that implements the iterator interface
279
3/4
✓ Branch 0 (5→6) taken 98 times.
✗ Branch 1 (5→50) not taken.
✓ Branch 2 (6→7) taken 1 times.
✓ Branch 3 (6→8) taken 97 times.
98 if (!is(TY_STRUCT))
280 1 return false;
281
282
2/4
✓ Branch 0 (10→11) taken 97 times.
✗ Branch 1 (10→33) not taken.
✓ Branch 2 (11→12) taken 97 times.
✗ Branch 3 (11→31) not taken.
97 const QualType genericType(TY_GENERIC, "T");
283 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
284
3/6
✓ Branch 0 (16→17) taken 97 times.
✗ Branch 1 (16→45) not taken.
✓ Branch 2 (19→20) taken 97 times.
✗ Branch 3 (19→39) not taken.
✓ Branch 4 (20→21) taken 97 times.
✗ Branch 5 (20→37) not taken.
388 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERABLE_INTERFACE, data, {genericType});
285
1/2
✓ Branch 0 (25→26) taken 97 times.
✗ Branch 1 (25→50) not taken.
97 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
286
1/2
✓ Branch 0 (27→28) taken 97 times.
✗ Branch 1 (27→50) not taken.
97 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 668 bool QualType::isStringObj() const {
295
4/6
✓ Branch 0 (3→4) taken 116 times.
✓ Branch 1 (3→10) taken 552 times.
✓ Branch 2 (6→7) taken 116 times.
✗ Branch 3 (6→10) not taken.
✓ Branch 4 (8→9) taken 116 times.
✗ Branch 5 (8→10) not taken.
668 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 615 bool QualType::isErrorObj() const {
304
3/6
✓ Branch 0 (3→4) taken 615 times.
✗ Branch 1 (3→10) not taken.
✓ Branch 2 (6→7) taken 615 times.
✗ Branch 3 (6→10) not taken.
✓ Branch 4 (8→9) taken 615 times.
✗ Branch 5 (8→10) not taken.
615 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 275953 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 667 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
322
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 667 times.
667 assert(!hasAnyGenericParts());
323
324 // Heap-allocated values may not be copied via memcpy
325
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→7) taken 667 times.
667 if (qualifiers.isHeap)
326 return false;
327
328 // References can't be copied at all
329
1/2
✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 667 times.
667 if (isRef())
330 return false;
331
332 // In case of an array, the item type is determining the copy triviality
333
2/2
✓ Branch 0 (11→12) taken 8 times.
✓ Branch 1 (11→16) taken 659 times.
667 if (isArray())
334
2/4
✓ Branch 0 (12→13) taken 8 times.
✗ Branch 1 (12→39) not taken.
✓ Branch 2 (13→14) taken 8 times.
✗ Branch 3 (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 0 (17→18) taken 197 times.
✓ Branch 1 (17→37) taken 462 times.
659 if (is(TY_STRUCT)) {
338 // If the struct has a copy ctor, it is a non-trivially copyable one
339
1/2
✓ Branch 0 (18→19) taken 197 times.
✗ Branch 1 (18→54) not taken.
197 const Struct *spiceStruct = getStruct(node);
340
2/4
✓ Branch 0 (19→20) taken 197 times.
✗ Branch 1 (19→43) not taken.
✓ Branch 2 (23→24) taken 197 times.
✗ Branch 3 (23→40) not taken.
591 const std::vector args = {Arg(toConstRef(node), false)};
341
2/4
✓ Branch 0 (27→28) taken 197 times.
✗ Branch 1 (27→48) not taken.
✓ Branch 2 (28→29) taken 197 times.
✗ Branch 3 (28→46) not taken.
197 const Function *copyCtor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, args, true);
342
2/2
✓ Branch 0 (31→32) taken 84 times.
✓ Branch 1 (31→33) taken 113 times.
197 if (copyCtor != nullptr)
343 84 return false;
344
345 // Check if all member types are trivially copyable
346 224 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
347
1/2
✓ Branch 0 (33→34) taken 113 times.
✗ Branch 1 (33→52) not taken.
113 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
348 197 }
349
350 462 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 7101 bool QualType::isTriviallyDestructible(const ASTNode *node) const {
361
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 7101 times.
7101 assert(!hasAnyGenericParts());
362
363 // Heap-allocated values require manual de-allocation, which is done in the default/explicit dtor
364
2/2
✓ Branch 0 (5→6) taken 443 times.
✓ Branch 1 (5→7) taken 6658 times.
7101 if (qualifiers.isHeap)
365 443 return false;
366
367 // In case of an array, the item type is determining the destructing triviality
368
2/2
✓ Branch 0 (8→9) taken 5 times.
✓ Branch 1 (8→13) taken 6653 times.
6658 if (isArray())
369
2/4
✓ Branch 0 (9→10) taken 5 times.
✗ Branch 1 (9→31) not taken.
✓ Branch 2 (10→11) taken 5 times.
✗ Branch 3 (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 0 (14→15) taken 3701 times.
✓ Branch 1 (14→29) taken 2952 times.
6653 if (is(TY_STRUCT)) {
373 // If the struct has a dtor, it is a non-trivially destructible one
374
1/2
✓ Branch 0 (15→16) taken 3701 times.
✗ Branch 1 (15→41) not taken.
3701 const Struct *spiceStruct = getStruct(node);
375
2/4
✓ Branch 0 (19→20) taken 3701 times.
✗ Branch 1 (19→34) not taken.
✓ Branch 2 (20→21) taken 3701 times.
✗ Branch 3 (20→32) not taken.
11103 const Function *dtor = FunctionManager::lookup(spiceStruct->scope, DTOR_FUNCTION_NAME, *this, {}, true);
376
2/2
✓ Branch 0 (24→25) taken 1530 times.
✓ Branch 1 (24→26) taken 2171 times.
3701 if (dtor != nullptr)
377 1530 return false;
378
379 // Check if all member types are trivially destructible
380 3797 const auto pred = [&](const QualType &fieldType) {
381 3797 return fieldType.isTriviallyDestructible(node);
382 2171 }; // NOLINT(*-no-recursion)
383
1/2
✓ Branch 0 (26→27) taken 2171 times.
✗ Branch 1 (26→41) not taken.
2171 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
384 }
385
386 2952 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 200 bool QualType::doesImplement(const QualType &implementedInterfaceType, const ASTNode *node) const {
397
2/4
✓ Branch 0 (3→4) taken 200 times.
✗ Branch 1 (3→7) not taken.
✓ Branch 2 (5→6) taken 200 times.
✗ Branch 3 (5→7) not taken.
200 assert(is(TY_STRUCT) && implementedInterfaceType.is(TY_INTERFACE));
398 200 const Struct *spiceStruct = getStruct(node);
399
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 200 times.
200 assert(spiceStruct != nullptr);
400 200 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
401
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 200 times.
200 assert(interfaceType.is(TY_INTERFACE));
402 200 return implementedInterfaceType.matches(interfaceType, false, false, true);
403 200 });
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 11242 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
414
8/8
✓ Branch 0 (2→3) taken 3105 times.
✓ Branch 1 (2→9) taken 8137 times.
✓ Branch 2 (4→5) taken 2901 times.
✓ Branch 3 (4→9) taken 204 times.
✓ Branch 4 (6→7) taken 276 times.
✓ Branch 5 (6→9) taken 2625 times.
✓ Branch 6 (8→9) taken 274 times.
✓ Branch 7 (8→10) taken 2 times.
11242 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 94499 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
428 // Compare type
429
2/2
✓ Branch 0 (3→4) taken 41141 times.
✓ Branch 1 (3→5) taken 53358 times.
94499 if (!type->matches(otherType.type, ignoreArraySize))
430 41141 return false;
431
432 // Ignore or compare qualifiers
433
4/4
✓ Branch 0 (5→6) taken 11027 times.
✓ Branch 1 (5→8) taken 42331 times.
✓ Branch 2 (7→8) taken 10914 times.
✓ Branch 3 (7→9) taken 113 times.
53358 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 51124 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
444
8/10
✓ Branch 0 (2→3) taken 51124 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 160 times.
✓ Branch 3 (3→6) taken 50964 times.
✓ Branch 4 (4→5) taken 160 times.
✗ Branch 5 (4→17) not taken.
✓ Branch 6 (5→6) taken 29 times.
✓ Branch 7 (5→7) taken 131 times.
✓ Branch 8 (8→9) taken 50993 times.
✓ Branch 9 (8→10) taken 131 times.
51124 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
445 50993 return false;
446
447 // Check if the rhs is a struct type that implements the lhs interface type
448
1/2
✓ Branch 0 (10→11) taken 131 times.
✗ Branch 1 (10→17) not taken.
131 const Struct *spiceStruct = structType.getStruct(nullptr);
449
1/2
✗ Branch 0 (11→12) not taken.
✓ Branch 1 (11→13) taken 131 times.
131 assert(spiceStruct != nullptr);
450 127 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
451
1/2
✓ Branch 0 (13→14) taken 131 times.
✗ Branch 1 (13→17) not taken.
131 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 1825 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 17958 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
469
2/2
✓ Branch 0 (3→4) taken 13217 times.
✓ Branch 1 (3→5) taken 4741 times.
17958 if (!is(TY_STRUCT))
470 13217 return false;
471
472 // If no type was set by a previous iteration, we set it to the current type
473
2/2
✓ Branch 0 (5→6) taken 3477 times.
✓ Branch 1 (5→7) taken 1264 times.
4741 if (typeToCompareWith == nullptr)
474 3477 typeToCompareWith = this;
475
476 4741 Scope *baseTypeBodyScope = getBodyScope();
477
2/2
✓ Branch 0 (24→9) taken 14389 times.
✓ Branch 1 (24→25) taken 4541 times.
18930 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
478
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 14389 times.
14389 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
479 14389 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 0 (15→16) taken 14389 times.
✗ Branch 1 (15→27) not taken.
✓ Branch 2 (17→18) taken 200 times.
✓ Branch 3 (17→19) taken 14189 times.
14389 if (fieldType.getBase() == *typeToCompareWith)
483 200 return true;
484
485 // If the field is a struct, check if it is a self-referencing struct type
486
1/2
✗ Branch 0 (20→21) not taken.
✓ Branch 1 (20→22) taken 14189 times.
14189 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
487 return true;
488 }
489 4541 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 20814 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
499
1/2
✓ Branch 0 (2→3) taken 20814 times.
✗ Branch 1 (2→19) not taken.
20814 const QualType baseType = getBase();
500 // Check if the symbol type itself is generic
501
3/4
✓ Branch 0 (3→4) taken 20814 times.
✗ Branch 1 (3→19) not taken.
✓ Branch 2 (4→5) taken 3818 times.
✓ Branch 3 (4→7) taken 16996 times.
20814 if (baseType.is(TY_GENERIC)) {
502
1/2
✓ Branch 0 (5→6) taken 3818 times.
✗ Branch 1 (5→19) not taken.
3818 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
503
2/2
✓ Branch 0 (3→4) taken 3810 times.
✓ Branch 1 (3→5) taken 663 times.
4473 if (baseType.matches(t, true, true, true)) {
504 3810 t.used = true;
505 3810 return true;
506 }
507 663 return false;
508 3818 });
509 }
510
511 // If the type is non-generic check template types
512 16996 bool covered = true;
513 // Check template types
514
1/2
✓ Branch 0 (7→8) taken 16996 times.
✗ Branch 1 (7→19) not taken.
16996 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
515 1543 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
516 1543 return templateType.isCoveredByGenericTypeList(genericTypeList);
517 16996 };
518
1/2
✓ Branch 0 (8→9) taken 16996 times.
✗ Branch 1 (8→19) not taken.
16996 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
519
520 // If function/procedure, check param and return types
521
3/4
✓ Branch 0 (9→10) taken 16996 times.
✗ Branch 1 (9→17) not taken.
✓ Branch 2 (10→11) taken 29 times.
✓ Branch 3 (10→14) taken 16967 times.
16996 if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
522
1/2
✓ Branch 0 (11→12) taken 29 times.
✗ Branch 1 (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 0 (12→13) taken 29 times.
✗ Branch 1 (12→18) not taken.
29 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
527 }
528
529 16996 return covered;
530 }
531
532 /**
533 * Check if the current type needs de-allocation
534 *
535 * @return Needs de-allocation or not
536 */
537 1126 bool QualType::needsDeAllocation() const {
538
2/2
✓ Branch 0 (3→4) taken 1077 times.
✓ Branch 1 (3→5) taken 49 times.
1126 if (!isHeap())
539 1077 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 0 (6→7) taken 49 times.
✗ Branch 1 (6→10) not taken.
✓ Branch 2 (8→9) taken 49 times.
✗ Branch 3 (8→10) not taken.
49 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 343642 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic) const {
553 // Append the qualifiers
554
3/6
✓ Branch 0 (2→3) taken 343642 times.
✗ Branch 1 (2→31) not taken.
✓ Branch 2 (3→4) taken 343642 times.
✗ Branch 3 (3→31) not taken.
✓ Branch 4 (4→5) taken 343642 times.
✗ Branch 5 (4→31) not taken.
343642 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
555
5/6
✓ Branch 0 (5→6) taken 221941 times.
✓ Branch 1 (5→9) taken 121701 times.
✓ Branch 2 (6→7) taken 80898 times.
✓ Branch 3 (6→9) taken 141043 times.
✓ Branch 4 (7→8) taken 80898 times.
✗ Branch 5 (7→9) not taken.
343642 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
556
1/2
✓ Branch 0 (8→9) taken 80898 times.
✗ Branch 1 (8→32) not taken.
80898 name << "public ";
557
3/4
✓ Branch 0 (9→10) taken 4 times.
✓ Branch 1 (9→12) taken 343638 times.
✓ Branch 2 (10→11) taken 4 times.
✗ Branch 3 (10→12) not taken.
343642 if (qualifiers.isComposition && !defaultForSuperType.isComposition)
558
1/2
✓ Branch 0 (11→12) taken 4 times.
✗ Branch 1 (11→32) not taken.
4 name << "compose ";
559
8/8
✓ Branch 0 (12→13) taken 39947 times.
✓ Branch 1 (12→17) taken 303695 times.
✓ Branch 2 (13→14) taken 38939 times.
✓ Branch 3 (13→17) taken 1008 times.
✓ Branch 4 (15→16) taken 29966 times.
✓ Branch 5 (15→17) taken 8973 times.
✓ Branch 6 (18→19) taken 29966 times.
✓ Branch 7 (18→20) taken 313676 times.
343642 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
560
1/2
✓ Branch 0 (19→20) taken 29966 times.
✗ Branch 1 (19→32) not taken.
29966 name << "const ";
561
3/4
✓ Branch 0 (20→21) taken 12892 times.
✓ Branch 1 (20→23) taken 330750 times.
✓ Branch 2 (21→22) taken 12892 times.
✗ Branch 3 (21→23) not taken.
343642 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
562
1/2
✓ Branch 0 (22→23) taken 12892 times.
✗ Branch 1 (22→32) not taken.
12892 name << "heap ";
563
3/4
✓ Branch 0 (23→24) taken 31961 times.
✓ Branch 1 (23→26) taken 311681 times.
✗ Branch 2 (24→25) not taken.
✓ Branch 3 (24→26) taken 31961 times.
343642 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
564 name << "signed ";
565
4/4
✓ Branch 0 (26→27) taken 311681 times.
✓ Branch 1 (26→29) taken 31961 times.
✓ Branch 2 (27→28) taken 32974 times.
✓ Branch 3 (27→29) taken 278707 times.
343642 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
566
1/2
✓ Branch 0 (28→29) taken 32974 times.
✗ Branch 1 (28→32) not taken.
32974 name << "unsigned ";
567
568 // Loop through all chain elements
569
1/2
✓ Branch 0 (29→30) taken 343642 times.
✗ Branch 1 (29→32) not taken.
343642 type->getName(name, withSize, ignorePublic);
570 343642 }
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 217327 std::string QualType::getName(bool withSize, bool ignorePublic) const {
580
1/2
✓ Branch 0 (2→3) taken 217327 times.
✗ Branch 1 (2→11) not taken.
217327 std::stringstream name;
581
1/2
✓ Branch 0 (3→4) taken 217327 times.
✗ Branch 1 (3→9) not taken.
217327 getName(name, withSize, ignorePublic);
582
1/2
✓ Branch 0 (4→5) taken 217327 times.
✗ Branch 1 (4→9) not taken.
434654 return name.str();
583 217327 }
584
585 /**
586 * Convert the type to an LLVM type
587 *
588 * @param sourceFile Source file
589 * @return LLVM type
590 */
591 203529 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 13101 QualType QualType::toPtr(const ASTNode *node) const {
600 13101 QualType newType = *this;
601
2/2
✓ Branch 0 (2→3) taken 13099 times.
✓ Branch 1 (2→5) taken 2 times.
13101 newType.type = type->toPtr(node);
602 13099 return newType;
603 }
604
605 /**
606 * Retrieve the reference type to this type
607 *
608 * @param node ASTNode
609 * @return New type
610 */
611 10571 QualType QualType::toRef(const ASTNode *node) const {
612 10571 QualType newType = *this;
613
1/2
✓ Branch 0 (2→3) taken 10571 times.
✗ Branch 1 (2→5) not taken.
10571 newType.type = type->toRef(node);
614 10571 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 3517 QualType QualType::toConstRef(const ASTNode *node) const {
624
1/2
✓ Branch 0 (2→3) taken 3517 times.
✗ Branch 1 (2→6) not taken.
3517 QualType newType = toRef(node);
625 3517 newType.makeConst();
626 3517 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 0 (2→3) taken 217 times.
✓ Branch 1 (2→5) taken 1 times.
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 1773 QualType QualType::toNonConst() const {
649 1773 QualType newType = *this;
650 1773 newType.qualifiers.isConst = false;
651 1773 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 52239 QualType QualType::getContained() const {
661
2/4
✓ Branch 0 (2→3) taken 52239 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 52239 times.
52239 assert(isOneOf({TY_PTR, TY_REF, TY_ARRAY, TY_STRING}));
662 52239 QualType newType = *this;
663
1/2
✓ Branch 0 (5→6) taken 52239 times.
✗ Branch 1 (5→9) not taken.
52239 newType.type = type->getContained();
664 52239 return newType;
665 }
666
667 /**
668 * Retrieve the base type of this type
669 *
670 * @return New type
671 */
672 642317 QualType QualType::getBase() const {
673 642317 QualType newType = *this;
674
1/2
✓ Branch 0 (2→3) taken 642317 times.
✗ Branch 1 (2→5) not taken.
642317 newType.type = type->getBase();
675 642317 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 934 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
685
2/4
✓ Branch 0 (2→3) taken 934 times.
✗ Branch 1 (2→18) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 934 times.
934 assert(is(TY_ALIAS));
686 // Get type of aliased type container entry
687
1/2
✓ Branch 0 (5→6) taken 934 times.
✗ Branch 1 (5→18) not taken.
934 const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
688
1/2
✓ Branch 0 (6→7) taken 934 times.
✗ Branch 1 (6→16) not taken.
934 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
689
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 934 times.
934 assert(aliasedTypeContainerEntry != nullptr);
690
1/2
✓ Branch 0 (11→12) taken 934 times.
✗ Branch 1 (11→16) not taken.
1868 return aliasedTypeContainerEntry->getQualType();
691 934 }
692
693 /**
694 * Remove reference of this type, if it is a reference
695 *
696 * @return New type
697 */
698
2/2
✓ Branch 0 (3→4) taken 4429 times.
✓ Branch 1 (3→5) taken 169998 times.
174427 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 20271 QualType QualType::autoDeReference() const {
707 20271 QualType newType = *this;
708
3/4
✓ Branch 0 (5→6) taken 37478 times.
✗ Branch 1 (5→10) not taken.
✓ Branch 2 (6→3) taken 17207 times.
✓ Branch 3 (6→7) taken 20271 times.
37478 while (newType.isOneOf({TY_PTR, TY_REF}))
709
1/2
✓ Branch 0 (3→4) taken 17207 times.
✗ Branch 1 (3→9) not taken.
17207 newType = newType.getContained();
710 20271 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 8609 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
720 // Create new type
721
1/2
✓ Branch 0 (3→4) taken 8609 times.
✗ Branch 1 (3→9) not taken.
8609 const Type *newType = type->replaceBase(newBaseType.getType());
722 // Create new qualifiers
723
1/2
✓ Branch 0 (4→5) taken 8609 times.
✗ Branch 1 (4→9) not taken.
8609 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
724 // Return the new qualified type
725 8609 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 19999 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
746 // Create new type
747 19999 const Type *newType = type->getWithBodyScope(bodyScope);
748 // Return the new qualified type
749 19999 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 2831 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
759 // Create new type
760 2831 const Type *newType = type->getWithTemplateTypes(templateTypes);
761 // Return the new qualified type
762 2831 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 3769 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
772 // Create new type
773 3769 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
774 // Return the new qualified type
775 3769 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 11380 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
785 // Create new type
786 11380 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
787 // Return the new qualified type
788 11380 return {newType, qualifiers};
789 }
790
791 11361 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
792
1/2
✓ Branch 0 (2→3) taken 11361 times.
✗ Branch 1 (2→15) not taken.
11361 QualTypeList paramAndReturnTypes = paramTypes;
793
1/2
✓ Branch 0 (5→6) taken 11361 times.
✗ Branch 1 (5→11) not taken.
11361 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
794
1/2
✓ Branch 0 (6→7) taken 11361 times.
✗ Branch 1 (6→13) not taken.
22722 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
795 11361 }
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 0 (3→4) taken 24542 times.
✓ Branch 1 (3→6) taken 2368 times.
✓ Branch 2 (4→5) taken 3918 times.
✓ Branch 3 (4→6) taken 20624 times.
26910 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 12930 bool QualType::isSigned() const {
820
2/4
✓ Branch 0 (2→3) taken 12930 times.
✗ Branch 1 (2→7) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 12930 times.
12930 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
821 12930 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 8352 bool QualType::isInline() const {
840
2/4
✓ Branch 0 (2→3) taken 8352 times.
✗ Branch 1 (2→7) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 8352 times.
8352 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
841 8352 return qualifiers.isInline;
842 }
843
844 /**
845 * Check if the current type is marked public
846 *
847 * @return Is public or not
848 */
849 17801 bool QualType::isPublic() const {
850
5/8
✓ Branch 0 (2→3) taken 17801 times.
✗ Branch 1 (2→9) not taken.
✓ Branch 2 (3→4) taken 16470 times.
✓ Branch 3 (3→7) taken 1331 times.
✓ Branch 4 (4→5) taken 16470 times.
✗ Branch 5 (4→9) not taken.
✗ Branch 6 (5→6) not taken.
✓ Branch 7 (5→7) taken 16470 times.
17801 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
851 17801 return qualifiers.isPublic;
852 }
853
854 /**
855 * Check if the current type is marked heap
856 *
857 * @return Is heap or not
858 */
859 10940 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 3517 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 12 void QualType::makeUnsigned(bool isUnsigned) {
881
2/4
✓ Branch 0 (2→3) taken 12 times.
✗ Branch 1 (2→6) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 12 times.
12 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
882 12 qualifiers.isSigned = !isUnsigned;
883 12 qualifiers.isUnsigned = isUnsigned;
884 12 }
885
886 /**
887 * Make the current type public
888 *
889 * @param isPublic Is public or not
890 */
891 304 void QualType::makePublic(bool isPublic) {
892
4/8
✓ Branch 0 (2→3) taken 304 times.
✗ Branch 1 (2→8) not taken.
✓ Branch 2 (3→4) taken 304 times.
✗ Branch 3 (3→7) not taken.
✓ Branch 4 (4→5) taken 304 times.
✗ Branch 5 (4→8) not taken.
✗ Branch 6 (5→6) not taken.
✓ Branch 7 (5→7) taken 304 times.
304 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
893 304 qualifiers.isPublic = isPublic;
894 304 }
895
896 /**
897 * Make the current type heap
898 *
899 * @param isHeap Is heap or not
900 */
901 48 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 23707 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 1523 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 75128 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
929
930 } // namespace spice::compiler
931