GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.8% 225 / 1 / 231
Functions: 97.8% 45 / 0 / 46
Branches: 59.8% 268 / 6 / 454

src/symboltablebuilder/Type.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "Type.h"
4
5 #include <utility>
6
7 #include <SourceFile.h>
8 #include <ast/Attributes.h>
9 #include <driver/Driver.h>
10 #include <exception/CompilerError.h>
11 #include <exception/SemanticError.h>
12 #include <global/GlobalResourceManager.h>
13 #include <global/TypeRegistry.h>
14 #include <irgenerator/NameMangling.h>
15 #include <model/Struct.h>
16 #include <symboltablebuilder/Scope.h>
17 #include <symboltablebuilder/SymbolTableEntry.h>
18
19 #include <llvm/IR/Module.h>
20 #include <llvm/IR/Type.h>
21
22 namespace spice::compiler {
23
24
3/10
✓ Branch 5 → 6 taken 4194879 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 4194879 times.
✓ Branch 7 → 9 taken 4194879 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 19 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
12584637 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
25
26
4/12
✓ Branch 4 → 5 taken 5766 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 5766 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 5766 times.
✓ Branch 8 → 10 taken 5766 times.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 24 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
17298 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
27
28 6360 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
29 const QualTypeList &templateTypes)
30
5/14
✓ Branch 4 → 5 taken 6360 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 6360 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 6360 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 6360 times.
✓ Branch 9 → 11 taken 6360 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 29 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 29 not taken.
19080 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
31
32 19160650 Type::Type(TypeChain typeChain) : typeChain(std::move(typeChain)) {}
33
34 /**
35 * Get the super type of the current type
36 *
37 * @return Super type
38 */
39 42978286 SuperType Type::getSuperType() const {
40
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 42978286 times.
42978286 assert(!typeChain.empty());
41 42978286 return typeChain.back().superType;
42 }
43
44 /**
45 * Get the sub type of the current type
46 *
47 * @return Sub type
48 */
49 1074107 const std::string &Type::getSubType() const {
50
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1074107 times.
1074107 assert(!typeChain.empty());
51
2/4
✓ Branch 5 → 6 taken 1074107 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1074107 times.
1074107 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
52 1074107 return typeChain.back().subType;
53 }
54
55 /**
56 * Get the array size of the current type
57 *
58 * @return Array size
59 */
60 2193 unsigned int Type::getArraySize() const {
61
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2193 times.
2193 assert(isArray());
62 2193 return typeChain.back().data.arraySize;
63 }
64
65 /**
66 * Get the body scope of the current type
67 *
68 * @return Body scope
69 */
70 3811832 Scope *Type::getBodyScope() const {
71
2/4
✓ Branch 2 → 3 taken 3811832 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3811832 times.
3811832 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
72 3811832 return typeChain.back().data.bodyScope;
73 }
74
75 /**
76 * Get the return type of function type
77 *
78 * @return Function return type
79 */
80 53 const QualType &Type::getFunctionReturnType() const {
81
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 53 times.
53 assert(is(TY_FUNCTION));
82
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 53 times.
53 assert(!typeChain.front().paramTypes.empty());
83 53 return typeChain.front().paramTypes.front();
84 }
85
86 /**
87 * Get the param types of a function or procedure type
88 *
89 * @return Function param types
90 */
91 358 QualTypeList Type::getFunctionParamTypes() const {
92
2/4
✓ Branch 2 → 3 taken 358 times.
✗ Branch 2 → 23 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 358 times.
358 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
93
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 358 times.
358 if (typeChain.front().paramTypes.empty())
94 return {};
95
1/2
✓ Branch 18 → 19 taken 358 times.
✗ Branch 18 → 24 not taken.
1432 return {typeChain.front().paramTypes.begin() + 1, typeChain.front().paramTypes.end()};
96 }
97
98 /**
99 * Get the param and return types of a function or procedure base type
100 *
101 * @return Function param and return types (first is return type, rest are param types)
102 */
103 4377 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
104
2/4
✓ Branch 3 → 4 taken 4377 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 4377 times.
4377 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
105 4377 return typeChain.front().paramTypes;
106 }
107
108 /**
109 * Check if a function or procedure type has captures
110 *
111 * @return Has captures
112 */
113 313 bool Type::hasLambdaCaptures() const {
114
2/4
✓ Branch 3 → 4 taken 313 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 313 times.
313 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
115 313 return typeChain.front().data.hasCaptures;
116 }
117
118 /**
119 * Retrieve template types of the current type
120 *
121 * @return Vector of template types
122 */
123 1830161 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
124
125 /**
126 * Get the type chain depth of the current type
127 *
128 * @return Type chain depth
129 */
130 size_t Type::getTypeChainDepth() const { return typeChain.size(); }
131
132 /**
133 * Check if the current type is of a certain super type
134 *
135 * @return Applicable or not
136 */
137 32902373 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
138
139 /**
140 * Check if the current type is one of a list of super types
141 *
142 * @return Applicable or not
143 */
144 9417918 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
145 26063421 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
146 }
147
148 /**
149 * Check if the base type of the current type chain is of a certain super type
150 *
151 * @param superType Super type to check for
152 * @return Applicable or not
153 */
154 17868180 bool Type::isBase(SuperType superType) const {
155
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 17868180 times.
17868180 assert(!typeChain.empty());
156 17868180 return typeChain.front().superType == superType;
157 }
158
159 /**
160 * Check if the current type is a primitive type
161 *
162 * @return Primitive type or not
163 */
164
1/2
✓ Branch 2 → 3 taken 377620 times.
✗ Branch 2 → 6 not taken.
377620 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
165
166 /**
167 * Check if the type is an extended primitive type
168 * The definition of extended primitive types contains all primitive types plus the following:
169 * - structs
170 * - interfaces
171 * - functions/procedures
172 *
173 * @return Extended primitive or not
174 */
175
6/8
✓ Branch 2 → 3 taken 281607 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 122859 times.
✓ Branch 3 → 6 taken 158748 times.
✓ Branch 4 → 5 taken 122859 times.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 93131 times.
✓ Branch 5 → 7 taken 29728 times.
281607 bool Type::isExtendedPrimitive() const { return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}); }
176
177 /**
178 * Check if the current type is a pointer type
179 *
180 * @return Pointer type or not
181 */
182 1549470 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
183
184 /**
185 * Check if the current type is a reference type
186 *
187 * @return Reference type or not
188 */
189 3524498 bool Type::isRef() const { return getSuperType() == TY_REF; }
190
191 /**
192 * Check if the current type is an array type
193 *
194 * @return Array type or not
195 */
196 850822 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
197
198 /**
199 * Checks if the base type is generic itself or has generic parts in its template types
200 *
201 * @return Contains generic parts or not
202 */
203 1589395 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
204
1/2
✓ Branch 2 → 3 taken 1589395 times.
✗ Branch 2 → 34 not taken.
1589395 const Type *baseType = getBase();
205
206 // Check if the type itself is generic
207
2/2
✓ Branch 4 → 5 taken 265052 times.
✓ Branch 4 → 6 taken 1324343 times.
1589395 if (baseType->is(TY_GENERIC))
208 265052 return true;
209
210 // Check if the type has generic template types
211
1/2
✓ Branch 7 → 8 taken 1324343 times.
✗ Branch 7 → 34 not taken.
1324343 const auto templateTypes = baseType->getTemplateTypes();
212
3/4
✓ Branch 8 → 9 taken 1324343 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 109018 times.
✓ Branch 9 → 11 taken 1215325 times.
1717552 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
213 109018 return true;
214
215 // Check param and return types or functions/procedures
216
3/4
✓ Branch 11 → 12 taken 1215325 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 4221 times.
✓ Branch 12 → 24 taken 1211104 times.
1215325 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
217
2/4
✓ Branch 13 → 14 taken 4221 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 4221 times.
✗ Branch 14 → 31 not taken.
4221 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
218
3/4
✓ Branch 15 → 16 taken 4221 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 201 times.
✓ Branch 16 → 18 taken 4020 times.
11788 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
219 201 return true;
220
2/2
✓ Branch 20 → 21 taken 4020 times.
✓ Branch 20 → 23 taken 201 times.
4221 }
221
222 1215124 return false; // Does not have generic parts
223 1324343 }
224
225 /**
226 * Check if the current type is of the same container type like the other type.
227 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
228 *
229 * @param other Other symbol type
230 * @return Same container type or not
231 */
232 376290 bool Type::isSameContainerTypeAs(const Type *other) const {
233
4/4
✓ Branch 3 → 4 taken 11264 times.
✓ Branch 3 → 7 taken 365026 times.
✓ Branch 5 → 6 taken 10260 times.
✓ Branch 5 → 7 taken 1004 times.
376290 const bool bothPtr = isPtr() && other->isPtr();
234
4/4
✓ Branch 9 → 10 taken 24309 times.
✓ Branch 9 → 13 taken 351981 times.
✓ Branch 11 → 12 taken 18327 times.
✓ Branch 11 → 13 taken 5982 times.
376290 const bool bothRef = isRef() && other->isRef();
235
3/4
✓ Branch 15 → 16 taken 388 times.
✓ Branch 15 → 19 taken 375902 times.
✓ Branch 17 → 18 taken 388 times.
✗ Branch 17 → 19 not taken.
376290 const bool bothArray = isArray() && other->isArray();
236
6/6
✓ Branch 20 → 21 taken 366030 times.
✓ Branch 20 → 23 taken 10260 times.
✓ Branch 21 → 22 taken 347703 times.
✓ Branch 21 → 23 taken 18327 times.
✓ Branch 22 → 23 taken 388 times.
✓ Branch 22 → 24 taken 347315 times.
376290 return bothPtr || bothRef || bothArray;
237 }
238
239 /**
240 * Check for the matching compatibility of two types.
241 * Useful for struct and function matching as well as assignment type validation and function arg matching.
242 *
243 * @param otherType Type to compare against
244 * @param ignoreArraySize Ignore array sizes
245 * @return Matching or not
246 */
247 439015 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
248 // If the size does not match, it is not equal
249
2/2
✓ Branch 4 → 5 taken 46961 times.
✓ Branch 4 → 6 taken 392054 times.
439015 if (typeChain.size() != otherType->typeChain.size())
250 46961 return false;
251
252 // Compare the elements
253
2/2
✓ Branch 18 → 7 taken 436386 times.
✓ Branch 18 → 19 taken 265888 times.
702274 for (size_t i = 0; i < typeChain.size(); i++) {
254 436386 const TypeChainElement &lhsElement = typeChain.at(i);
255 436386 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
256
257 // Ignore differences in array size
258
5/6
✓ Branch 9 → 10 taken 265486 times.
✓ Branch 9 → 13 taken 170900 times.
✓ Branch 10 → 11 taken 5 times.
✓ Branch 10 → 13 taken 265481 times.
✓ Branch 11 → 12 taken 5 times.
✗ Branch 11 → 13 not taken.
436386 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
259 5 continue;
260
261 // Not both types are arrays -> compare them as usual
262
2/2
✓ Branch 14 → 15 taken 126166 times.
✓ Branch 14 → 16 taken 310215 times.
436381 if (lhsElement != rhsElement)
263 126166 return false;
264 }
265
266 265888 return true;
267 }
268
269 /**
270 * Get the name of the symbol type as a string
271 *
272 * @param name Get name of type
273 * @param withSize Include the array size for sized types
274 * @param ignorePublic Ignore any potential public qualifier
275 * @param withAliases Print aliases as is and not decompose them
276 * @return Symbol type name
277 */
278 2776557 void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
279 // Loop through all chain elements
280
2/2
✓ Branch 18 → 4 taken 3635809 times.
✓ Branch 18 → 19 taken 2776557 times.
9188923 for (const TypeChainElement &chainElement : typeChain)
281
2/4
✓ Branch 6 → 7 taken 3635809 times.
✗ Branch 6 → 22 not taken.
✓ Branch 7 → 8 taken 3635809 times.
✗ Branch 7 → 20 not taken.
3635809 name << chainElement.getName(withSize, ignorePublic, withAliases);
282 2776557 }
283
284 /**
285 * Get the name of the symbol type as a string
286 *
287 * @param withSize Include the array size for sized types
288 * @param ignorePublic Ignore any potential public qualifier
289 * @param withAliases Print aliases as is and not decompose them
290 * @return Symbol type name
291 */
292 51548 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
293
1/2
✓ Branch 2 → 3 taken 51548 times.
✗ Branch 2 → 11 not taken.
51548 std::stringstream name;
294
1/2
✓ Branch 3 → 4 taken 51548 times.
✗ Branch 3 → 9 not taken.
51548 getName(name, withSize, ignorePublic, withAliases);
295
1/2
✓ Branch 4 → 5 taken 51548 times.
✗ Branch 4 → 9 not taken.
103096 return name.str();
296 51548 }
297
298 /**
299 * Get the pointer type of the current type as a new type
300 *
301 * @param node AST node for error messages
302 * @return Pointer type of the current type
303 */
304 107992 const Type *Type::toPtr(const ASTNode *node) const {
305
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 12 taken 107990 times.
107992 if (is(TY_DYN))
306
2/4
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 32 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 29 not taken.
6 throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead");
307
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 107990 times.
107990 if (isRef())
308 throw SemanticError(node, REF_POINTERS_ARE_NOT_ALLOWED, "Pointers to references are not allowed. Use pointer instead");
309
310 // Create new type chain
311
1/2
✓ Branch 22 → 23 taken 107990 times.
✗ Branch 22 → 50 not taken.
107990 TypeChain newTypeChain = typeChain;
312
1/2
✓ Branch 23 → 24 taken 107990 times.
✗ Branch 23 → 47 not taken.
107990 newTypeChain.emplace_back(TY_PTR);
313
314 // Register new type or return if already registered
315
1/2
✓ Branch 24 → 25 taken 107990 times.
✗ Branch 24 → 48 not taken.
215980 return TypeRegistry::getOrInsert(newTypeChain);
316 107990 }
317
318 /**
319 * Get the reference type of the current type as a new type
320 *
321 * @param node AST node for error messages
322 * @return Reference type of the current type
323 */
324 49873 const Type *Type::toRef(const ASTNode *node) const {
325
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 49873 times.
49873 if (is(TY_DYN))
326 throw SemanticError(node, DYN_REFERENCES_NOT_ALLOWED, "Just use the dyn type without '&' instead");
327
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 49873 times.
49873 if (isRef())
328 throw SemanticError(node, MULTI_REF_NOT_ALLOWED, "References to references are not allowed");
329
330 // Create new type chain
331
1/2
✓ Branch 22 → 23 taken 49873 times.
✗ Branch 22 → 50 not taken.
49873 TypeChain newTypeChain = typeChain;
332
1/2
✓ Branch 23 → 24 taken 49873 times.
✗ Branch 23 → 47 not taken.
49873 newTypeChain.emplace_back(TY_REF);
333
334 // Register new type or return if already registered
335
1/2
✓ Branch 24 → 25 taken 49873 times.
✗ Branch 24 → 48 not taken.
99746 return TypeRegistry::getOrInsert(newTypeChain);
336 49873 }
337
338 /**
339 * Get the array type of the current type as a new type
340 *
341 * @param node AST node for error messages
342 * @param size Size of the array
343 * @param skipDynCheck Skip check if array base type is dyn
344 * @return Array type of the current type
345 */
346 601 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
347
6/6
✓ Branch 2 → 3 taken 280 times.
✓ Branch 2 → 6 taken 321 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 279 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 16 taken 600 times.
601 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
348
2/4
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 26 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 23 not taken.
3 throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead");
349
350 // Create new type chain
351
1/2
✓ Branch 16 → 17 taken 600 times.
✗ Branch 16 → 36 not taken.
600 TypeChain newTypeChain = typeChain;
352
1/2
✓ Branch 17 → 18 taken 600 times.
✗ Branch 17 → 32 not taken.
600 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
353
354 // Register new type or return if already registered
355
1/2
✓ Branch 18 → 19 taken 600 times.
✗ Branch 18 → 34 not taken.
1200 return TypeRegistry::getOrInsert(newTypeChain);
356 600 }
357
358 /**
359 * Retrieve the base type of an array or a pointer
360 *
361 * @return Base type
362 */
363 556700 const Type *Type::getContained() const {
364
2/2
✓ Branch 3 → 4 taken 2748 times.
✓ Branch 3 → 6 taken 553952 times.
556700 if (is(TY_STRING))
365
1/2
✓ Branch 4 → 5 taken 2748 times.
✗ Branch 4 → 18 not taken.
2748 return TypeRegistry::getOrInsert(TY_CHAR);
366
367 // Create new type chain
368
1/2
✓ Branch 6 → 7 taken 553952 times.
✗ Branch 6 → 18 not taken.
553952 TypeChain newTypeChain = typeChain;
369
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 553952 times.
553952 assert(newTypeChain.size() > 1);
370 553952 newTypeChain.pop_back();
371
372 // Register new type or return if already registered
373
1/2
✓ Branch 11 → 12 taken 553952 times.
✗ Branch 11 → 16 not taken.
553952 return TypeRegistry::getOrInsert(newTypeChain);
374 553952 }
375
376 /**
377 * Replace the base type with another one
378 *
379 * @param newBaseType New base type
380 * @return The new type
381 */
382 79196 const Type *Type::replaceBase(const Type *newBaseType) const {
383
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 79196 times.
79196 assert(!typeChain.empty());
384
385 // Create new type
386
1/2
✓ Branch 5 → 6 taken 79196 times.
✗ Branch 5 → 27 not taken.
79196 TypeChain newTypeChain = newBaseType->typeChain;
387
4/4
✓ Branch 7 → 8 taken 4203 times.
✓ Branch 7 → 11 taken 74993 times.
✓ Branch 9 → 10 taken 65 times.
✓ Branch 9 → 11 taken 4138 times.
79196 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
388
2/2
✓ Branch 19 → 13 taken 11018 times.
✓ Branch 19 → 20 taken 79196 times.
90214 for (size_t i = 1; i < typeChain.size(); i++)
389
3/4
✓ Branch 13 → 14 taken 65 times.
✓ Branch 13 → 15 taken 10953 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 65 times.
11018 if (!doubleRef || i > 1)
390
2/4
✓ Branch 15 → 16 taken 10953 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 10953 times.
✗ Branch 16 → 25 not taken.
10953 newTypeChain.push_back(typeChain.at(i));
391
392 // Register new type or return if already registered
393
1/2
✓ Branch 20 → 21 taken 79196 times.
✗ Branch 20 → 25 not taken.
158392 return TypeRegistry::getOrInsert(newTypeChain);
394 79196 }
395
396 /**
397 * Remove reference wrapper from the current type
398 *
399 * @return Type without reference wrapper
400 */
401
1/2
✓ Branch 3 → 4 taken 138548 times.
✗ Branch 3 → 6 not taken.
138548 const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; }
402
403 /**
404 * Retrieve the base type of the current type
405 *
406 * @return Base type
407 */
408 8586607 const Type *Type::getBase() const {
409
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 8586607 times.
8586607 assert(!typeChain.empty());
410
411 // Create new type chain
412
3/6
✓ Branch 9 → 10 taken 8586607 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 8586607 times.
✓ Branch 12 → 14 taken 8586607 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
25759821 const TypeChain newTypeChain = {typeChain.front()};
413
414 // Register new type or return if already registered
415
1/2
✓ Branch 14 → 15 taken 8586607 times.
✗ Branch 14 → 32 not taken.
17173214 return TypeRegistry::getOrInsert(newTypeChain);
416
1/6
✓ Branch 6 → 7 taken 8586607 times.
✗ Branch 6 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 30 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
17173214 }
417
418 /**
419 * Retrieve the same type, but with lambda captures
420 *
421 * @return Type with lambda captures
422 */
423 98 const Type *Type::getWithLambdaCaptures(bool enabled) const {
424
3/6
✓ Branch 2 → 3 taken 98 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 98 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 98 times.
98 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
425
426 // Create new type chain
427
1/2
✓ Branch 6 → 7 taken 98 times.
✗ Branch 6 → 16 not taken.
98 TypeChain newTypeChain = typeChain;
428 98 newTypeChain.front().data.hasCaptures = enabled;
429
430 // Register new type or return if already registered
431
1/2
✓ Branch 8 → 9 taken 98 times.
✗ Branch 8 → 14 not taken.
196 return TypeRegistry::getOrInsert(newTypeChain);
432 98 }
433
434 /**
435 * Retrieve the same type, but with the body scope removed
436 *
437 * @return Type with body scope removed
438 */
439 120406 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
440
3/6
✓ Branch 2 → 3 taken 120406 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 120406 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 120406 times.
120406 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
441
442 // Create new type chain
443
1/2
✓ Branch 6 → 7 taken 120406 times.
✗ Branch 6 → 16 not taken.
120406 TypeChain newTypeChain = typeChain;
444 120406 newTypeChain.front().data.bodyScope = bodyScope;
445
446 // Register new type or return if already registered
447
1/2
✓ Branch 8 → 9 taken 120406 times.
✗ Branch 8 → 14 not taken.
240812 return TypeRegistry::getOrInsert(newTypeChain);
448 120406 }
449
450 /**
451 * Retrieve the same type, but with the given template types
452 *
453 * @return Type with new template types
454 */
455 17693 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
456
2/4
✓ Branch 2 → 3 taken 17693 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 17693 times.
17693 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
457 17693 return getWithBaseTemplateTypes(templateTypes);
458 }
459
460 /**
461 * Retrieve the same type, but with the given base template types
462 *
463 * @return Type with new base template types
464 */
465 42919 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
466
3/6
✓ Branch 2 → 3 taken 42919 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 42919 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 42919 times.
42919 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
467
468 // Create new type chain
469
1/2
✓ Branch 6 → 7 taken 42919 times.
✗ Branch 6 → 17 not taken.
42919 TypeChain newTypeChain = typeChain;
470
1/2
✓ Branch 8 → 9 taken 42919 times.
✗ Branch 8 → 15 not taken.
42919 newTypeChain.front().templateTypes = templateTypes;
471
472 // Register new type or return if already registered
473
1/2
✓ Branch 9 → 10 taken 42919 times.
✗ Branch 9 → 15 not taken.
85838 return TypeRegistry::getOrInsert(newTypeChain);
474 42919 }
475
476 /**
477 * Retrieve the same type, but with the param and return types removed
478 *
479 * @return Type with param and return types removed
480 */
481 38684 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
482
3/6
✓ Branch 2 → 3 taken 38684 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 38684 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 38684 times.
38684 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
483
484 // Create new type chain
485
1/2
✓ Branch 6 → 7 taken 38684 times.
✗ Branch 6 → 17 not taken.
38684 TypeChain newTypeChain = typeChain;
486
1/2
✓ Branch 8 → 9 taken 38684 times.
✗ Branch 8 → 15 not taken.
38684 newTypeChain.front().paramTypes = paramAndReturnTypes;
487
488 // Register new type or return if already registered
489
1/2
✓ Branch 9 → 10 taken 38684 times.
✗ Branch 9 → 15 not taken.
77368 return TypeRegistry::getOrInsert(newTypeChain);
490 38684 }
491
492 /**
493 * Return the LLVM type for this symbol type
494 *
495 * @param sourceFile Referenced source file
496 * @return Corresponding LLVM type
497 */
498 34203 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
499
2/4
✓ Branch 3 → 4 taken 34203 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 34203 times.
✗ Branch 5 → 7 not taken.
34203 assert(!typeChain.empty() && !is(TY_INVALID));
500
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 34201 times.
34203 llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context;
501
502
10/12
✓ Branch 11 → 12 taken 34203 times.
✗ Branch 11 → 166 not taken.
✓ Branch 12 → 13 taken 16873 times.
✓ Branch 12 → 17 taken 17330 times.
✓ Branch 14 → 15 taken 220 times.
✓ Branch 14 → 18 taken 16653 times.
✓ Branch 15 → 16 taken 220 times.
✗ Branch 15 → 166 not taken.
✓ Branch 16 → 17 taken 59 times.
✓ Branch 16 → 18 taken 161 times.
✓ Branch 19 → 20 taken 17389 times.
✓ Branch 19 → 22 taken 16814 times.
34203 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
503 17389 return llvm::PointerType::get(context, 0);
504
505
2/2
✓ Branch 23 → 24 taken 161 times.
✓ Branch 23 → 32 taken 16653 times.
16814 if (isArray()) {
506
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 161 times.
161 assert(getArraySize() > 0);
507 161 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
508 161 return llvm::ArrayType::get(containedType, getArraySize());
509 }
510
511
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 16653 times.
16653 assert(!hasAnyGenericParts());
512
513
2/2
✓ Branch 36 → 37 taken 188 times.
✓ Branch 36 → 39 taken 16465 times.
16653 if (is(TY_DOUBLE))
514 188 return llvm::Type::getDoubleTy(context);
515
516
3/4
✓ Branch 39 → 40 taken 16465 times.
✗ Branch 39 → 167 not taken.
✓ Branch 40 → 41 taken 1557 times.
✓ Branch 40 → 43 taken 14908 times.
16465 if (isOneOf({TY_INT, TY_ENUM}))
517 1557 return llvm::Type::getInt32Ty(context);
518
519
2/2
✓ Branch 44 → 45 taken 137 times.
✓ Branch 44 → 47 taken 14771 times.
14908 if (is(TY_SHORT))
520 137 return llvm::Type::getInt16Ty(context);
521
522
2/2
✓ Branch 48 → 49 taken 1109 times.
✓ Branch 48 → 51 taken 13662 times.
14771 if (is(TY_LONG))
523 1109 return llvm::Type::getInt64Ty(context);
524
525
3/4
✓ Branch 51 → 52 taken 13662 times.
✗ Branch 51 → 168 not taken.
✓ Branch 52 → 53 taken 925 times.
✓ Branch 52 → 55 taken 12737 times.
13662 if (isOneOf({TY_CHAR, TY_BYTE}))
526 925 return llvm::Type::getInt8Ty(context);
527
528
2/2
✓ Branch 56 → 57 taken 1208 times.
✓ Branch 56 → 59 taken 11529 times.
12737 if (is(TY_BOOL))
529 1208 return llvm::Type::getInt1Ty(context);
530
531
3/4
✓ Branch 59 → 60 taken 11529 times.
✗ Branch 59 → 169 not taken.
✓ Branch 60 → 61 taken 11250 times.
✓ Branch 60 → 150 taken 279 times.
11529 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
532
1/2
✓ Branch 61 → 62 taken 11250 times.
✗ Branch 61 → 198 not taken.
11250 const Scope *structBodyScope = getBodyScope();
533
2/4
✓ Branch 63 → 64 taken 11250 times.
✗ Branch 63 → 198 not taken.
✓ Branch 64 → 65 taken 11250 times.
✗ Branch 64 → 198 not taken.
11250 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
534
1/2
✓ Branch 65 → 66 taken 11250 times.
✗ Branch 65 → 196 not taken.
11250 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
535
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 11250 times.
11250 assert(structSymbol != nullptr);
536
537 // Collect concrete field types
538 11250 std::string mangledName;
539 11250 std::vector<llvm::Type *> fieldTypes;
540 11250 bool isPacked = false;
541
2/2
✓ Branch 72 → 73 taken 9997 times.
✓ Branch 72 → 132 taken 1253 times.
11250 if (is(TY_STRUCT)) { // Struct
542
2/4
✓ Branch 73 → 74 taken 9997 times.
✗ Branch 73 → 192 not taken.
✓ Branch 74 → 75 taken 9997 times.
✗ Branch 74 → 192 not taken.
9997 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
543
1/2
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 9997 times.
9997 assert(spiceStruct != nullptr);
544
1/2
✓ Branch 77 → 78 taken 9997 times.
✗ Branch 77 → 170 not taken.
9997 mangledName = NameMangling::mangleStruct(*spiceStruct);
545
546
1/2
✓ Branch 80 → 81 taken 9997 times.
✗ Branch 80 → 192 not taken.
9997 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
547
1/2
✓ Branch 81 → 82 taken 9997 times.
✗ Branch 81 → 192 not taken.
9997 fieldTypes.reserve(totalFieldCount);
548
549 // If the struct has no interface types, but a vtable was requested, add another ptr field type
550
2/4
✓ Branch 82 → 83 taken 9997 times.
✗ Branch 82 → 192 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 9997 times.
9997 assert(structSymbol->declNode->isStructDef());
551
1/2
✓ Branch 85 → 86 taken 9997 times.
✗ Branch 85 → 87 not taken.
9997 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
552
4/4
✓ Branch 92 → 93 taken 7381 times.
✓ Branch 92 → 97 taken 2616 times.
✓ Branch 93 → 94 taken 95 times.
✓ Branch 93 → 97 taken 7286 times.
9997 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
553
2/4
✓ Branch 94 → 95 taken 95 times.
✗ Branch 94 → 171 not taken.
✓ Branch 95 → 96 taken 95 times.
✗ Branch 95 → 171 not taken.
95 fieldTypes.push_back(llvm::PointerType::get(context, 0));
554
555 // Collect all field types
556
2/2
✓ Branch 110 → 98 taken 25512 times.
✓ Branch 110 → 111 taken 9997 times.
35509 for (size_t i = 0; i < totalFieldCount; i++) {
557
1/2
✗ Branch 98 → 99 not taken.
✓ Branch 98 → 100 taken 25512 times.
25512 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
558
1/2
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 105 taken 25512 times.
25512 assert(fieldSymbol != nullptr);
559
3/6
✓ Branch 105 → 106 taken 25512 times.
✗ Branch 105 → 172 not taken.
✓ Branch 107 → 108 taken 25512 times.
✗ Branch 107 → 172 not taken.
✓ Branch 108 → 109 taken 25512 times.
✗ Branch 108 → 172 not taken.
25512 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
560 }
561
562 // Check if the struct is declared as packed
563
12/18
✓ Branch 111 → 112 taken 96 times.
✓ Branch 111 → 118 taken 9901 times.
✓ Branch 114 → 115 taken 96 times.
✗ Branch 114 → 173 not taken.
✓ Branch 115 → 116 taken 96 times.
✗ Branch 115 → 173 not taken.
✓ Branch 116 → 117 taken 1 time.
✓ Branch 116 → 118 taken 95 times.
✓ Branch 119 → 120 taken 96 times.
✓ Branch 119 → 121 taken 9901 times.
✓ Branch 121 → 122 taken 96 times.
✓ Branch 121 → 124 taken 9901 times.
✓ Branch 124 → 125 taken 1 time.
✓ Branch 124 → 142 taken 9996 times.
✗ Branch 173 → 174 not taken.
✗ Branch 173 → 175 not taken.
✗ Branch 177 → 178 not taken.
✗ Branch 177 → 180 not taken.
10189 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
564
2/4
✓ Branch 127 → 128 taken 1 time.
✗ Branch 127 → 184 not taken.
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 182 not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
565 } else { // Interface
566
2/4
✓ Branch 132 → 133 taken 1253 times.
✗ Branch 132 → 192 not taken.
✓ Branch 133 → 134 taken 1253 times.
✗ Branch 133 → 192 not taken.
1253 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
567
1/2
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 1253 times.
1253 assert(spiceInterface != nullptr);
568
1/2
✓ Branch 136 → 137 taken 1253 times.
✗ Branch 136 → 188 not taken.
1253 mangledName = NameMangling::mangleInterface(*spiceInterface);
569
570 // vtable pointer
571
2/4
✓ Branch 139 → 140 taken 1253 times.
✗ Branch 139 → 189 not taken.
✓ Branch 140 → 141 taken 1253 times.
✗ Branch 140 → 189 not taken.
1253 fieldTypes.push_back(llvm::PointerType::get(context, 0));
572 }
573
574
1/2
✓ Branch 144 → 145 taken 11250 times.
✗ Branch 144 → 190 not taken.
11250 return llvm::StructType::create(context, fieldTypes, mangledName, isPacked);
575 11250 }
576
577
2/4
✓ Branch 150 → 151 taken 279 times.
✗ Branch 150 → 199 not taken.
✓ Branch 151 → 152 taken 279 times.
✗ Branch 151 → 158 not taken.
279 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
578 // Lambda/function values are represented as a fat pointer with three slots:
579 // { fctPtr, capturePtr, captureSize }. The capture size (in bytes) travels with
580 // the value so that the std Lambda type can take ownership of the captures on the
581 // heap regardless of where the lambda came from. It is 0 if there is no owned
582 // capture struct (no captures, or a single capture stored inline in capturePtr).
583 279 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
584 279 llvm::IntegerType *int64Ty = llvm::Type::getInt64Ty(context);
585
1/2
✓ Branch 155 → 156 taken 279 times.
✗ Branch 155 → 200 not taken.
279 return llvm::StructType::get(context, {ptrTy, ptrTy, int64Ty});
586 }
587
588 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
589 }
590
591 /**
592 * Remove pointers / arrays / references if both types have them as far as possible.
593 *
594 * @param typeA Candidate type
595 * @param typeB Requested type
596 */
597 341214 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
598 // Unwrap both types as far as possible
599
2/2
✓ Branch 7 → 3 taken 26248 times.
✓ Branch 7 → 8 taken 341214 times.
367462 while (typeA->isSameContainerTypeAs(typeB)) {
600 26248 typeB = typeB->getContained();
601 26248 typeA = typeA->getContained();
602 }
603 341214 }
604
605 /**
606 * Remove pointers / arrays / references if both types have them as far as possible.
607 * Furthermore, remove reference wrappers if possible.
608 *
609 * @param typeA Candidate type
610 * @param typeB Requested type
611 */
612 334405 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
613 // Remove reference wrapper of front type if required
614
6/6
✓ Branch 3 → 4 taken 147281 times.
✓ Branch 3 → 7 taken 187124 times.
✓ Branch 5 → 6 taken 129027 times.
✓ Branch 5 → 7 taken 18254 times.
✓ Branch 8 → 9 taken 129027 times.
✓ Branch 8 → 11 taken 205378 times.
334405 if (typeA->isRef() && !typeB->isRef())
615 129027 typeA = typeA->removeReferenceWrapper();
616
617 // Remove reference wrapper of requested type if required
618
8/8
✓ Branch 12 → 13 taken 316151 times.
✓ Branch 12 → 18 taken 18254 times.
✓ Branch 14 → 15 taken 11759 times.
✓ Branch 14 → 18 taken 304392 times.
✓ Branch 16 → 17 taken 9521 times.
✓ Branch 16 → 18 taken 2238 times.
✓ Branch 19 → 20 taken 9521 times.
✓ Branch 19 → 22 taken 324884 times.
334405 if (!typeA->isRef() && typeB->isRef() && !typeA->isBase(TY_GENERIC))
619 9521 typeB = typeB->removeReferenceWrapper();
620
621 // Unwrap both types as far as possible
622 334405 unwrapBoth(typeA, typeB);
623 334405 }
624
625 /**
626 * Check if two types have the same type chain depth
627 *
628 * @param typeA First type
629 * @param typeB Second type
630 * @return Same depth or not
631 */
632 50683 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
633 50683 return typeA->typeChain.size() == typeB->typeChain.size();
634 }
635
636 } // namespace spice::compiler
637