GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/QualType.cpp
Date: 2025-03-05 01:50:32
Exec Total Coverage
Lines: 266 275 96.7%
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 4175284 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 46950 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 731936 SuperType QualType::getSuperType() const { return type->getSuperType(); }
29
30 /**
31 * Get the subtype of the underlying type
32 *
33 * @return Subtype
34 */
35 189777 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 2442176 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 486207 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 386357 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 28926 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 661 bool QualType::isStringObj() const {
295
4/6
✓ Branch 0 (3→4) taken 116 times.
✓ Branch 1 (3→10) taken 545 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.
661 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 271610 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) { return fieldType.isTriviallyDestructible(node); }; // NOLINT(*-no-recursion)
381
1/2
✓ Branch 0 (26→27) taken 2057 times.
✗ Branch 1 (26→41) not taken.
2057 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
382 }
383
384 2800 return true;
385 }
386
387
388 /**
389 * Check if the current type implements the given interface type
390 *
391 * @param implementedInterfaceType Interface type
392 * @param node Accessing ASTNode
393 * @return Struct implements interface or not
394 */
395 200 bool QualType::doesImplement(const QualType &implementedInterfaceType, const ASTNode *node) const {
396
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));
397 200 const Struct *spiceStruct = getStruct(node);
398
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 200 times.
200 assert(spiceStruct != nullptr);
399 200 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
400
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 200 times.
200 assert(interfaceType.is(TY_INTERFACE));
401 200 return implementedInterfaceType.matches(interfaceType, false, false, true);
402 200 });
403 }
404
405 /**
406 * Check if a certain input type can be bound (assigned) to the current type->
407 *
408 * @param inputType Qualified type, which should be bound to the current type
409 * @param isTemporary Is the input type a temporary type
410 * @return Can be bound or not
411 */
412 11034 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
413
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();
414 }
415
416 /**
417 * Check for the matching compatibility of two types.
418 * Useful for struct and function matching as well as assignment type validation and function arg matching.
419 *
420 * @param otherType Type to compare against
421 * @param ignoreArraySize Ignore array sizes
422 * @param ignoreQualifiers Ignore qualifiers, except for pointer and reference types
423 * @param allowConstify Match when the types are the same, but the lhs type is more const restrictive than the rhs type
424 * @return Matching or not
425 */
426 92780 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
427 // Compare type
428
2/2
✓ Branch 0 (3→4) taken 40483 times.
✓ Branch 1 (3→5) taken 52297 times.
92780 if (!type->matches(otherType.type, ignoreArraySize))
429 40483 return false;
430
431 // Ignore or compare qualifiers
432
4/4
✓ Branch 0 (5→6) taken 10852 times.
✓ Branch 1 (5→8) taken 41445 times.
✓ Branch 2 (7→8) taken 10739 times.
✓ Branch 3 (7→9) taken 113 times.
52297 return ignoreQualifiers || qualifiers.match(otherType.qualifiers, allowConstify);
433 }
434
435 /**
436 * Check for the matching compatibility of two types in terms of interface implementation.
437 * Useful for function matching as well as assignment type validation and function arg matching.
438 *
439 * @param structType Type to compare against
440 * @return Matching or not
441 */
442 50143 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
443
8/10
✓ Branch 0 (2→3) taken 50143 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 160 times.
✓ Branch 3 (3→6) taken 49983 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 50012 times.
✓ Branch 9 (8→10) taken 131 times.
50143 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
444 50012 return false;
445
446 // Check if the rhs is a struct type that implements the lhs interface type
447
1/2
✓ Branch 0 (10→11) taken 131 times.
✗ Branch 1 (10→17) not taken.
131 const Struct *spiceStruct = structType.getStruct(nullptr);
448
1/2
✗ Branch 0 (11→12) not taken.
✓ Branch 1 (11→13) taken 131 times.
131 assert(spiceStruct != nullptr);
449 127 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
450
1/2
✓ Branch 0 (13→14) taken 131 times.
✗ Branch 1 (13→17) not taken.
131 return std::ranges::any_of(spiceStruct->interfaceTypes, pred);
451 }
452
453 /**
454 * Check if the current type is the same container type as another type.
455 * Container types include arrays, pointers, and references.
456 *
457 * @param other Other type
458 * @return Same container type or not
459 */
460 1794 bool QualType::isSameContainerTypeAs(const QualType &other) const { return type->isSameContainerTypeAs(other.type); }
461
462 /**
463 * Check if the current type is a self-referencing struct type
464 *
465 * @return Self-referencing struct type or not
466 */
467 17808 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
468
2/2
✓ Branch 0 (3→4) taken 13127 times.
✓ Branch 1 (3→5) taken 4681 times.
17808 if (!is(TY_STRUCT))
469 13127 return false;
470
471 // If no type was set by a previous iteration, we set it to the current type
472
2/2
✓ Branch 0 (5→6) taken 3447 times.
✓ Branch 1 (5→7) taken 1234 times.
4681 if (typeToCompareWith == nullptr)
473 3447 typeToCompareWith = this;
474
475 4681 Scope *baseTypeBodyScope = getBodyScope();
476
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++) {
477
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 14269 times.
14269 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
478 14269 const QualType &fieldType = field->getQualType();
479 // Check if the base type of the field matches with the current type, which is also a base type
480 // If yes, this is a self-referencing struct type
481
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)
482 200 return true;
483
484 // If the field is a struct, check if it is a self-referencing struct type
485
1/2
✗ Branch 0 (20→21) not taken.
✓ Branch 1 (20→22) taken 14069 times.
14069 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
486 return true;
487 }
488 4481 return false;
489 }
490
491 /**
492 * Check if the given generic type list has a substantiation for the current (generic) type
493 *
494 * @param genericTypeList Generic type list
495 * @return Has substantiation or not
496 */
497 20498 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
498
1/2
✓ Branch 0 (2→3) taken 20498 times.
✗ Branch 1 (2→19) not taken.
20498 const QualType baseType = getBase();
499 // Check if the symbol type itself is generic
500
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)) {
501
1/2
✓ Branch 0 (5→6) taken 3797 times.
✗ Branch 1 (5→19) not taken.
3797 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
502
2/2
✓ Branch 0 (3→4) taken 3789 times.
✓ Branch 1 (3→5) taken 662 times.
4451 if (baseType.matches(t, true, true, true)) {
503 3789 t.used = true;
504 3789 return true;
505 }
506 662 return false;
507 3797 });
508 }
509
510 // If the type is non-generic check template types
511 16701 bool covered = true;
512 // Check template types
513
1/2
✓ Branch 0 (7→8) taken 16701 times.
✗ Branch 1 (7→19) not taken.
16701 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
514 1526 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
515 1526 return templateType.isCoveredByGenericTypeList(genericTypeList);
516 16701 };
517
1/2
✓ Branch 0 (8→9) taken 16701 times.
✗ Branch 1 (8→19) not taken.
16701 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
518
519 // If function/procedure, check param and return types
520
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})) {
521
1/2
✓ Branch 0 (11→12) taken 29 times.
✗ Branch 1 (11→18) not taken.
29 const QualTypeList &paramAndReturnTypes = baseType.getFunctionParamAndReturnTypes();
522 46 const auto innerPred = [&](const QualType &paramType) { // NOLINT(*-no-recursion)
523 46 return paramType.isCoveredByGenericTypeList(genericTypeList);
524 29 };
525
1/2
✓ Branch 0 (12→13) taken 29 times.
✗ Branch 1 (12→18) not taken.
29 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
526 }
527
528 16701 return covered;
529 }
530
531 /**
532 * Check if the current type needs de-allocation
533 *
534 * @return Needs de-allocation or not
535 */
536 1119 bool QualType::needsDeAllocation() const {
537
2/2
✓ Branch 0 (3→4) taken 1070 times.
✓ Branch 1 (3→5) taken 49 times.
1119 if (!isHeap())
538 1070 return false;
539 // We only need de-allocation, if we directly point to a heap-allocated type
540 // e.g. for heap TestStruct** we don't need to de-allocate, since it is a non-owning pointer to an owning pointer
541
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);
542 }
543
544 /**
545 * Get the name of the symbol type as a string
546 *
547 * @param name Name stream
548 * @param withSize Include the array size for sized types
549 * @param ignorePublic Ignore any potential public qualifier
550 */
551 337823 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic) const {
552 // Append the qualifiers
553
3/6
✓ Branch 0 (2→3) taken 337823 times.
✗ Branch 1 (2→31) not taken.
✓ Branch 2 (3→4) taken 337823 times.
✗ Branch 3 (3→31) not taken.
✓ Branch 4 (4→5) taken 337823 times.
✗ Branch 5 (4→31) not taken.
337823 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
554
5/6
✓ Branch 0 (5→6) taken 247442 times.
✓ Branch 1 (5→9) taken 90381 times.
✓ Branch 2 (6→7) taken 85014 times.
✓ Branch 3 (6→9) taken 162428 times.
✓ Branch 4 (7→8) taken 85014 times.
✗ Branch 5 (7→9) not taken.
337823 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
555
1/2
✓ Branch 0 (8→9) taken 85014 times.
✗ Branch 1 (8→32) not taken.
85014 name << "public ";
556
3/4
✓ Branch 0 (9→10) taken 4 times.
✓ Branch 1 (9→12) taken 337819 times.
✓ Branch 2 (10→11) taken 4 times.
✗ Branch 3 (10→12) not taken.
337823 if (qualifiers.isComposition && !defaultForSuperType.isComposition)
557
1/2
✓ Branch 0 (11→12) taken 4 times.
✗ Branch 1 (11→32) not taken.
4 name << "compose ";
558
8/8
✓ Branch 0 (12→13) taken 38928 times.
✓ Branch 1 (12→17) taken 298895 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 308527 times.
337823 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
559
1/2
✓ Branch 0 (19→20) taken 29296 times.
✗ Branch 1 (19→32) not taken.
29296 name << "const ";
560
3/4
✓ Branch 0 (20→21) taken 12812 times.
✓ Branch 1 (20→23) taken 325011 times.
✓ Branch 2 (21→22) taken 12812 times.
✗ Branch 3 (21→23) not taken.
337823 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
561
1/2
✓ Branch 0 (22→23) taken 12812 times.
✗ Branch 1 (22→32) not taken.
12812 name << "heap ";
562
3/4
✓ Branch 0 (23→24) taken 31366 times.
✓ Branch 1 (23→26) taken 306457 times.
✗ Branch 2 (24→25) not taken.
✓ Branch 3 (24→26) taken 31366 times.
337823 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
563 name << "signed ";
564
4/4
✓ Branch 0 (26→27) taken 306457 times.
✓ Branch 1 (26→29) taken 31366 times.
✓ Branch 2 (27→28) taken 32391 times.
✓ Branch 3 (27→29) taken 274066 times.
337823 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
565
1/2
✓ Branch 0 (28→29) taken 32391 times.
✗ Branch 1 (28→32) not taken.
32391 name << "unsigned ";
566
567 // Loop through all chain elements
568
1/2
✓ Branch 0 (29→30) taken 337823 times.
✗ Branch 1 (29→32) not taken.
337823 type->getName(name, withSize);
569 337823 }
570
571 /**
572 * Get the name of the symbol type as a string
573 *
574 * @param withSize Include the array size for sized types
575 * @param ignorePublic Ignore any potential public qualifier
576 * @return Symbol type name
577 */
578 236886 std::string QualType::getName(bool withSize, bool ignorePublic) const {
579
1/2
✓ Branch 0 (2→3) taken 236886 times.
✗ Branch 1 (2→11) not taken.
236886 std::stringstream name;
580
1/2
✓ Branch 0 (3→4) taken 236886 times.
✗ Branch 1 (3→9) not taken.
236886 getName(name, withSize, ignorePublic);
581
1/2
✓ Branch 0 (4→5) taken 236886 times.
✗ Branch 1 (4→9) not taken.
473772 return name.str();
582 236886 }
583
584 /**
585 * Convert the type to an LLVM type
586 *
587 * @param sourceFile Source file
588 * @return LLVM type
589 */
590 199849 llvm::Type *QualType::toLLVMType(SourceFile *sourceFile) const { return sourceFile->getLLVMType(type); }
591
592 /**
593 * Retrieve the pointer type to this type
594 *
595 * @param node ASTNode
596 * @return New type
597 */
598 12956 QualType QualType::toPtr(const ASTNode *node) const {
599 12956 QualType newType = *this;
600
2/2
✓ Branch 0 (2→3) taken 12954 times.
✓ Branch 1 (2→5) taken 2 times.
12956 newType.type = type->toPtr(node);
601 12954 return newType;
602 }
603
604 /**
605 * Retrieve the reference type to this type
606 *
607 * @param node ASTNode
608 * @return New type
609 */
610 10388 QualType QualType::toRef(const ASTNode *node) const {
611 10388 QualType newType = *this;
612
1/2
✓ Branch 0 (2→3) taken 10388 times.
✗ Branch 1 (2→5) not taken.
10388 newType.type = type->toRef(node);
613 10388 return newType;
614 }
615
616 /**
617 * Retrieve the const reference type of this type
618 *
619 * @param node ASTNode
620 * @return New type
621 */
622 3453 QualType QualType::toConstRef(const ASTNode *node) const {
623
1/2
✓ Branch 0 (2→3) taken 3453 times.
✗ Branch 1 (2→6) not taken.
3453 QualType newType = toRef(node);
624 3453 newType.makeConst();
625 3453 return newType;
626 }
627
628 /**
629 * Retrieve the array type of this type
630 *
631 * @param node ASTNode
632 * @param size Array size
633 * @param skipDynCheck Skip dynamic check
634 * @return New type
635 */
636 219 QualType QualType::toArr(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
637 219 QualType newType = *this;
638
2/2
✓ Branch 0 (2→3) taken 218 times.
✓ Branch 1 (2→5) taken 1 times.
219 newType.type = type->toArr(node, size, skipDynCheck);
639 218 return newType;
640 }
641
642 /**
643 * Retrieve the non-const type of this type
644 *
645 * @return New type
646 */
647 1720 QualType QualType::toNonConst() const {
648 1720 QualType newType = *this;
649 1720 newType.qualifiers.isConst = false;
650 1720 return newType;
651 }
652
653 /**
654 * Retrieve the contained type of this type
655 * This works on pointers, arrays, references and strings (which alias with char*)
656 *
657 * @return New type
658 */
659 51348 QualType QualType::getContained() const {
660
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}));
661 51348 QualType newType = *this;
662
1/2
✓ Branch 0 (5→6) taken 51348 times.
✗ Branch 1 (5→9) not taken.
51348 newType.type = type->getContained();
663 51348 return newType;
664 }
665
666 /**
667 * Retrieve the base type of this type
668 *
669 * @return New type
670 */
671 631380 QualType QualType::getBase() const {
672 631380 QualType newType = *this;
673
1/2
✓ Branch 0 (2→3) taken 631380 times.
✗ Branch 1 (2→5) not taken.
631380 newType.type = type->getBase();
674 631380 return newType;
675 }
676
677 /**
678 * Get aliased type for an alias type
679 *
680 * @param aliasEntry Entry of the alias definition
681 * @return Aliased type
682 */
683 919 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
684
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));
685 // Get type of aliased type container entry
686
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;
687
1/2
✓ Branch 0 (6→7) taken 919 times.
✗ Branch 1 (6→16) not taken.
919 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
688
1/2
✗ Branch 0 (9→10) not taken.
✓ Branch 1 (9→11) taken 919 times.
919 assert(aliasedTypeContainerEntry != nullptr);
689
1/2
✓ Branch 0 (11→12) taken 919 times.
✗ Branch 1 (11→16) not taken.
1838 return aliasedTypeContainerEntry->getQualType();
690 919 }
691
692 /**
693 * Remove reference of this type, if it is a reference
694 *
695 * @return New type
696 */
697
2/2
✓ Branch 0 (3→4) taken 4365 times.
✓ Branch 1 (3→5) taken 167358 times.
171723 QualType QualType::removeReferenceWrapper() const { return isRef() ? getContained() : *this; }
698
699 /**
700 * Auto-dereference the given symbol type (peeling off all ptr/ref wrappers).
701 * This process is NOT equivalent with getBase() because getBase() also removes e.g. array wrappers
702 *
703 * @return New type
704 */
705 19900 QualType QualType::autoDeReference() const {
706 19900 QualType newType = *this;
707
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}))
708
1/2
✓ Branch 0 (3→4) taken 16923 times.
✗ Branch 1 (3→9) not taken.
16923 newType = newType.getContained();
709 19900 return newType;
710 }
711
712 /**
713 * Replace the base type with another one
714 *
715 * @param newBaseType New base type
716 * @return New type
717 */
718 8539 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
719 // Create new type
720
1/2
✓ Branch 0 (3→4) taken 8539 times.
✗ Branch 1 (3→9) not taken.
8539 const Type *newType = type->replaceBase(newBaseType.getType());
721 // Create new qualifiers
722
1/2
✓ Branch 0 (4→5) taken 8539 times.
✗ Branch 1 (4→9) not taken.
8539 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
723 // Return the new qualified type
724 8539 return {newType, newQualifiers};
725 }
726
727 /**
728 * Retrieve the same type, but with lambda captures enabled
729 *
730 * @return Same type with lambda captures
731 */
732 45 QualType QualType::getWithLambdaCaptures(bool enabled /*=true*/) const {
733 // Create new type
734 45 const Type *newType = type->getWithLambdaCaptures(enabled);
735 // Return the new qualified type
736 45 return {newType, qualifiers};
737 }
738
739 /**
740 * Retrieve the same type, but with a new body scope
741 *
742 * @return Same type with body scope
743 */
744 19625 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
745 // Create new type
746 19625 const Type *newType = type->getWithBodyScope(bodyScope);
747 // Return the new qualified type
748 19625 return {newType, qualifiers};
749 }
750
751 /**
752 * Retrieve the same type, but with new template types
753 *
754 * @param templateTypes New template types
755 * @return Same type with new template types
756 */
757 2796 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
758 // Create new type
759 2796 const Type *newType = type->getWithTemplateTypes(templateTypes);
760 // Return the new qualified type
761 2796 return {newType, qualifiers};
762 }
763
764 /**
765 * Retrieve the same type, but with new base template types
766 *
767 * @param templateTypes New base template types
768 * @return Same type with new base template types
769 */
770 3739 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
771 // Create new type
772 3739 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
773 // Return the new qualified type
774 3739 return {newType, qualifiers};
775 }
776
777 /**
778 * Retrieve the same type, but with new function parameter and return types
779 *
780 * @param paramAndReturnTypes New parameter types
781 * @return Same type with new parameter types
782 */
783 11203 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
784 // Create new type
785 11203 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
786 // Return the new qualified type
787 11203 return {newType, qualifiers};
788 }
789
790 11184 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
791
1/2
✓ Branch 0 (2→3) taken 11184 times.
✗ Branch 1 (2→15) not taken.
11184 QualTypeList paramAndReturnTypes = paramTypes;
792
1/2
✓ Branch 0 (5→6) taken 11184 times.
✗ Branch 1 (5→11) not taken.
11184 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
793
1/2
✓ Branch 0 (6→7) taken 11184 times.
✗ Branch 1 (6→13) not taken.
22368 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
794 11184 }
795
796 /**
797 * Check if the current type is const
798 *
799 * Examples for const types:
800 * - const int
801 * - const TestStruct
802 * - const string
803 *
804 * Examples for non-const types:
805 * - double (reason: not marked const)
806 * - const int* (reason: pointer to const int is not const itself)
807 * - const TestStruct& (reason: reference to const TestStruct is not const itself)
808 *
809 * @return Is const or not
810 */
811
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; }
812
813 /**
814 * Check if the current type is marked signed
815 *
816 * @return Is signed or not
817 */
818 12754 bool QualType::isSigned() const {
819
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}));
820 12754 return qualifiers.isSigned;
821 }
822
823 /**
824 * Check if the current type is marked unsigned
825 *
826 * @return Is unsigned or not
827 */
828 bool QualType::isUnsigned() const {
829 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
830 return qualifiers.isUnsigned;
831 }
832
833 /**
834 * Check if the current type is marked inline
835 *
836 * @return Is inline or not
837 */
838 8158 bool QualType::isInline() const {
839
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}));
840 8158 return qualifiers.isInline;
841 }
842
843 /**
844 * Check if the current type is marked public
845 *
846 * @return Is public or not
847 */
848 17412 bool QualType::isPublic() const {
849
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}));
850 17412 return qualifiers.isPublic;
851 }
852
853 /**
854 * Check if the current type is marked heap
855 *
856 * @return Is heap or not
857 */
858 10819 bool QualType::isHeap() const { return qualifiers.isHeap; }
859
860 /**
861 * Check if the current type is marked as composition
862 *
863 * @return Is composition or not
864 */
865 41 bool QualType::isComposition() const { return qualifiers.isComposition; }
866
867 /**
868 * Make the current type const
869 *
870 * @param isConst Is const or not
871 */
872 3453 void QualType::makeConst(bool isConst) { qualifiers.isConst = isConst; }
873
874 /**
875 * Make the current type unsigned
876 *
877 * @param isUnsigned Is unsigned or not
878 */
879 12 void QualType::makeUnsigned(bool isUnsigned) {
880
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}));
881 12 qualifiers.isSigned = !isUnsigned;
882 12 qualifiers.isUnsigned = isUnsigned;
883 12 }
884
885 /**
886 * Make the current type public
887 *
888 * @param isPublic Is public or not
889 */
890 302 void QualType::makePublic(bool isPublic) {
891
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}));
892 302 qualifiers.isPublic = isPublic;
893 302 }
894
895 /**
896 * Make the current type heap
897 *
898 * @param isHeap Is heap or not
899 */
900 48 void QualType::makeHeap(bool isHeap) { qualifiers.isHeap = isHeap; }
901
902 /**
903 * Check if two types are equal
904 *
905 * @param lhs Left-hand side type
906 * @param rhs Right-hand side type
907 * @return Equal or not
908 */
909 23473 bool operator==(const QualType &lhs, const QualType &rhs) { return lhs.type == rhs.type; }
910
911 /**
912 * Check if two types are not equal
913 *
914 * @param lhs Left-hand side type
915 * @param rhs Right-hand side type
916 * @return Not equal or not
917 */
918 1523 bool operator!=(const QualType &lhs, const QualType &rhs) { return !(lhs == rhs); }
919
920 /**
921 * Remove pointers / arrays / references if both types have them as far as possible.
922 * Furthermore, remove reference wrappers if possible.
923 *
924 * @param typeA Candidate type
925 * @param typeB Requested type
926 */
927 73928 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
928
929 } // namespace spice::compiler
930