GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/QualType.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 232 242 95.9%
Functions: 75 77 97.4%
Branches: 203 338 60.1%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 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 7448201 QualType::QualType(SuperType superType) : type(TypeRegistry::getOrInsert(superType)), specifiers(TypeSpecifiers::of(superType)) {}
19 1253 QualType::QualType(SuperType superType, const std::string &subType)
20 1253 : type(TypeRegistry::getOrInsert(superType, subType)), specifiers(TypeSpecifiers::of(superType)) {}
21 45298 QualType::QualType(const Type *type, TypeSpecifiers specifiers) : type(type), specifiers(specifiers) {}
22
23 /**
24 * Get the super type of the underlying type
25 *
26 * @return Super type
27 */
28 915899 SuperType QualType::getSuperType() const { return type->getSuperType(); }
29
30 /**
31 * Get the subtype of the underlying type
32 *
33 * @return Subtype
34 */
35 206830 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 397 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 98567 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 21 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 97 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 99 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 134 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 72671 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 * @return Struct instance
91 */
92 3120 Struct *QualType::getStruct(const ASTNode *node) const {
93
2/4
✓ Branch 1 taken 3120 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3120 times.
3120 assert(is(TY_STRUCT));
94
1/2
✓ Branch 1 taken 3120 times.
✗ Branch 2 not taken.
3120 Scope *structDefScope = getBodyScope()->parent;
95
2/4
✓ Branch 1 taken 3120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3120 times.
✗ Branch 5 not taken.
3120 const std::string structName = getSubType();
96
1/2
✓ Branch 1 taken 3120 times.
✗ Branch 2 not taken.
3120 const QualTypeList &templateTypes = getTemplateTypes();
97
1/2
✓ Branch 1 taken 3120 times.
✗ Branch 2 not taken.
6240 return StructManager::match(structDefScope, structName, templateTypes, node);
98 3120 }
99
100 /**
101 * Get the interface instance for an interface type
102 *
103 * @param node Accessing AST node
104 * @return Interface instance
105 */
106 247 Interface *QualType::getInterface(const ASTNode *node) const {
107
2/4
✓ Branch 1 taken 247 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 247 times.
247 assert(is(TY_INTERFACE));
108
1/2
✓ Branch 1 taken 247 times.
✗ Branch 2 not taken.
247 Scope *interfaceDefScope = getBodyScope()->parent;
109
2/4
✓ Branch 1 taken 247 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 247 times.
✗ Branch 5 not taken.
247 const std::string structName = getSubType();
110
1/2
✓ Branch 1 taken 247 times.
✗ Branch 2 not taken.
247 const QualTypeList &templateTypes = getTemplateTypes();
111
1/2
✓ Branch 1 taken 247 times.
✗ Branch 2 not taken.
494 return InterfaceManager::match(interfaceDefScope, structName, templateTypes, node);
112 247 }
113
114 /**
115 * Check if the underlying type is of a certain super type
116 *
117 * @param superType Super type
118 * @return Is of super type or not
119 */
120 2162772 bool QualType::is(SuperType superType) const { return type->is(superType); }
121
122 /**
123 * Check if the underlying type is one of a list of super types
124 *
125 * @param superTypes List of super types
126 * @return Is one of the super types or not
127 */
128 379855 bool QualType::isOneOf(const std::initializer_list<SuperType> &superTypes) const { return type->isOneOf(superTypes); }
129
130 /**
131 * Check if the base type of the underlying type is a certain super type
132 *
133 * @param superType Super type
134 * @return Is base type or not
135 */
136 370339 bool QualType::isBase(SuperType superType) const { return type->isBase(superType); }
137
138 /**
139 * Check if the underlying type is a primitive type
140 *
141 * @return Primitive or not
142 */
143 36725 bool QualType::isPrimitive() const { return type->isPrimitive(); }
144
145 /**
146 * Check if the underlying type is a pointer
147 *
148 * @return Pointer or not
149 */
150 151043 bool QualType::isPtr() const { return type->isPtr(); }
151
152 /**
153 * Check if the underlying type is a pointer to a certain super type
154 *
155 * @param superType Super type
156 * @return Pointer to super type or not
157 */
158
7/10
✓ Branch 1 taken 18691 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 145 times.
✓ Branch 4 taken 18546 times.
✓ Branch 6 taken 145 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 145 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 143 times.
18691 bool QualType::isPtrTo(SuperType superType) const { return isPtr() && getContained().is(superType); }
159
160 /**
161 * Check if the underlying type is a reference
162 *
163 * @return Reference or not
164 */
165 315948 bool QualType::isRef() const { return type->isRef(); }
166
167 /**
168 * Check if the underlying type is a reference to a certain super type
169 *
170 * @param superType Super type
171 * @return Reference to super type or not
172 */
173 bool QualType::isRefTo(SuperType superType) const { return isRef() && getContained().is(superType); }
174
175 /**
176 * Check if the underlying type is an array
177 *
178 * @return Array or not
179 */
180 44078 bool QualType::isArray() const { return type->isArray(); }
181
182 /**
183 * Check if the underlying type is an array of a certain super type
184 *
185 * @param superType Super type
186 * @return Array of super type or not
187 */
188
7/10
✓ Branch 1 taken 12940 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 12891 times.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 49 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
✓ Branch 12 taken 43 times.
12940 bool QualType::isArrayOf(SuperType superType) const { return isArray() && getContained().is(superType); }
189
190 /**
191 * Check if the underlying type is a const reference
192 *
193 * @return Const reference or not
194 */
195
3/4
✓ Branch 1 taken 230 times.
✓ Branch 2 taken 189 times.
✓ Branch 4 taken 230 times.
✗ Branch 5 not taken.
419 bool QualType::isConstRef() const { return isConst() && isRef(); }
196
197 /**
198 * Check if the current type is an iterator
199 *
200 * @param node ASTNode
201 * @return Iterator or not
202 */
203 89 bool QualType::isIterator(const ASTNode *node) const {
204 // The type must be a struct that implements the iterator interface
205
3/4
✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 88 times.
89 if (!is(TY_STRUCT))
206 1 return false;
207
208
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
88 const QualType genericType(TY_GENERIC, "T");
209 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
210
3/6
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 88 times.
✗ Branch 8 not taken.
352 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERATOR_INTERFACE, data, {genericType});
211
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 const QualType iteratorQualType(itType, TypeSpecifiers::of(TY_INTERFACE));
212
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 return doesImplement(iteratorQualType, node);
213 }
214
215 /**
216 * Check if the current type is an iterable
217 * - Arrays are always considered iterable
218 * - Otherwise the type must be a struct that implements the iterator interface
219 *
220 * @param node ASTNode
221 * @return Iterable or not
222 */
223 91 bool QualType::isIterable(const ASTNode *node) const {
224 // Arrays are always considered iterable
225
3/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 83 times.
91 if (isArray())
226 8 return true;
227 // Otherwise the type must be a struct that implements the iterator interface
228
3/4
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 82 times.
83 if (!is(TY_STRUCT))
229 1 return false;
230
231
2/4
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
82 const QualType genericType(TY_GENERIC, "T");
232 static constexpr TypeChainElementData data = {.bodyScope = nullptr};
233
3/6
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 82 times.
✗ Branch 8 not taken.
328 const Type *itType = TypeRegistry::getOrInsert(TY_INTERFACE, IITERATOR_NAME, TYPE_ID_ITERABLE_INTERFACE, data, {genericType});
234
1/2
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
82 const QualType iteratorQualType(itType, TypeSpecifiers::of(TY_INTERFACE));
235
1/2
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
82 return doesImplement(iteratorQualType, node);
236 }
237
238 /**
239 * Check if the current type is a string object
240 *
241 * @return String object or not
242 */
243 7100 bool QualType::isStringObj() const {
244
5/6
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 6563 times.
✓ Branch 5 taken 193 times.
✓ Branch 6 taken 344 times.
✓ Branch 8 taken 193 times.
✗ Branch 9 not taken.
7100 return is(TY_STRUCT) && getSubType() == STROBJ_NAME && getBodyScope()->sourceFile->isStdFile;
245 }
246
247 /**
248 * Check if the current type is an error object
249 *
250 * @return Error object or not
251 */
252 366 bool QualType::isErrorObj() const {
253
3/6
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 366 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 366 times.
✗ Branch 9 not taken.
366 return is(TY_STRUCT) && getSubType() == ERROBJ_NAME && getBodyScope()->sourceFile->isStdFile;
254 }
255
256 /**
257 * Check if the current type has any generic parts
258 *
259 * @return Generic parts or not
260 */
261 282985 bool QualType::hasAnyGenericParts() const { return type->hasAnyGenericParts(); }
262
263 /**
264 * Check if copying an instance of the current type would require calling other copy ctors.
265 * If this function return true, the type can be copied by calling memcpy.
266 *
267 * @param node Accessing ASTNode
268 * @return Trivially copyable or not
269 */
270 233 bool QualType::isTriviallyCopyable(const ASTNode *node) const { // NOLINT(*-no-recursion)
271 // Heap-allocated values may not be copied via memcpy
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 233 times.
233 if (specifiers.isHeap)
273 return false;
274
275 // References can't be copied at all
276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 233 times.
233 if (is(TY_REF))
277 return false;
278
279 // In case of an array, the item type is determining the copy triviality
280
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 233 times.
233 if (is(TY_ARRAY))
281 return getBase().isTriviallyCopyable(node);
282
283 // In case of a struct, the member types determine the copy triviality
284
2/2
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 155 times.
233 if (is(TY_STRUCT)) {
285 // If the struct has a copy ctor, it is a non-trivially copyable one
286
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 const Struct *spiceStruct = getStruct(node);
287
288 // If the struct itself has a copy ctor, it is not trivially copyable
289
2/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 78 times.
✗ Branch 6 not taken.
234 const std::vector args = {Arg(toConstRef(node), false)};
290
2/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 78 times.
✗ Branch 5 not taken.
78 const Function *copyCtor = FunctionManager::lookup(spiceStruct->scope, CTOR_FUNCTION_NAME, *this, args, true);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (copyCtor != nullptr)
292 return false;
293
294 // Check if all member types are trivially copyable
295 155 const auto pred = [&](const QualType &fieldType) { return fieldType.isTriviallyCopyable(node); }; // NOLINT(*-no-recursion)
296
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 return std::ranges::all_of(spiceStruct->fieldTypes, pred);
297 78 }
298
299 155 return true;
300 }
301
302 /**
303 * Check if the current type implements the given interface type
304 *
305 * @param symbolType Interface type
306 * @param node Accessing ASTNode
307 * @return Struct implements interface or not
308 */
309 170 bool QualType::doesImplement(const QualType &symbolType, const ASTNode *node) const {
310
2/4
✓ Branch 1 taken 170 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 170 times.
✗ Branch 5 not taken.
170 assert(is(TY_STRUCT) && symbolType.is(TY_INTERFACE));
311 170 const Struct *spiceStruct = getStruct(node);
312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 assert(spiceStruct != nullptr);
313 170 return std::ranges::any_of(spiceStruct->interfaceTypes, [&](const QualType &interfaceType) {
314
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
170 assert(interfaceType.is(TY_INTERFACE));
315 170 return symbolType.matches(interfaceType, false, false, true);
316 170 });
317 }
318
319 /**
320 * Check if a certain input type can be bound (assigned) to the current type->
321 *
322 * @param inputType Qualified type, which should be bound to the current type
323 * @param isTemporary Is the input type a temporary type
324 * @return Can be bound or not
325 */
326 8952 bool QualType::canBind(const QualType &inputType, bool isTemporary) const {
327
8/8
✓ Branch 0 taken 2363 times.
✓ Branch 1 taken 6589 times.
✓ Branch 3 taken 2242 times.
✓ Branch 4 taken 121 times.
✓ Branch 6 taken 218 times.
✓ Branch 7 taken 2024 times.
✓ Branch 9 taken 216 times.
✓ Branch 10 taken 2 times.
8952 return !isTemporary || inputType.type->isRef() || !type->isRef() || isConstRef();
328 }
329
330 /**
331 * Check for the matching compatibility of two types.
332 * Useful for struct and function matching as well as assignment type validation and function arg matching.
333 *
334 * @param otherType Type to compare against
335 * @param ignoreArraySize Ignore array sizes
336 * @param ignoreSpecifiers Ignore specifiers, except for pointer and reference types
337 * @param allowConstify Match when the types are the same, but the lhs type is more const restrictive than the rhs type
338 * @return Matching or not
339 */
340 79883 bool QualType::matches(const QualType &otherType, bool ignoreArraySize, bool ignoreSpecifiers, bool allowConstify) const {
341 // Compare type
342
2/2
✓ Branch 1 taken 28447 times.
✓ Branch 2 taken 51436 times.
79883 if (!type->matches(otherType.type, ignoreArraySize))
343 28447 return false;
344
345 // Ignore or compare specifiers
346
4/4
✓ Branch 0 taken 20336 times.
✓ Branch 1 taken 31100 times.
✓ Branch 3 taken 19937 times.
✓ Branch 4 taken 399 times.
51436 return ignoreSpecifiers || specifiers.match(otherType.specifiers, allowConstify);
347 }
348
349 /**
350 * Check for the matching compatibility of two types in terms of interface implementation.
351 * Useful for function matching as well as assignment type validation and function arg matching.
352 *
353 * @param structType Type to compare against
354 * @return Matching or not
355 */
356 49846 bool QualType::matchesInterfaceImplementedByStruct(const QualType &structType) const {
357
8/10
✓ Branch 1 taken 49846 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 246 times.
✓ Branch 4 taken 49600 times.
✓ Branch 6 taken 246 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 238 times.
✓ Branch 10 taken 49608 times.
✓ Branch 11 taken 238 times.
49846 if (!is(TY_INTERFACE) || !structType.is(TY_STRUCT))
358 49608 return false;
359
360 // Check if the rhs is a struct type that implements the lhs interface type
361
1/2
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
238 const Struct *spiceStruct = structType.getStruct(nullptr);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 assert(spiceStruct != nullptr);
363 237 const auto pred = [&](const QualType &interfaceType) { return matches(interfaceType, false, false, true); };
364
1/2
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
238 return std::ranges::any_of(spiceStruct->interfaceTypes, pred);
365 }
366
367 /**
368 * Check if the current type is the same container type as another type.
369 * Container types include arrays, pointers, and references.
370 *
371 * @param other Other type
372 * @return Same container type or not
373 */
374 2357 bool QualType::isSameContainerTypeAs(const QualType &other) const { return type->isSameContainerTypeAs(other.type); }
375
376 /**
377 * Check if the current type is a self-referencing struct type
378 *
379 * @return Self-referencing struct type or not
380 */
381 16327 bool QualType::isSelfReferencingStructType(const QualType *typeToCompareWith) const { // NOLINT(*-no-recursion)
382
2/2
✓ Branch 1 taken 12138 times.
✓ Branch 2 taken 4189 times.
16327 if (!is(TY_STRUCT))
383 12138 return false;
384
385 // If no type was set by a previous iteration, we set it to the current type
386
2/2
✓ Branch 0 taken 3250 times.
✓ Branch 1 taken 939 times.
4189 if (typeToCompareWith == nullptr)
387 3250 typeToCompareWith = this;
388
389 4189 Scope *baseTypeBodyScope = getBodyScope();
390
2/2
✓ Branch 1 taken 12888 times.
✓ Branch 2 taken 4000 times.
16888 for (size_t i = 0; i < baseTypeBodyScope->getFieldCount(); i++) {
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12888 times.
12888 const SymbolTableEntry *field = baseTypeBodyScope->lookupField(i);
392 // Check if the base type of the field matches with the current type, which is also a base type
393 // If yes, this is a self-referencing struct type
394
4/6
✓ Branch 1 taken 12888 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12888 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 189 times.
✓ Branch 8 taken 12699 times.
12888 if (field->getQualType().getBase() == *typeToCompareWith)
395 189 return true;
396
397 // If the field is a struct, check if it is a self-referencing struct type
398
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 12699 times.
12699 if (field->getQualType().isSelfReferencingStructType(typeToCompareWith))
399 return true;
400 }
401 4000 return false;
402 }
403
404 /**
405 * Check if the given generic type list has a substantiation for the current (generic) type
406 *
407 * @param genericTypeList Generic type list
408 * @return Has substantiation or not
409 */
410 14672 bool QualType::isCoveredByGenericTypeList(std::vector<GenericType> &genericTypeList) const { // NOLINT(*-no-recursion)
411
1/2
✓ Branch 1 taken 14672 times.
✗ Branch 2 not taken.
14672 const QualType baseType = getBase();
412 // Check if the symbol type itself is generic
413
3/4
✓ Branch 1 taken 14672 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2955 times.
✓ Branch 4 taken 11717 times.
14672 if (baseType.is(TY_GENERIC)) {
414
1/2
✓ Branch 1 taken 2955 times.
✗ Branch 2 not taken.
2955 return std::ranges::any_of(genericTypeList, [&](GenericType &t) {
415
2/2
✓ Branch 1 taken 2947 times.
✓ Branch 2 taken 573 times.
3520 if (baseType.matches(t, true, true, true)) {
416 2947 t.used = true;
417 2947 return true;
418 }
419 573 return false;
420 2955 });
421 }
422
423 // If the type is non-generic check template types
424 11717 bool covered = true;
425 // Check template types
426
1/2
✓ Branch 1 taken 11717 times.
✗ Branch 2 not taken.
11717 const QualTypeList &baseTemplateTypes = baseType.getTemplateTypes();
427 1332 auto outerPred = [&](const QualType &templateType) { // NOLINT(*-no-recursion)
428 1332 return templateType.isCoveredByGenericTypeList(genericTypeList);
429 11717 };
430
1/2
✓ Branch 1 taken 11717 times.
✗ Branch 2 not taken.
11717 covered &= std::ranges::all_of(baseTemplateTypes, outerPred);
431
432 // If function/procedure, check param and return types
433
3/4
✓ Branch 1 taken 11717 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 11680 times.
11717 if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
434
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 const QualTypeList &paramAndReturnTypes = baseType.getFunctionParamAndReturnTypes();
435 62 const auto innerPred = [&](const QualType &paramType) { // NOLINT(*-no-recursion)
436 62 return paramType.isCoveredByGenericTypeList(genericTypeList);
437 37 };
438
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 covered &= std::ranges::all_of(paramAndReturnTypes, innerPred);
439 }
440
441 11717 return covered;
442 }
443
444 /**
445 * Check if the current type needs de-allocation
446 *
447 * @return Needs de-allocation or not
448 */
449 1016 bool QualType::needsDeAllocation() const {
450
2/2
✓ Branch 1 taken 972 times.
✓ Branch 2 taken 44 times.
1016 if (!isHeap())
451 972 return false;
452 // We only need de-allocation, if we directly point to a heap-allocated type
453 // e.g. for heap TestStruct** we don't need to de-allocate, since it is a non-owning pointer to an owning pointer
454
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
44 return isPtr() && !isPtrTo(TY_PTR);
455 }
456
457 /**
458 * Get the name of the symbol type as a string
459 *
460 * @param name Name stream
461 * @param withSize Include the array size for sized types
462 * @param ignorePublic Ignore any potential public specifier
463 */
464 609155 void QualType::getName(std::stringstream &name, bool withSize, bool ignorePublic) const {
465 // Append the specifiers
466
3/6
✓ Branch 1 taken 609155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 609155 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 609155 times.
✗ Branch 8 not taken.
609155 const TypeSpecifiers defaultForSuperType = TypeSpecifiers::of(getBase().getSuperType());
467
5/6
✓ Branch 0 taken 538939 times.
✓ Branch 1 taken 70216 times.
✓ Branch 2 taken 196792 times.
✓ Branch 3 taken 342147 times.
✓ Branch 4 taken 196792 times.
✗ Branch 5 not taken.
609155 if (!ignorePublic && specifiers.isPublic && !defaultForSuperType.isPublic)
468
1/2
✓ Branch 1 taken 196792 times.
✗ Branch 2 not taken.
196792 name << "public ";
469
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 609151 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
609155 if (specifiers.isComposition && !defaultForSuperType.isComposition)
470
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 name << "compose ";
471
8/8
✓ Branch 0 taken 85116 times.
✓ Branch 1 taken 524039 times.
✓ Branch 2 taken 84157 times.
✓ Branch 3 taken 959 times.
✓ Branch 5 taken 59642 times.
✓ Branch 6 taken 24515 times.
✓ Branch 7 taken 59642 times.
✓ Branch 8 taken 549513 times.
609155 if (specifiers.isConst && !defaultForSuperType.isConst && type->typeChain.size() > 1)
472
1/2
✓ Branch 1 taken 59642 times.
✗ Branch 2 not taken.
59642 name << "const ";
473
3/4
✓ Branch 0 taken 20634 times.
✓ Branch 1 taken 588521 times.
✓ Branch 2 taken 20634 times.
✗ Branch 3 not taken.
609155 if (specifiers.isHeap && !defaultForSuperType.isHeap)
474
1/2
✓ Branch 1 taken 20634 times.
✗ Branch 2 not taken.
20634 name << "heap ";
475
3/4
✓ Branch 0 taken 45134 times.
✓ Branch 1 taken 564021 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 45134 times.
609155 if (specifiers.isSigned && !defaultForSuperType.isSigned)
476 name << "signed ";
477
4/4
✓ Branch 0 taken 564021 times.
✓ Branch 1 taken 45134 times.
✓ Branch 2 taken 68589 times.
✓ Branch 3 taken 495432 times.
609155 if (!specifiers.isSigned && defaultForSuperType.isSigned)
478
1/2
✓ Branch 1 taken 68589 times.
✗ Branch 2 not taken.
68589 name << "unsigned ";
479
480 // Loop through all chain elements
481
1/2
✓ Branch 1 taken 609155 times.
✗ Branch 2 not taken.
609155 type->getName(name, withSize);
482 609155 }
483
484 /**
485 * Get the name of the symbol type as a string
486 *
487 * @param withSize Include the array size for sized types
488 * @param ignorePublic Ignore any potential public specifier
489 * @return Symbol type name
490 */
491 431309 std::string QualType::getName(bool withSize, bool ignorePublic) const {
492
1/2
✓ Branch 1 taken 431309 times.
✗ Branch 2 not taken.
431309 std::stringstream name;
493
1/2
✓ Branch 1 taken 431309 times.
✗ Branch 2 not taken.
431309 getName(name, withSize, ignorePublic);
494
1/2
✓ Branch 1 taken 431309 times.
✗ Branch 2 not taken.
862618 return name.str();
495 431309 }
496
497 /**
498 * Convert the type to an LLVM type
499 *
500 * @param sourceFile Source file
501 * @return LLVM type
502 */
503 156522 llvm::Type *QualType::toLLVMType(SourceFile *sourceFile) const { return sourceFile->getLLVMType(type); }
504
505 /**
506 * Retrieve the pointer type to this type
507 *
508 * @param node ASTNode
509 * @return New type
510 */
511 10774 QualType QualType::toPtr(const ASTNode *node) const {
512 10774 QualType newType = *this;
513
2/2
✓ Branch 1 taken 10772 times.
✓ Branch 2 taken 2 times.
10774 newType.type = type->toPtr(node);
514 10772 return newType;
515 }
516
517 /**
518 * Retrieve the reference type to this type
519 *
520 * @param node ASTNode
521 * @return New type
522 */
523 11992 QualType QualType::toRef(const ASTNode *node) const {
524 11992 QualType newType = *this;
525
1/2
✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
11992 newType.type = type->toRef(node);
526 11992 return newType;
527 }
528
529 /**
530 * Retrieve the const reference type of this type
531 *
532 * @param node ASTNode
533 * @return New type
534 */
535 6544 QualType QualType::toConstRef(const ASTNode *node) const {
536
1/2
✓ Branch 1 taken 6544 times.
✗ Branch 2 not taken.
6544 QualType qualType = toRef(node);
537 6544 qualType.makeConst();
538 6544 return qualType;
539 }
540
541 /**
542 * Retrieve the array type of this type
543 *
544 * @param node ASTNode
545 * @param size Array size
546 * @param skipDynCheck Skip dynamic check
547 * @return New type
548 */
549 201 QualType QualType::toArray(const ASTNode *node, size_t size, bool skipDynCheck /*=false*/) const {
550 201 QualType newType = *this;
551
2/2
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 1 times.
201 newType.type = type->toArr(node, size, skipDynCheck);
552 200 return newType;
553 }
554
555 /**
556 * Retrieve the non-const type of this type
557 *
558 * @return New type
559 */
560 354 QualType QualType::toNonConst() const {
561 354 QualType qualType = *this;
562 354 qualType.specifiers.isConst = false;
563 354 return qualType;
564 }
565
566 /**
567 * Retrieve the contained type of this type
568 * This works on pointers, arrays, references and strings (which alias with char*)
569 *
570 * @return New type
571 */
572 43821 QualType QualType::getContained() const {
573
2/4
✓ Branch 1 taken 43821 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 43821 times.
43821 assert(isOneOf({TY_PTR, TY_ARRAY, TY_REF, TY_STRING}));
574 43821 QualType qualType = *this;
575
1/2
✓ Branch 1 taken 43821 times.
✗ Branch 2 not taken.
43821 qualType.type = type->getContained();
576 43821 return qualType;
577 }
578
579 /**
580 * Retrieve the base type of this type
581 *
582 * @return New type
583 */
584 839085 QualType QualType::getBase() const {
585 839085 QualType qualType = *this;
586
1/2
✓ Branch 1 taken 839085 times.
✗ Branch 2 not taken.
839085 qualType.type = type->getBase();
587 839085 return qualType;
588 }
589
590 /**
591 * Remove reference of this type, if it is a reference
592 *
593 * @return New type
594 */
595
2/2
✓ Branch 1 taken 3514 times.
✓ Branch 2 taken 135567 times.
139081 QualType QualType::removeReferenceWrapper() const { return isRef() ? getContained() : *this; }
596
597 /**
598 * Replace the base type with another one
599 *
600 * @param newBaseType New base type
601 * @return The new type
602 */
603 10152 QualType QualType::replaceBaseType(const QualType &newBaseType) const {
604 // Create new type
605
1/2
✓ Branch 2 taken 10152 times.
✗ Branch 3 not taken.
10152 const Type *newType = type->replaceBase(newBaseType.getType());
606 // Create new specifiers
607
1/2
✓ Branch 1 taken 10152 times.
✗ Branch 2 not taken.
10152 TypeSpecifiers newSpecifiers = specifiers.merge(newBaseType.specifiers);
608 // Return the new qualified type
609 10152 return {newType, newSpecifiers};
610 }
611
612 /**
613 * Retrieve the same type, but with lambda captures enabled
614 *
615 * @return Same type with lambda captures
616 */
617 42 QualType QualType::getWithLambdaCaptures(bool enabled /*=true*/) const {
618 // Create new type
619 42 const Type *newType = type->getWithLambdaCaptures(enabled);
620 // Return the new qualified type
621 42 return {newType, specifiers};
622 }
623
624 /**
625 * Retrieve the same type, but with a new body scope
626 *
627 * @return Same type with body scope
628 */
629 19609 QualType QualType::getWithBodyScope(Scope *bodyScope) const {
630 // Create new type
631 19609 const Type *newType = type->getWithBodyScope(bodyScope);
632 // Return the new qualified type
633 19609 return {newType, specifiers};
634 }
635
636 /**
637 * Retrieve the same type, but with new template types
638 *
639 * @param templateTypes New template types
640 * @return Same type with new template types
641 */
642 2656 QualType QualType::getWithTemplateTypes(const QualTypeList &templateTypes) const {
643 // Create new type
644 2656 const Type *newType = type->getWithTemplateTypes(templateTypes);
645 // Return the new qualified type
646 2656 return {newType, specifiers};
647 }
648
649 /**
650 * Retrieve the same type, but with new base template types
651 *
652 * @param templateTypes New base template types
653 * @return Same type with new base template types
654 */
655 3628 QualType QualType::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
656 // Create new type
657 3628 const Type *newType = type->getWithBaseTemplateTypes(templateTypes);
658 // Return the new qualified type
659 3628 return {newType, specifiers};
660 }
661
662 /**
663 * Retrieve the same type, but with new function parameter and return types
664 *
665 * @param paramAndReturnTypes New parameter types
666 * @return Same type with new parameter types
667 */
668 8356 QualType QualType::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
669 // Create new type
670 8356 const Type *newType = type->getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
671 // Return the new qualified type
672 8356 return {newType, specifiers};
673 }
674
675 8314 QualType QualType::getWithFunctionParamAndReturnTypes(const QualType &returnType, const QualTypeList &paramTypes) const {
676
1/2
✓ Branch 1 taken 8314 times.
✗ Branch 2 not taken.
8314 QualTypeList paramAndReturnTypes = paramTypes;
677
1/2
✓ Branch 3 taken 8314 times.
✗ Branch 4 not taken.
8314 paramAndReturnTypes.insert(paramAndReturnTypes.begin(), returnType);
678
1/2
✓ Branch 1 taken 8314 times.
✗ Branch 2 not taken.
16628 return getWithFunctionParamAndReturnTypes(paramAndReturnTypes);
679 8314 }
680
681 /**
682 * Check if the current type is marked const
683 *
684 * @return Is const or not
685 */
686 71371 bool QualType::isConst() const { return specifiers.isConst; }
687
688 /**
689 * Check if the current type is marked signed
690 *
691 * @return Is signed or not
692 */
693 10147 bool QualType::isSigned() const {
694
2/4
✓ Branch 1 taken 10147 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10147 times.
10147 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
695 10147 return specifiers.isSigned;
696 }
697
698 /**
699 * Check if the current type is marked unsigned
700 *
701 * @return Is unsigned or not
702 */
703 bool QualType::isUnsigned() const {
704 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
705 return specifiers.isUnsigned;
706 }
707
708 /**
709 * Check if the current type is marked inline
710 *
711 * @return Is inline or not
712 */
713 5967 bool QualType::isInline() const {
714
2/4
✓ Branch 1 taken 5967 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5967 times.
5967 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
715 5967 return specifiers.isInline;
716 }
717
718 /**
719 * Check if the current type is marked public
720 *
721 * @return Is public or not
722 */
723 26064 bool QualType::isPublic() const {
724
5/8
✓ Branch 1 taken 26064 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25230 times.
✓ Branch 4 taken 834 times.
✓ Branch 6 taken 25230 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 25230 times.
26064 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
725 26064 return specifiers.isPublic;
726 }
727
728 /**
729 * Check if the current type is marked heap
730 *
731 * @return Is heap or not
732 */
733 9883 bool QualType::isHeap() const { return specifiers.isHeap; }
734
735 /**
736 * Check if the current type is marked as composition
737 *
738 * @return Is composition or not
739 */
740 41 bool QualType::isComposition() const { return specifiers.isComposition; }
741
742 /**
743 * Make the current type const
744 *
745 * @param isConst Is const or not
746 */
747 6544 void QualType::makeConst(bool isConst) { specifiers.isConst = isConst; }
748
749 /**
750 * Make the current type unsigned
751 *
752 * @param isUnsigned Is unsigned or not
753 */
754 11 void QualType::makeUnsigned(bool isUnsigned) {
755
2/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 assert(isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}));
756 11 specifiers.isSigned = !isUnsigned;
757 11 specifiers.isUnsigned = isUnsigned;
758 11 }
759
760 /**
761 * Make the current type public
762 *
763 * @param isPublic Is public or not
764 */
765 264 void QualType::makePublic(bool isPublic) {
766
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 264 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 264 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 264 times.
264 assert(type->isPrimitive() /* Global variables */ || isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_ENUM, TY_STRUCT, TY_INTERFACE}));
767 264 specifiers.isPublic = isPublic;
768 264 }
769
770 /**
771 * Make the current type heap
772 *
773 * @param isHeap Is heap or not
774 */
775 43 void QualType::makeHeap(bool isHeap) { specifiers.isHeap = isHeap; }
776
777 /**
778 * Check if two types are equal
779 *
780 * @param lhs Left-hand side type
781 * @param rhs Right-hand side type
782 * @return Equal or not
783 */
784 28547 bool operator==(const QualType &lhs, const QualType &rhs) { return lhs.type == rhs.type; }
785
786 /**
787 * Check if two types are not equal
788 *
789 * @param lhs Left-hand side type
790 * @param rhs Right-hand side type
791 * @return Not equal or not
792 */
793 2042 bool operator!=(const QualType &lhs, const QualType &rhs) { return !(lhs == rhs); }
794
795 /**
796 * Remove pointers / arrays / references if both types have them as far as possible.
797 * Furthermore, remove reference wrappers if possible.
798 *
799 * @param typeA Candidate type
800 * @param typeB Requested type
801 */
802 62031 void QualType::unwrapBoth(QualType &typeA, QualType &typeB) { Type::unwrapBoth(typeA.type, typeB.type); }
803
804 } // namespace spice::compiler
805