GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/QualType.cpp
Date: 2025-12-07 00:53:49
Coverage Exec Excl Total
Lines: 97.5% 274 0 281
Functions: 97.7% 84 0 86
Branches: 61.9% 240 0 388

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 5276371 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), qualifiers(TypeQualifiers::of(superType)) {}
19 1829 QualType::QualType(SuperType superType, const std::string &subType)
20 1829 : type(TypeRegistry::getOrInsert(superType, subType)), qualifiers(TypeQualifiers::of(superType)) {}
21 68456 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 963209 SuperType QualType::getSuperType() const { return type->getSuperType(); }
29
30 /**
31 * Get the subtype of the underlying type
32 *
33 * @return Subtype
34 */
35 281593 const std::string &QualType::getSubType() const { return type->getSubType(); }
36
37 /**
38 * Get the array size of the underlying type
39 *
40 * @return Array size
41 */
42 572 unsigned int QualType::getArraySize() const { return type->getArraySize(); }
43
44 /**
45 * Get the body scope of the underlying type
46 *
47 * @return Body scope
48 */
49 134500 Scope *QualType::getBodyScope() const { return type->getBodyScope(); }
50
51 /**
52 * Get the function parameter types of the underlying type
53 *
54 * @return Function parameter types
55 */
56 39 const QualType &QualType::getFunctionReturnType() const { return type->getFunctionReturnType(); }
57
58 /**
59 * Get the function parameter types of the underlying type
60 *
61 * @return Function parameter types
62 */
63 140 QualTypeList QualType::getFunctionParamTypes() const { return type->getFunctionParamTypes(); }
64
65 /**
66 * Get the function parameter and return types of the underlying type
67 *
68 * @return Function parameter and return types
69 */
70 54 const QualTypeList &QualType::getFunctionParamAndReturnTypes() const { return type->getFunctionParamAndReturnTypes(); }
71
72 /**
73 * Check if the underlying type has lambda captures
74 *
75 * @return Has lambda captures or not
76 */
77 145 bool QualType::hasLambdaCaptures() const { return type->hasLambdaCaptures(); }
78
79 /**
80 * Get the template types of the underlying type
81 *
82 * @return Template types
83 */
84 82106 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 15924 Struct *QualType::getStruct(const ASTNode *node, const QualTypeList &templateTypes) const {
94
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 15924 times.
15924 assert(is(TY_STRUCT));
95 15924 Scope *structDefScope = getBodyScope()->parent;
96 15924 const std::string &structName = getSubType();
97 15924 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 9030 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 294 Struct *QualType::getStructAndAdjustType(const ASTNode *node, const QualTypeList &templateTypes) {
117 294 Struct *spiceStruct = getStruct(node, templateTypes);
118
2/4
✓ Branch 4 → 5 taken 294 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 294 times.
✗ Branch 5 → 9 not taken.
294 type = type->getWithBodyScope(spiceStruct->scope)->getWithTemplateTypes(spiceStruct->getTemplateTypes());
119 294 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 1388 Interface *QualType::getInterface(const ASTNode *node, const QualTypeList &templateTypes) const {
139
2/4
✓ Branch 2 → 3 taken 1388 times.
✗ Branch 2 → 15 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1388 times.
1388 assert(is(TY_INTERFACE));
140
1/2
✓ Branch 5 → 6 taken 1388 times.
✗ Branch 5 → 15 not taken.
1388 Scope *interfaceDefScope = getBodyScope()->parent;
141
2/4
✓ Branch 6 → 7 taken 1388 times.
✗ Branch 6 → 15 not taken.
✓ Branch 7 → 8 taken 1388 times.
✗ Branch 7 → 15 not taken.
1388 const std::string structName = getSubType();
142
1/2
✓ Branch 8 → 9 taken 1388 times.
✗ Branch 8 → 13 not taken.
2776 return InterfaceManager::match(interfaceDefScope, structName, templateTypes, node);
143 1388 }
144
145 /**
146 * Get the interface instance for an interface type
147 *
148 * @param node Accessing AST node
149 * @return Interface instance
150 */
151 792 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 3303167 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 657705 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 479685 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 1187 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 97149 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 374019 bool QualType::isPtr() const { return type->isPtr(); }
202
203 /**
204 * Check if the underlying type is a pointer to a certain super type
205 *
206 * @param superType Super type
207 * @return Pointer to super type or not
208 */
209
7/10
✓ Branch 2 → 3 taken 174653 times.
✗ Branch 2 → 12 not taken.
✓ Branch 3 → 4 taken 12018 times.
✓ Branch 3 → 8 taken 162635 times.
✓ Branch 4 → 5 taken 12018 times.
✗ Branch 4 → 12 not taken.
✓ Branch 5 → 6 taken 12018 times.
✗ Branch 5 → 12 not taken.
✓ Branch 6 → 7 taken 7055 times.
✓ Branch 6 → 8 taken 4963 times.
174653 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 512527 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 35493 bool QualType::isArray() const { return type->isArray(); }
232
233 /**
234 * Check if the underlying type is an array of a certain super type
235 *
236 * @param superType Super type
237 * @return Array of super type or not
238 */
239
2/10
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 12 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 8 taken 1 time.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 12 not taken.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 12 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
1 bool QualType::isArrayOf(SuperType superType) const { return isArray() && getContained().is(superType); }
240
241 /**
242 * Check if the underlying type is a const reference
243 *
244 * @return Const reference or not
245 */
246
4/4
✓ Branch 2 → 3 taken 350 times.
✓ Branch 2 → 6 taken 283 times.
✓ Branch 4 → 5 taken 346 times.
✓ Branch 4 → 6 taken 4 times.
633 bool QualType::isConstRef() const { return qualifiers.isConst && isRef(); }
247
248 /**
249 * Check if the current type is an iterator
250 *
251 * @param node ASTNode
252 * @return Iterator or not
253 */
254 118 bool QualType::isIterator(const ASTNode *node) const {
255 // The type must be a struct that implements the iterator interface
256
3/4
✓ Branch 2 → 3 taken 118 times.
✗ Branch 2 → 47 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 117 times.
118 if (!is(TY_STRUCT))
257 1 return false;
258
259
2/4
✓ Branch 7 → 8 taken 117 times.
✗ Branch 7 → 30 not taken.
✓ Branch 8 → 9 taken 117 times.
✗ Branch 8 → 28 not taken.
117 const QualType genericType(TY_GENERIC, "T");
260 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
261
3/6
✓ Branch 13 → 14 taken 117 times.
✗ Branch 13 → 42 not taken.
✓ Branch 16 → 17 taken 117 times.
✗ Branch 16 → 36 not taken.
✓ Branch 17 → 18 taken 117 times.
✗ Branch 17 → 34 not taken.
468 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERATOR_INTERFACE, data, {genericType});
262
1/2
✓ Branch 22 → 23 taken 117 times.
✗ Branch 22 → 47 not taken.
117 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
263
1/2
✓ Branch 24 → 25 taken 117 times.
✗ Branch 24 → 47 not taken.
117 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 120 bool QualType::isIterable(const ASTNode *node) const {
275 // Arrays are always considered iterable
276
3/4
✓ Branch 2 → 3 taken 120 times.
✗ Branch 2 → 50 not taken.
✓ Branch 3 → 4 taken 8 times.
✓ Branch 3 → 5 taken 112 times.
120 if (isArray())
277 8 return true;
278 // Otherwise the type must be a struct that implements the iterator interface
279
3/4
✓ Branch 5 → 6 taken 112 times.
✗ Branch 5 → 50 not taken.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 111 times.
112 if (!is(TY_STRUCT))
280 1 return false;
281
282
2/4
✓ Branch 10 → 11 taken 111 times.
✗ Branch 10 → 33 not taken.
✓ Branch 11 → 12 taken 111 times.
✗ Branch 11 → 31 not taken.
111 const QualType genericType(TY_GENERIC, "T");
283 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
284
3/6
✓ Branch 16 → 17 taken 111 times.
✗ Branch 16 → 45 not taken.
✓ Branch 19 → 20 taken 111 times.
✗ Branch 19 → 39 not taken.
✓ Branch 20 → 21 taken 111 times.
✗ Branch 20 → 37 not taken.
444 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERABLE_INTERFACE, data, {genericType});
285
1/2
✓ Branch 25 → 26 taken 111 times.
✗ Branch 25 → 50 not taken.
111 const QualType iteratorQualType(itType, TypeQualifiers::of(TY_INTERFACE));
286
1/2
✓ Branch 27 → 28 taken 111 times.
✗ Branch 27 → 50 not taken.
111 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 710 bool QualType::isStringObj() const {
295
4/6
✓ Branch 3 → 4 taken 122 times.
✓ Branch 3 → 10 taken 588 times.
✓ Branch 6 → 7 taken 122 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 122 times.
✗ Branch 8 → 10 not taken.
710 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 745 bool QualType::isErrorObj() const {
304
3/6
✓ Branch 3 → 4 taken 745 times.
✗ Branch 3 → 10 not taken.
✓ Branch 6 → 7 taken 745 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 745 times.
✗ Branch 8 → 10 not taken.
745 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 368831 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 745 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
322
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 745 times.
745 assert(!hasAnyGenericParts());
323
324 // Heap-allocated values may not be copied via memcpy
325
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 745 times.
745 if (qualifiers.isHeap)
326 return false;
327
328 // References can't be copied at all
329
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 745 times.
745 if (isRef())
330 return false;
331
332 // In case of an array, the item type is determining the copy triviality
333
2/2
✓ Branch 11 → 12 taken 8 times.
✓ Branch 11 → 16 taken 737 times.
745 if (isArray())
334
2/4
✓ Branch 12 → 13 taken 8 times.
✗ Branch 12 → 39 not taken.
✓ Branch 13 → 14 taken 8 times.
✗ Branch 13 → 39 not taken.
8 return getBase().isTriviallyCopyable(node);
335
336 // In case of a struct, the member types determine the copy triviality
337
2/2
✓ Branch 17 → 18 taken 214 times.
✓ Branch 17 → 37 taken 523 times.
737 if (is(TY_STRUCT)) {
338 // If the struct has a copy ctor, it is a non-trivially copyable one
339
1/2
✓ Branch 18 → 19 taken 214 times.
✗ Branch 18 → 54 not taken.
214 const Struct *spiceStruct = getStruct(node);
340
2/4
✓ Branch 19 → 20 taken 214 times.
✗ Branch 19 → 43 not taken.
✓ Branch 23 → 24 taken 214 times.
✗ Branch 23 → 40 not taken.
642 const std::vector args = {Arg(toConstRef(node), false)};
341
2/4
✓ Branch 27 → 28 taken 214 times.
✗ Branch 27 → 48 not taken.
✓ Branch 28 → 29 taken 214 times.
✗ Branch 28 → 46 not taken.
214 const Function *copyCtor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, args, true);
342
2/2
✓ Branch 31 → 32 taken 84 times.
✓ Branch 31 → 33 taken 130 times.
214 if (copyCtor != nullptr)
343 84 return false;
344
345 // Check if all member types are trivially copyable
346 256 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
347
1/2
✓ Branch 33 → 34 taken 130 times.
✗ Branch 33 → 52 not taken.
130 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
348 214 }
349
350 523 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 8338 bool QualType::isTriviallyDestructible(const ASTNode *node) const {
361
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 8338 times.
8338 assert(!hasAnyGenericParts());
362
363 // Heap-allocated values require manual de-allocation, which is done in the default/explicit dtor
364
2/2
✓ Branch 5 → 6 taken 579 times.
✓ Branch 5 → 7 taken 7759 times.
8338 if (qualifiers.isHeap)
365 579 return false;
366
367 // In case of an array, the item type is determining the destructing triviality
368
2/2
✓ Branch 8 → 9 taken 5 times.
✓ Branch 8 → 13 taken 7754 times.
7759 if (isArray())
369
2/4
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 31 not taken.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 31 not taken.
5 return getBase().isTriviallyDestructible(node);
370
371 // In case of a struct, the member types determine the destructing triviality
372
2/2
✓ Branch 14 → 15 taken 4304 times.
✓ Branch 14 → 29 taken 3450 times.
7754 if (is(TY_STRUCT)) {
373 // If the struct has a dtor, it is a non-trivially destructible one
374
1/2
✓ Branch 15 → 16 taken 4304 times.
✗ Branch 15 → 41 not taken.
4304 const Struct *spiceStruct = getStruct(node);
375
2/4
✓ Branch 19 → 20 taken 4304 times.
✗ Branch 19 → 34 not taken.
✓ Branch 20 → 21 taken 4304 times.
✗ Branch 20 → 32 not taken.
12912 const Function *dtor = FunctionManager::lookup(spiceStruct->scope, DTOR_FUNCTION_NAME, *this, {}, true);
376
2/2
✓ Branch 24 → 25 taken 1743 times.
✓ Branch 24 → 26 taken 2561 times.
4304 if (dtor != nullptr)
377 1743 return false;
378
379 // Check if all member types are trivially destructible
380 4477 const auto pred = [&](const QualType &fieldType) {
381 4477 return fieldType.isTriviallyDestructible(node);
382 2561 }; // NOLINT(*-no-recursion)
383
1/2
✓ Branch 26 → 27 taken 2561 times.
✗ Branch 26 → 41 not taken.
2561 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
384 }
385
386 3450 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 228 bool QualType::doesImplement(const QualType &implementedInterfaceType, const ASTNode *node) const {
397
2/4
✓ Branch 3 → 4 taken 228 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 228 times.
✗ Branch 5 → 7 not taken.
228 assert(is(TY_STRUCT) && implementedInterfaceType.is(TY_INTERFACE));
398 228 const Struct *spiceStruct = getStruct(node);
399
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 228 times.
228 assert(spiceStruct != nullptr);
400 228 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
401
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 228 times.
228 assert(interfaceType.is(TY_INTERFACE));
402 228 return implementedInterfaceType.matches(interfaceType, false, false, true);
403 228 });
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 16151 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
414
8/8
✓ Branch 2 → 3 taken 5452 times.
✓ Branch 2 → 9 taken 10699 times.
✓ Branch 4 → 5 taken 5217 times.
✓ Branch 4 → 9 taken 235 times.
✓ Branch 6 → 7 taken 324 times.
✓ Branch 6 → 9 taken 4893 times.
✓ Branch 8 → 9 taken 322 times.
✓ Branch 8 → 10 taken 2 times.
16151 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 127024 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreQualifiers, bool allowConstify) const {
428 // Special case: string is equivalent to const char*
429
6/8
✓ Branch 3 → 4 taken 18987 times.
✓ Branch 3 → 9 taken 108037 times.
✓ Branch 5 → 6 taken 1394 times.
✓ Branch 5 → 9 taken 17593 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1394 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 127024 times.
127024 if (is(TY_STRING) && otherType.isPtrTo(TY_CHAR) && otherType.isConst())
430 return true;
431
4/8
✓ Branch 13 → 14 taken 5645 times.
✓ Branch 13 → 19 taken 121379 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 19 taken 5645 times.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 127024 times.
127024 if (isPtrTo(TY_CHAR) && isConst() && otherType.is(TY_STRING))
432 return true;
433
434 // Compare type
435
2/2
✓ Branch 23 → 24 taken 51046 times.
✓ Branch 23 → 25 taken 75978 times.
127024 if (!type->matches(otherType.type, ignoreArraySize))
436 51046 return false;
437
438 // Ignore or compare qualifiers
439
4/4
✓ Branch 25 → 26 taken 14084 times.
✓ Branch 25 → 28 taken 61894 times.
✓ Branch 27 → 28 taken 13907 times.
✓ Branch 27 → 29 taken 177 times.
75978 return ignoreQualifiers || qualifiers.match(otherType.qualifiers, allowConstify);
440 }
441
442 /**
443 * Check for the matching compatibility of two types in terms of interface implementation.
444 * Useful for function matching as well as assignment type validation and function arg matching.
445 *
446 * @param structType Type to compare against
447 * @return Matching or not
448 */
449 60498 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
450
8/10
✓ Branch 2 → 3 taken 60498 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 212 times.
✓ Branch 3 → 6 taken 60286 times.
✓ Branch 4 → 5 taken 212 times.
✗ Branch 4 → 17 not taken.
✓ Branch 5 → 6 taken 37 times.
✓ Branch 5 → 7 taken 175 times.
✓ Branch 8 → 9 taken 60323 times.
✓ Branch 8 → 10 taken 175 times.
60498 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
451 60323 return false;
452
453 // Check if the rhs is a struct type that implements the lhs interface type
454
1/2
✓ Branch 10 → 11 taken 175 times.
✗ Branch 10 → 17 not taken.
175 const Struct *spiceStruct = structType.getStruct(nullptr);
455
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 175 times.
175 assert(spiceStruct != nullptr);
456 171 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
457
1/2
✓ Branch 13 → 14 taken 175 times.
✗ Branch 13 → 17 not taken.
175 return std::ranges::any_of(spiceStruct->interfaceTypes, pred);
458 }
459
460 /**
461 * Check if the current type is the same container type as another type.
462 * Container types include arrays, pointers, and references.
463 *
464 * @param other Other type
465 * @return Same container type or not
466 */
467 2686 bool QualType::isSameContainerTypeAs(const QualType &other) const { return type->isSameContainerTypeAs(other.type); }
468
469 /**
470 * Check if the current type is a self-referencing struct type
471 *
472 * @return Self-referencing struct type or not
473 */
474 23026 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
475
2/2
✓ Branch 3 → 4 taken 16904 times.
✓ Branch 3 → 5 taken 6122 times.
23026 if (!is(TY_STRUCT))
476 16904 return false;
477
478 // If no type was set by a previous iteration, we set it to the current type
479
2/2
✓ Branch 5 → 6 taken 4507 times.
✓ Branch 5 → 7 taken 1615 times.
6122 if (typeToCompareWith == nullptr)
480 4507 typeToCompareWith = this;
481
482 6122 Scope *baseTypeBodyScope = getBodyScope();
483
2/2
✓ Branch 24 → 9 taken 18425 times.
✓ Branch 24 → 25 taken 5784 times.
24209 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
484
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 18425 times.
18425 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
485 18425 const QualType &fieldType = field->getQualType();
486 // Check if the base type of the field matches with the current type, which is also a base type
487 // If yes, this is a self-referencing struct type
488
3/4
✓ Branch 15 → 16 taken 18425 times.
✗ Branch 15 → 27 not taken.
✓ Branch 17 → 18 taken 338 times.
✓ Branch 17 → 19 taken 18087 times.
18425 if (fieldType.getBase() == *typeToCompareWith)
489 338 return true;
490
491 // If the field is a struct, check if it is a self-referencing struct type
492
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 18087 times.
18087 if (fieldType.isSelfReferencingStructType(typeToCompareWith))
493 return true;
494 }
495 5784 return false;
496 }
497
498 /**
499 * Check if the given generic type list has a substantiation for the current (generic) type
500 *
501 * @param genericTypeList Generic type list
502 * @return Has substantiation or not
503 */
504 26011 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
505
1/2
✓ Branch 2 → 3 taken 26011 times.
✗ Branch 2 → 19 not taken.
26011 const QualType baseType = getBase();
506 // Check if the symbol type itself is generic
507
3/4
✓ Branch 3 → 4 taken 26011 times.
✗ Branch 3 → 19 not taken.
✓ Branch 4 → 5 taken 5132 times.
✓ Branch 4 → 7 taken 20879 times.
26011 if (baseType.is(TY_GENERIC)) {
508
1/2
✓ Branch 5 → 6 taken 5132 times.
✗ Branch 5 → 19 not taken.
5132 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
509
2/2
✓ Branch 3 → 4 taken 5124 times.
✓ Branch 3 → 5 taken 934 times.
6058 if (baseType.matches(t, true, true, true)) {
510 5124 t.used = true;
511 5124 return true;
512 }
513 934 return false;
514 5132 });
515 }
516
517 // If the type is non-generic check template types
518 20879 bool covered = true;
519 // Check template types
520
1/2
✓ Branch 7 → 8 taken 20879 times.
✗ Branch 7 → 19 not taken.
20879 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
521 2042 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
522 2042 return templateType.isCoveredByGenericTypeList(genericTypeList);
523 20879 };
524
1/2
✓ Branch 8 → 9 taken 20879 times.
✗ Branch 8 → 19 not taken.
20879 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
525
526 // If function/procedure, check param and return types
527
3/4
✓ Branch 9 → 10 taken 20879 times.
✗ Branch 9 → 17 not taken.
✓ Branch 10 → 11 taken 33 times.
✓ Branch 10 → 14 taken 20846 times.
20879 if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
528
1/2
✓ Branch 11 → 12 taken 33 times.
✗ Branch 11 → 18 not taken.
33 const QualTypeList &paramAndReturnTypes = baseType.getFunctionParamAndReturnTypes();
529 50 const auto innerPred = [&](const QualType &paramType) { // NOLINT(*-no-recursion)
530 50 return paramType.isCoveredByGenericTypeList(genericTypeList);
531 33 };
532
1/2
✓ Branch 12 → 13 taken 33 times.
✗ Branch 12 → 18 not taken.
33 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
533 }
534
535 20879 return covered;
536 }
537
538 /**
539 * Check if the current type needs de-allocation
540 *
541 * @return Needs de-allocation or not
542 */
543 1349 bool QualType::needsDeAllocation() const {
544
2/2
✓ Branch 3 → 4 taken 1280 times.
✓ Branch 3 → 5 taken 69 times.
1349 if (!isHeap())
545 1280 return false;
546 // We only need de-allocation, if we directly point to a heap-allocated type
547 // e.g. for heap TestStruct** we don't need to de-allocate, since it is a non-owning pointer to an owning pointer
548
2/4
✓ Branch 6 → 7 taken 69 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 69 times.
✗ Branch 8 → 10 not taken.
69 return isPtr() && !isPtrTo(TY_PTR);
549 }
550
551 /**
552 * Get the name of the symbol type as a string
553 *
554 * @param name Name stream
555 * @param withSize Include the array size for sized types
556 * @param ignorePublic Ignore any potential public qualifier
557 * @param withAliases Print aliases as is and not decompose them
558 */
559 476025 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
560 // Append the qualifiers
561
3/6
✓ Branch 2 → 3 taken 476025 times.
✗ Branch 2 → 31 not taken.
✓ Branch 3 → 4 taken 476025 times.
✗ Branch 3 → 31 not taken.
✓ Branch 4 → 5 taken 476025 times.
✗ Branch 4 → 31 not taken.
476025 const TypeQualifiers defaultForSuperType = TypeQualifiers::of(getBase().getSuperType());
562
5/6
✓ Branch 5 → 6 taken 301880 times.
✓ Branch 5 → 9 taken 174145 times.
✓ Branch 6 → 7 taken 103662 times.
✓ Branch 6 → 9 taken 198218 times.
✓ Branch 7 → 8 taken 103662 times.
✗ Branch 7 → 9 not taken.
476025 if (!ignorePublic && qualifiers.isPublic && !defaultForSuperType.isPublic)
563
1/2
✓ Branch 8 → 9 taken 103662 times.
✗ Branch 8 → 32 not taken.
103662 name << "public ";
564
3/4
✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 12 taken 476021 times.
✓ Branch 10 → 11 taken 4 times.
✗ Branch 10 → 12 not taken.
476025 if (qualifiers.isComposition && !defaultForSuperType.isComposition)
565
1/2
✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 32 not taken.
4 name << "compose ";
566
8/8
✓ Branch 12 → 13 taken 65739 times.
✓ Branch 12 → 17 taken 410286 times.
✓ Branch 13 → 14 taken 64458 times.
✓ Branch 13 → 17 taken 1281 times.
✓ Branch 15 → 16 taken 38683 times.
✓ Branch 15 → 17 taken 25775 times.
✓ Branch 18 → 19 taken 38683 times.
✓ Branch 18 → 20 taken 437342 times.
476025 if (qualifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
567
1/2
✓ Branch 19 → 20 taken 38683 times.
✗ Branch 19 → 32 not taken.
38683 name << "const ";
568
3/4
✓ Branch 20 → 21 taken 19440 times.
✓ Branch 20 → 23 taken 456585 times.
✓ Branch 21 → 22 taken 19440 times.
✗ Branch 21 → 23 not taken.
476025 if (qualifiers.isHeap && !defaultForSuperType.isHeap)
569
1/2
✓ Branch 22 → 23 taken 19440 times.
✗ Branch 22 → 32 not taken.
19440 name << "heap ";
570
4/4
✓ Branch 23 → 24 taken 57306 times.
✓ Branch 23 → 26 taken 418719 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 26 taken 57305 times.
476025 if (qualifiers.isSigned && !defaultForSuperType.isSigned)
571
1/2
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 32 not taken.
1 name << "signed ";
572
4/4
✓ Branch 26 → 27 taken 418719 times.
✓ Branch 26 → 29 taken 57306 times.
✓ Branch 27 → 28 taken 42549 times.
✓ Branch 27 → 29 taken 376170 times.
476025 if (!qualifiers.isSigned && defaultForSuperType.isSigned)
573
1/2
✓ Branch 28 → 29 taken 42549 times.
✗ Branch 28 → 32 not taken.
42549 name << "unsigned ";
574
575 // Loop through all chain elements
576
1/2
✓ Branch 29 → 30 taken 476025 times.
✗ Branch 29 → 32 not taken.
476025 type->getName(name, withSize, ignorePublic, withAliases);
577 476025 }
578
579 /**
580 * Get the name of the symbol type as a string
581 *
582 * @param withSize Include the array size for sized types
583 * @param ignorePublic Ignore any potential public qualifier
584 * @param withAliases Print aliases as is and not decompose them
585 * @return Symbol type name
586 */
587 283385 std::string QualType::getName(bool withSize, bool ignorePublic, bool withAliases) const {
588
1/2
✓ Branch 2 → 3 taken 283385 times.
✗ Branch 2 → 11 not taken.
283385 std::stringstream name;
589
1/2
✓ Branch 3 → 4 taken 283385 times.
✗ Branch 3 → 9 not taken.
283385 getName(name, withSize, ignorePublic, withAliases);
590
1/2
✓ Branch 4 → 5 taken 283385 times.
✗ Branch 4 → 9 not taken.
566770 return name.str();
591 283385 }
592
593 /**
594 * Convert the type to an LLVM type
595 *
596 * @param sourceFile Source file
597 * @return LLVM type
598 */
599 352229 llvm::Type *QualType::toLLVMType(SourceFile *sourceFile) const { return sourceFile->getLLVMType(type); }
600
601 /**
602 * Retrieve the pointer type to this type
603 *
604 * @param node ASTNode
605 * @return New type
606 */
607 24965 QualType QualType::toPtr(const ASTNode *node) const {
608 24965 QualType newType = *this;
609
2/2
✓ Branch 2 → 3 taken 24963 times.
✓ Branch 2 → 5 taken 2 times.
24965 newType.type = type->toPtr(node);
610 24963 return newType;
611 }
612
613 /**
614 * Retrieve the reference type to this type
615 *
616 * @param node ASTNode
617 * @return New type
618 */
619 12540 QualType QualType::toRef(const ASTNode *node) const {
620 12540 QualType newType = *this;
621
1/2
✓ Branch 2 → 3 taken 12540 times.
✗ Branch 2 → 5 not taken.
12540 newType.type = type->toRef(node);
622 12540 return newType;
623 }
624
625 /**
626 * Retrieve the const reference type of this type
627 *
628 * @param node ASTNode
629 * @return New type
630 */
631 4082 QualType QualType::toConstRef(const ASTNode *node) const {
632
1/2
✓ Branch 2 → 3 taken 4082 times.
✗ Branch 2 → 6 not taken.
4082 QualType newType = toRef(node);
633 4082 newType.makeConst();
634 4082 return newType;
635 }
636
637 /**
638 * Retrieve the array type of this type
639 *
640 * @param node ASTNode
641 * @param size Array size
642 * @param skipDynCheck Skip dynamic check
643 * @return New type
644 */
645 227 QualType QualType::toArr(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
646 227 QualType newType = *this;
647
2/2
✓ Branch 2 → 3 taken 226 times.
✓ Branch 2 → 5 taken 1 time.
227 newType.type = type->toArr(node, size, skipDynCheck);
648 226 return newType;
649 }
650
651 /**
652 * Retrieve the non-const type of this type
653 *
654 * @return New type
655 */
656 2022 QualType QualType::toNonConst() const {
657 2022 QualType newType = *this;
658 2022 newType.qualifiers.isConst = false;
659 2022 return newType;
660 }
661
662 /**
663 * Retrieve the contained type of this type
664 * This works on pointers, arrays, references and strings (which alias with char*)
665 *
666 * @return New type
667 */
668 86066 QualType QualType::getContained() const {
669
2/4
✓ Branch 2 → 3 taken 86066 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 86066 times.
86066 assert(isOneOf({TY_PTR, TY_REF, TY_ARRAY, TY_STRING}));
670 86066 QualType newType = *this;
671
1/2
✓ Branch 5 → 6 taken 86066 times.
✗ Branch 5 → 9 not taken.
86066 newType.type = type->getContained();
672 86066 return newType;
673 }
674
675 /**
676 * Retrieve the base type of this type
677 *
678 * @return New type
679 */
680 839912 QualType QualType::getBase() const {
681 839912 QualType newType = *this;
682
1/2
✓ Branch 2 → 3 taken 839912 times.
✗ Branch 2 → 5 not taken.
839912 newType.type = type->getBase();
683 839912 return newType;
684 }
685
686 /**
687 * Get aliased type for an alias type
688 *
689 * @param aliasEntry Entry of the alias definition
690 * @return Aliased type
691 */
692 999 QualType QualType::getAliased(const SymbolTableEntry *aliasEntry) const {
693
2/4
✓ Branch 2 → 3 taken 999 times.
✗ Branch 2 → 18 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 999 times.
999 assert(is(TY_ALIAS));
694 // Get type of aliased type container entry
695
1/2
✓ Branch 5 → 6 taken 999 times.
✗ Branch 5 → 18 not taken.
999 const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
696
1/2
✓ Branch 6 → 7 taken 999 times.
✗ Branch 6 → 16 not taken.
999 const SymbolTableEntry *aliasedTypeContainerEntry = aliasEntry->scope->lookupStrict(aliasedContainerEntryName);
697
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 999 times.
999 assert(aliasedTypeContainerEntry != nullptr);
698
1/2
✓ Branch 11 → 12 taken 999 times.
✗ Branch 11 → 16 not taken.
1998 return aliasedTypeContainerEntry->getQualType();
699 999 }
700
701 /**
702 * Remove reference of this type, if it is a reference
703 *
704 * @return New type
705 */
706
2/2
✓ Branch 3 → 4 taken 5267 times.
✓ Branch 3 → 5 taken 217516 times.
222783 QualType QualType::removeReferenceWrapper() const { return isRef() ? getContained() : *this; }
707
708 /**
709 * Auto-dereference the given symbol type (peeling off all ptr/ref wrappers).
710 * This process is NOT equivalent with getBase() because getBase() also removes e.g. array wrappers
711 *
712 * @return New type
713 */
714 23159 QualType QualType::autoDeReference() const {
715 23159 QualType newType = *this;
716
3/4
✓ Branch 5 → 6 taken 42875 times.
✗ Branch 5 → 10 not taken.
✓ Branch 6 → 3 taken 19716 times.
✓ Branch 6 → 7 taken 23159 times.
42875 while (newType.isOneOf({TY_PTR, TY_REF}))
717
1/2
✓ Branch 3 → 4 taken 19716 times.
✗ Branch 3 → 9 not taken.
19716 newType = newType.getContained();
718 23159 return newType;
719 }
720
721 /**
722 * Replace the base type with another one
723 *
724 * @param newBaseType New base type
725 * @return New type
726 */
727 20702 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
728 // Create new type
729
1/2
✓ Branch 3 → 4 taken 20702 times.
✗ Branch 3 → 9 not taken.
20702 const Type *newType = type->replaceBase(newBaseType.getType());
730 // Create new qualifiers
731
1/2
✓ Branch 4 → 5 taken 20702 times.
✗ Branch 4 → 9 not taken.
20702 TypeQualifiers newQualifiers = qualifiers.merge(newBaseType.qualifiers);
732 // Return the new qualified type
733 20702 return {newType, newQualifiers};
734 }
735
736 /**
737 * Retrieve the same type, but with lambda captures enabled
738 *
739 * @return Same type with lambda captures
740 */
741 53 QualType QualType::getWithLambdaCaptures(bool enabled /*=true*/) const {
742 // Create new type
743 53 const Type *newType = type->getWithLambdaCaptures(enabled);
744 // Return the new qualified type
745 53 return {newType, qualifiers};
746 }
747
748 /**
749 * Retrieve the same type, but with a new body scope
750 *
751 * @return Same type with body scope
752 */
753 23761 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
754 // Create new type
755 23761 const Type *newType = type->getWithBodyScope(bodyScope);
756 // Return the new qualified type
757 23761 return {newType, qualifiers};
758 }
759
760 /**
761 * Retrieve the same type, but with new template types
762 *
763 * @param templateTypes New template types
764 * @return Same type with new template types
765 */
766 3764 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
767 // Create new type
768 3764 const Type *newType = type->getWithTemplateTypes(templateTypes);
769 // Return the new qualified type
770 3764 return {newType, qualifiers};
771 }
772
773 /**
774 * Retrieve the same type, but with new base template types
775 *
776 * @param templateTypes New base template types
777 * @return Same type with new base template types
778 */
779 4939 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
780 // Create new type
781 4939 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
782 // Return the new qualified type
783 4939 return {newType, qualifiers};
784 }
785
786 /**
787 * Retrieve the same type, but with new function parameter and return types
788 *
789 * @param paramAndReturnTypes New parameter types
790 * @return Same type with new parameter types
791 */
792 14065 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
793 // Create new type
794 14065 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
795 // Return the new qualified type
796 14065 return {newType, qualifiers};
797 }
798
799 14046 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
800
1/2
✓ Branch 2 → 3 taken 14046 times.
✗ Branch 2 → 15 not taken.
14046 QualTypeList paramAndReturnTypes = paramTypes;
801
1/2
✓ Branch 5 → 6 taken 14046 times.
✗ Branch 5 → 11 not taken.
14046 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
802
1/2
✓ Branch 6 → 7 taken 14046 times.
✗ Branch 6 → 13 not taken.
28092 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
803 14046 }
804
805 /**
806 * Check if the current type is const
807 *
808 * Examples for const types:
809 * - const int
810 * - const TestStruct
811 * - const string
812 *
813 * Examples for non-const types:
814 * - double (reason: not marked const)
815 * - const int* (reason: pointer to const int is not const itself)
816 * - const TestStruct& (reason: reference to const TestStruct is not const itself)
817 *
818 * @return Is const or not
819 */
820
4/4
✓ Branch 3 → 4 taken 28790 times.
✓ Branch 3 → 6 taken 9975 times.
✓ Branch 4 → 5 taken 4611 times.
✓ Branch 4 → 6 taken 24179 times.
38765 bool QualType::isConst() const { return isExtendedPrimitive() && qualifiers.isConst; }
821
822 /**
823 * Check if the current type is marked signed
824 *
825 * @return Is signed or not
826 */
827 31855 bool QualType::isSigned() const {
828
2/4
✓ Branch 2 → 3 taken 31855 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 31855 times.
31855 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
829 31855 return qualifiers.isSigned;
830 }
831
832 /**
833 * Check if the current type is marked unsigned
834 *
835 * @return Is unsigned or not
836 */
837 2 bool QualType::isUnsigned() const {
838
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
839 2 return qualifiers.isUnsigned;
840 }
841
842 /**
843 * Check if the current type is marked inline
844 *
845 * @return Is inline or not
846 */
847 11006 bool QualType::isInline() const {
848
2/4
✓ Branch 2 → 3 taken 11006 times.
✗ Branch 2 → 7 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11006 times.
11006 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
849 11006 return qualifiers.isInline;
850 }
851
852 /**
853 * Check if the current type is marked public
854 *
855 * @return Is public or not
856 */
857 22295 bool QualType::isPublic() const {
858
5/8
✓ Branch 2 → 3 taken 22295 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 20957 times.
✓ Branch 3 → 7 taken 1338 times.
✓ Branch 4 → 5 taken 20957 times.
✗ Branch 4 → 9 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 20957 times.
22295 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
859 22295 return qualifiers.isPublic;
860 }
861
862 /**
863 * Check if the current type is marked heap
864 *
865 * @return Is heap or not
866 */
867 12973 bool QualType::isHeap() const { return qualifiers.isHeap; }
868
869 /**
870 * Check if the current type is marked as composition
871 *
872 * @return Is composition or not
873 */
874 41 bool QualType::isComposition() const { return qualifiers.isComposition; }
875
876 /**
877 * Make the current type const
878 *
879 * @param isConst Is const or not
880 */
881 4082 void QualType::makeConst(bool isConst) { qualifiers.isConst = isConst; }
882
883 /**
884 * Make the current type unsigned
885 *
886 * @param isUnsigned Is unsigned or not
887 */
888 14 void QualType::makeUnsigned(bool isUnsigned) {
889
2/4
✓ Branch 2 → 3 taken 14 times.
✗ Branch 2 → 6 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 14 times.
14 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
890 14 qualifiers.isSigned = !isUnsigned;
891 14 qualifiers.isUnsigned = isUnsigned;
892 14 }
893
894 /**
895 * Make the current type public
896 *
897 * @param isPublic Is public or not
898 */
899 376 void QualType::makePublic(bool isPublic) {
900
4/8
✓ Branch 2 → 3 taken 376 times.
✗ Branch 2 → 8 not taken.
✓ Branch 3 → 4 taken 376 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 376 times.
✗ Branch 4 → 8 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 376 times.
376 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
901 376 qualifiers.isPublic = isPublic;
902 376 }
903
904 /**
905 * Make the current type heap
906 *
907 * @param isHeap Is heap or not
908 */
909 67 void QualType::makeHeap(bool isHeap) { qualifiers.isHeap = isHeap; }
910
911 /**
912 * Check if two types are equal
913 *
914 * @param lhs Left-hand side type
915 * @param rhs Right-hand side type
916 * @return Equal or not
917 */
918 459451 bool operator==(const QualType &lhs, const QualType &rhs) { return lhs.type == rhs.type; }
919
920 /**
921 * Check if two types are not equal
922 *
923 * @param lhs Left-hand side type
924 * @param rhs Right-hand side type
925 * @return Not equal or not
926 */
927 111700 bool operator!=(const QualType &lhs, const QualType &rhs) { return !(lhs == rhs); }
928
929 /**
930 * Remove pointers / arrays / references if both types have them as far as possible.
931 * Furthermore, remove reference wrappers if possible.
932 *
933 * @param typeA Candidate type
934 * @param typeB Requested type
935 */
936 92484 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
937
938 } // namespace spice::compiler
939