GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/QualType.cpp
Date: 2025-05-08 21:00:15
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 4175514 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), qualifiers(TypeQualifiers::of(superType)) {}
19 1518 QualType::QualType(SuperType superType, const std::string &subType)
20 1518 : type(TypeRegistry::getOrInsert(superType, subType)), qualifiers(TypeQualifiers::of(superType)) {}
21 46951 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 731940 SuperType QualType::getSuperType() const { return type->getSuperType(); }
29
30 /**
31 * Get the subtype of the underlying type
32 *
33 * @return Subtype
34 */
35 189781 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 432 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 121066 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 81137 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 12963 Struct *QualType::getStruct(const ASTNode *node, const QualTypeList &templateTypes) const {
94
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 12963 times.
12963 assert(is(TY_STRUCT));
95 12963 Scope *structDefScope = getBodyScope()->parent;
96 12963 const std::string &structName = getSubType();
97 12963 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 7406 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 282 Struct *QualType::getStructAndAdjustType(const ASTNode *node, const QualTypeList &templateTypes) {
117 282 Struct *spiceStruct = getStruct(node, templateTypes);
118
2/4
✓ Branch 0 (4→5) taken 282 times.
✗ Branch 1 (4→11) not taken.
✓ Branch 2 (5→6) taken 282 times.
✗ Branch 3 (5→9) not taken.
282 type = type->getWithBodyScope(spiceStruct->scope)->getWithTemplateTypes(spiceStruct->getTemplateTypes());
119 282 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 2442197 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 486213 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 560153 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 1141 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 72361 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 146322 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 23264 times.
✗ Branch 1 (2→12) not taken.
✓ Branch 2 (3→4) taken 158 times.
✓ Branch 3 (3→8) taken 23106 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.
23264 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 386361 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 28928 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 288 times.
✓ Branch 1 (2→6) taken 263 times.
✓ Branch 2 (4→5) taken 284 times.
✓ Branch 3 (4→6) taken 4 times.
551 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 663 bool QualType::isStringObj() const {
295
4/6
✓ Branch 0 (3→4) taken 116 times.
✓ Branch 1 (3→10) taken 547 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.
663 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 610 bool QualType::isErrorObj() const {
304
3/6
✓ Branch 0 (3→4) taken 610 times.
✗ Branch 1 (3→10) not taken.
✓ Branch 2 (6→7) taken 610 times.
✗ Branch 3 (6→10) not taken.
✓ Branch 4 (8→9) taken 610 times.
✗ Branch 5 (8→10) not taken.
610 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 271642 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 649 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
322
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 649 times.
649 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 649 times.
649 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 649 times.
649 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 641 times.
649 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 191 times.
✓ Branch 1 (17→37) taken 450 times.
641 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 191 times.
✗ Branch 1 (18→54) not taken.
191 const Struct *spiceStruct = getStruct(node);
340
2/4
✓ Branch 0 (19→20) taken 191 times.
✗ Branch 1 (19→43) not taken.
✓ Branch 2 (23→24) taken 191 times.
✗ Branch 3 (23→40) not taken.
573 const std::vector args = {Arg(toConstRef(node), false)};
341
2/4
✓ Branch 0 (27→28) taken 191 times.
✗ Branch 1 (27→48) not taken.
✓ Branch 2 (28→29) taken 191 times.
✗ Branch 3 (28→46) not taken.
191 const Function *copyCtor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, args, true);
342
2/2
✓ Branch 0 (31→32) taken 83 times.
✓ Branch 1 (31→33) taken 108 times.
191 if (copyCtor != nullptr)
343 83 return false;
344
345 // Check if all member types are trivially copyable
346 214 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
347
1/2
✓ Branch 0 (33→34) taken 108 times.
✗ Branch 1 (33→52) not taken.
108 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
348 191 }
349
350 450 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 6795 bool QualType::isTriviallyDestructible(const ASTNode *node) const {
361
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 6795 times.
6795 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 6352 times.
6795 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 6347 times.
6352 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 3547 times.
✓ Branch 1 (14→29) taken 2800 times.
6347 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 3547 times.
✗ Branch 1 (15→41) not taken.
3547 const Struct *spiceStruct = getStruct(node);
375
2/4
✓ Branch 0 (19→20) taken 3547 times.
✗ Branch 1 (19→34) not taken.
✓ Branch 2 (20→21) taken 3547 times.
✗ Branch 3 (20→32) not taken.
10641 const Function *dtor = FunctionManager::lookup(spiceStruct->scope, DTOR_FUNCTION_NAME, *this, {}, true);
376
2/2
✓ Branch 0 (24→25) taken 1490 times.
✓ Branch 1 (24→26) taken 2057 times.
3547 if (dtor != nullptr)
377 1490 return false;
378
379 // Check if all member types are trivially destructible
380 3574 const auto pred = [&](const QualType &fieldType) {
381 3574 return fieldType.isTriviallyDestructible(node);
382 2057 }; // NOLINT(*-no-recursion)
383
1/2
✓ Branch 0 (26→27) taken 2057 times.
✗ Branch 1 (26→41) not taken.
2057 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
384 }
385
386 2800 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 11034 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
414
8/8
✓ Branch 0 (2→3) taken 3043 times.
✓ Branch 1 (2→9) taken 7991 times.
✓ Branch 2 (4→5) taken 2843 times.
✓ Branch 3 (4→9) taken 200 times.
✓ Branch 4 (6→7) taken 270 times.
✓ Branch 5 (6→9) taken 2573 times.
✓ Branch 6 (8→9) taken 268 times.
✓ Branch 7 (8→10) taken 2 times.
11034 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 92784 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
428 // Compare type
429
2/2
✓ Branch 0 (3→4) taken 40483 times.
✓ Branch 1 (3→5) taken 52301 times.
92784 if (!type->matches(otherType.type, ignoreArraySize))
430 40483 return false;
431
432 // Ignore or compare qualifiers
433
4/4
✓ Branch 0 (5→6) taken 10856 times.
✓ Branch 1 (5→8) taken 41445 times.
✓ Branch 2 (7→8) taken 10743 times.
✓ Branch 3 (7→9) taken 113 times.
52301 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 50147 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
444
8/10
✓ Branch 0 (2→3) taken 50147 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 160 times.
✓ Branch 3 (3→6) taken 49987 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 50016 times.
✓ Branch 9 (8→10) taken 131 times.
50147 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
445 50016 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 1794 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 17808 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
469
2/2
✓ Branch 0 (3→4) taken 13127 times.
✓ Branch 1 (3→5) taken 4681 times.
17808 if (!is(TY_STRUCT))
470 13127 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 3447 times.
✓ Branch 1 (5→7) taken 1234 times.
4681 if (typeToCompareWith == nullptr)
474 3447 typeToCompareWith = this;
475
476 4681 Scope *baseTypeBodyScope = getBodyScope();
477
2/2
✓ Branch 0 (24→9) taken 14269 times.
✓ Branch 1 (24→25) taken 4481 times.
18750 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
478
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 14269 times.
14269 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
479 14269 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 14269 times.
✗ Branch 1 (15→27) not taken.
✓ Branch 2 (17→18) taken 200 times.
✓ Branch 3 (17→19) taken 14069 times.
14269 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 14069 times.
14069 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
487 return true;
488 }
489 4481 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 20498 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
499
1/2
✓ Branch 0 (2→3) taken 20498 times.
✗ Branch 1 (2→19) not taken.
20498 const QualType baseType = getBase();
500 // Check if the symbol type itself is generic
501
3/4
✓ Branch 0 (3→4) taken 20498 times.
✗ Branch 1 (3→19) not taken.
✓ Branch 2 (4→5) taken 3797 times.
✓ Branch 3 (4→7) taken 16701 times.
20498 if (baseType.is(TY_GENERIC)) {
502
1/2
✓ Branch 0 (5→6) taken 3797 times.
✗ Branch 1 (5→19) not taken.
3797 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
503
2/2
✓ Branch 0 (3→4) taken 3789 times.
✓ Branch 1 (3→5) taken 662 times.
4451 if (baseType.matches(t, true, true, true)) {
504 3789 t.used = true;
505 3789 return true;
506 }
507 662 return false;
508 3797 });
509 }
510
511 // If the type is non-generic check template types
512 16701 bool covered = true;
513 // Check template types
514
1/2
✓ Branch 0 (7→8) taken 16701 times.
✗ Branch 1 (7→19) not taken.
16701 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
515 1526 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
516 1526 return templateType.isCoveredByGenericTypeList(genericTypeList);
517 16701 };
518
1/2
✓ Branch 0 (8→9) taken 16701 times.
✗ Branch 1 (8→19) not taken.
16701 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 16701 times.
✗ Branch 1 (9→17) not taken.
✓ Branch 2 (10→11) taken 29 times.
✓ Branch 3 (10→14) taken 16672 times.
16701 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 16701 return covered;
530 }
531
532 /**
533 * Check if the current type needs de-allocation
534 *
535 * @return Needs de-allocation or not
536 */
537 1119 bool QualType::needsDeAllocation() const {
538
2/2
✓ Branch 0 (3→4) taken 1070 times.
✓ Branch 1 (3→5) taken 49 times.
1119 if (!isHeap())
539 1070 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 337827 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic) const {
553 // Append the qualifiers
554
3/6
✓ Branch 0 (2→3) taken 337827 times.
✗ Branch 1 (2→31) not taken.
✓ Branch 2 (3→4) taken 337827 times.
✗ Branch 3 (3→31) not taken.
✓ Branch 4 (4→5) taken 337827 times.
✗ Branch 5 (4→31) not taken.
337827 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
555
5/6
✓ Branch 0 (5→6) taken 217719 times.
✓ Branch 1 (5→9) taken 120108 times.
✓ Branch 2 (6→7) taken 79090 times.
✓ Branch 3 (6→9) taken 138629 times.
✓ Branch 4 (7→8) taken 79090 times.
✗ Branch 5 (7→9) not taken.
337827 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
556
1/2
✓ Branch 0 (8→9) taken 79090 times.
✗ Branch 1 (8→32) not taken.
79090 name << "public ";
557
3/4
✓ Branch 0 (9→10) taken 4 times.
✓ Branch 1 (9→12) taken 337823 times.
✓ Branch 2 (10→11) taken 4 times.
✗ Branch 3 (10→12) not taken.
337827 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 38928 times.
✓ Branch 1 (12→17) taken 298899 times.
✓ Branch 2 (13→14) taken 37936 times.
✓ Branch 3 (13→17) taken 992 times.
✓ Branch 4 (15→16) taken 29296 times.
✓ Branch 5 (15→17) taken 8640 times.
✓ Branch 6 (18→19) taken 29296 times.
✓ Branch 7 (18→20) taken 308531 times.
337827 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
560
1/2
✓ Branch 0 (19→20) taken 29296 times.
✗ Branch 1 (19→32) not taken.
29296 name << "const ";
561
3/4
✓ Branch 0 (20→21) taken 12812 times.
✓ Branch 1 (20→23) taken 325015 times.
✓ Branch 2 (21→22) taken 12812 times.
✗ Branch 3 (21→23) not taken.
337827 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
562
1/2
✓ Branch 0 (22→23) taken 12812 times.
✗ Branch 1 (22→32) not taken.
12812 name << "heap ";
563
3/4
✓ Branch 0 (23→24) taken 31369 times.
✓ Branch 1 (23→26) taken 306458 times.
✗ Branch 2 (24→25) not taken.
✓ Branch 3 (24→26) taken 31369 times.
337827 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
564 name << "signed ";
565
4/4
✓ Branch 0 (26→27) taken 306458 times.
✓ Branch 1 (26→29) taken 31369 times.
✓ Branch 2 (27→28) taken 32391 times.
✓ Branch 3 (27→29) taken 274067 times.
337827 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
566
1/2
✓ Branch 0 (28→29) taken 32391 times.
✗ Branch 1 (28→32) not taken.
32391 name << "unsigned ";
567
568 // Loop through all chain elements
569
1/2
✓ Branch 0 (29→30) taken 337827 times.
✗ Branch 1 (29→32) not taken.
337827 type->getName(name, withSize, ignorePublic);
570 337827 }
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 213336 std::string QualType::getName(bool withSize, bool ignorePublic) const {
580
1/2
✓ Branch 0 (2→3) taken 213336 times.
✗ Branch 1 (2→11) not taken.
213336 std::stringstream name;
581
1/2
✓ Branch 0 (3→4) taken 213336 times.
✗ Branch 1 (3→9) not taken.
213336 getName(name, withSize, ignorePublic);
582
1/2
✓ Branch 0 (4→5) taken 213336 times.
✗ Branch 1 (4→9) not taken.
426672 return name.str();
583 213336 }
584
585 /**
586 * Convert the type to an LLVM type
587 *
588 * @param sourceFile Source file
589 * @return LLVM type
590 */
591 199849 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 12956 QualType QualType::toPtr(const ASTNode *node) const {
600 12956 QualType newType = *this;
601
2/2
✓ Branch 0 (2→3) taken 12954 times.
✓ Branch 1 (2→5) taken 2 times.
12956 newType.type = type->toPtr(node);
602 12954 return newType;
603 }
604
605 /**
606 * Retrieve the reference type to this type
607 *
608 * @param node ASTNode
609 * @return New type
610 */
611 10388 QualType QualType::toRef(const ASTNode *node) const {
612 10388 QualType newType = *this;
613
1/2
✓ Branch 0 (2→3) taken 10388 times.
✗ Branch 1 (2→5) not taken.
10388 newType.type = type->toRef(node);
614 10388 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 3453 QualType QualType::toConstRef(const ASTNode *node) const {
624
1/2
✓ Branch 0 (2→3) taken 3453 times.
✗ Branch 1 (2→6) not taken.
3453 QualType newType = toRef(node);
625 3453 newType.makeConst();
626 3453 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 219 QualType QualType::toArr(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
638 219 QualType newType = *this;
639
2/2
✓ Branch 0 (2→3) taken 218 times.
✓ Branch 1 (2→5) taken 1 times.
219 newType.type = type->toArr(node, size, skipDynCheck);
640 218 return newType;
641 }
642
643 /**
644 * Retrieve the non-const type of this type
645 *
646 * @return New type
647 */
648 1720 QualType QualType::toNonConst() const {
649 1720 QualType newType = *this;
650 1720 newType.qualifiers.isConst = false;
651 1720 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 51348 QualType QualType::getContained() const {
661
2/4
✓ Branch 0 (2→3) taken 51348 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 51348 times.
51348 assert(isOneOf({TY_PTR, TY_REF, TY_ARRAY, TY_STRING}));
662 51348 QualType newType = *this;
663
1/2
✓ Branch 0 (5→6) taken 51348 times.
✗ Branch 1 (5→9) not taken.
51348 newType.type = type->getContained();
664 51348 return newType;
665 }
666
667 /**
668 * Retrieve the base type of this type
669 *
670 * @return New type
671 */
672 631386 QualType QualType::getBase() const {
673 631386 QualType newType = *this;
674
1/2
✓ Branch 0 (2→3) taken 631386 times.
✗ Branch 1 (2→5) not taken.
631386 newType.type = type->getBase();
675 631386 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 919 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
685
2/4
✓ Branch 0 (2→3) taken 919 times.
✗ Branch 1 (2→18) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 919 times.
919 assert(is(TY_ALIAS));
686 // Get type of aliased type container entry
687
1/2
✓ Branch 0 (5→6) taken 919 times.
✗ Branch 1 (5→18) not taken.
919 const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
688
1/2
✓ Branch 0 (6→7) taken 919 times.
✗ Branch 1 (6→16) not taken.
919 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
689
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 919 times.
919 assert(aliasedTypeContainerEntry != nullptr);
690
1/2
✓ Branch 0 (11→12) taken 919 times.
✗ Branch 1 (11→16) not taken.
1838 return aliasedTypeContainerEntry->getQualType();
691 919 }
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 4365 times.
✓ Branch 1 (3→5) taken 167362 times.
171727 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 19900 QualType QualType::autoDeReference() const {
707 19900 QualType newType = *this;
708
3/4
✓ Branch 0 (5→6) taken 36823 times.
✗ Branch 1 (5→10) not taken.
✓ Branch 2 (6→3) taken 16923 times.
✓ Branch 3 (6→7) taken 19900 times.
36823 while (newType.isOneOf({TY_PTR, TY_REF}))
709
1/2
✓ Branch 0 (3→4) taken 16923 times.
✗ Branch 1 (3→9) not taken.
16923 newType = newType.getContained();
710 19900 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 8539 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
720 // Create new type
721
1/2
✓ Branch 0 (3→4) taken 8539 times.
✗ Branch 1 (3→9) not taken.
8539 const Type *newType = type->replaceBase(newBaseType.getType());
722 // Create new qualifiers
723
1/2
✓ Branch 0 (4→5) taken 8539 times.
✗ Branch 1 (4→9) not taken.
8539 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
724 // Return the new qualified type
725 8539 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 19625 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
746 // Create new type
747 19625 const Type *newType = type->getWithBodyScope(bodyScope);
748 // Return the new qualified type
749 19625 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 2796 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
759 // Create new type
760 2796 const Type *newType = type->getWithTemplateTypes(templateTypes);
761 // Return the new qualified type
762 2796 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 3739 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
772 // Create new type
773 3739 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
774 // Return the new qualified type
775 3739 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 11204 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
785 // Create new type
786 11204 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
787 // Return the new qualified type
788 11204 return {newType, qualifiers};
789 }
790
791 11185 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
792
1/2
✓ Branch 0 (2→3) taken 11185 times.
✗ Branch 1 (2→15) not taken.
11185 QualTypeList paramAndReturnTypes = paramTypes;
793
1/2
✓ Branch 0 (5→6) taken 11185 times.
✗ Branch 1 (5→11) not taken.
11185 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
794
1/2
✓ Branch 0 (6→7) taken 11185 times.
✗ Branch 1 (6→13) not taken.
22370 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
795 11185 }
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 24093 times.
✓ Branch 1 (3→6) taken 2348 times.
✓ Branch 2 (4→5) taken 3830 times.
✓ Branch 3 (4→6) taken 20263 times.
26441 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 12754 bool QualType::isSigned() const {
820
2/4
✓ Branch 0 (2→3) taken 12754 times.
✗ Branch 1 (2→7) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 12754 times.
12754 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
821 12754 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 8158 bool QualType::isInline() const {
840
2/4
✓ Branch 0 (2→3) taken 8158 times.
✗ Branch 1 (2→7) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 8158 times.
8158 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
841 8158 return qualifiers.isInline;
842 }
843
844 /**
845 * Check if the current type is marked public
846 *
847 * @return Is public or not
848 */
849 17412 bool QualType::isPublic() const {
850
5/8
✓ Branch 0 (2→3) taken 17412 times.
✗ Branch 1 (2→9) not taken.
✓ Branch 2 (3→4) taken 16143 times.
✓ Branch 3 (3→7) taken 1269 times.
✓ Branch 4 (4→5) taken 16143 times.
✗ Branch 5 (4→9) not taken.
✗ Branch 6 (5→6) not taken.
✓ Branch 7 (5→7) taken 16143 times.
17412 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
851 17412 return qualifiers.isPublic;
852 }
853
854 /**
855 * Check if the current type is marked heap
856 *
857 * @return Is heap or not
858 */
859 10819 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 3453 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 302 void QualType::makePublic(bool isPublic) {
892
4/8
✓ Branch 0 (2→3) taken 302 times.
✗ Branch 1 (2→8) not taken.
✓ Branch 2 (3→4) taken 302 times.
✗ Branch 3 (3→7) not taken.
✓ Branch 4 (4→5) taken 302 times.
✗ Branch 5 (4→8) not taken.
✗ Branch 6 (5→6) not taken.
✓ Branch 7 (5→7) taken 302 times.
302 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
893 302 qualifiers.isPublic = isPublic;
894 302 }
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 23477 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 73932 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
929
930 } // namespace spice::compiler
931