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.6% 267 / 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 9912786 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 9912786 times.
✓ Branch 7 → 9 taken 9912786 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.
29738358 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
25
26
4/12
✓ Branch 4 → 5 taken 12273 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 12273 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 12273 times.
✓ Branch 8 → 10 taken 12273 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.
36819 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
27
28 14143 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 14143 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 14143 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 14143 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 14143 times.
✓ Branch 9 → 11 taken 14143 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.
42429 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
31
32 41964542 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 102493395 SuperType Type::getSuperType() const {
40
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 102493395 times.
102493395 assert(!typeChain.empty());
41 102493395 return typeChain.back().superType;
42 }
43
44 /**
45 * Get the sub type of the current type
46 *
47 * @return Sub type
48 */
49 2353781 const std::string &Type::getSubType() const {
50
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2353781 times.
2353781 assert(!typeChain.empty());
51
2/4
✓ Branch 5 → 6 taken 2353781 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2353781 times.
2353781 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
52 2353781 return typeChain.back().subType;
53 }
54
55 /**
56 * Get the array size of the current type
57 *
58 * @return Array size
59 */
60 11296 unsigned int Type::getArraySize() const {
61
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11296 times.
11296 assert(isArray());
62 11296 return typeChain.back().data.arraySize;
63 }
64
65 /**
66 * Get the body scope of the current type
67 *
68 * @return Body scope
69 */
70 8745692 Scope *Type::getBodyScope() const {
71
2/4
✓ Branch 2 → 3 taken 8745692 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 8745692 times.
8745692 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
72 8745692 return typeChain.back().data.bodyScope;
73 }
74
75 /**
76 * Get the return type of function type
77 *
78 * @return Function return type
79 */
80 156 const QualType &Type::getFunctionReturnType() const {
81
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 156 times.
156 assert(is(TY_FUNCTION));
82
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 156 times.
156 assert(!typeChain.front().paramTypes.empty());
83 156 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 824 QualTypeList Type::getFunctionParamTypes() const {
92
2/4
✓ Branch 2 → 3 taken 824 times.
✗ Branch 2 → 23 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 824 times.
824 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
93
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 824 times.
824 if (typeChain.front().paramTypes.empty())
94 return {};
95
1/2
✓ Branch 18 → 19 taken 824 times.
✗ Branch 18 → 24 not taken.
3296 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 11090 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
104
2/4
✓ Branch 3 → 4 taken 11090 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 11090 times.
11090 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
105 11090 return typeChain.front().paramTypes;
106 }
107
108 /**
109 * Check if a function or procedure type has captures
110 *
111 * @return Has captures
112 */
113 730 bool Type::hasLambdaCaptures() const {
114
2/4
✓ Branch 3 → 4 taken 730 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 730 times.
730 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
115 730 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 4081034 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 78345192 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 21953081 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
145 61406436 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 41320541 bool Type::isBase(SuperType superType) const {
155
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 41320541 times.
41320541 assert(!typeChain.empty());
156 41320541 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 1126089 times.
✗ Branch 2 → 6 not taken.
1126089 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 863960 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 315902 times.
✓ Branch 3 → 6 taken 548058 times.
✓ Branch 4 → 5 taken 315902 times.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 239645 times.
✓ Branch 5 → 7 taken 76257 times.
863960 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 4046562 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 8679295 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 2296926 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 3361141 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
204
1/2
✓ Branch 2 → 3 taken 3361141 times.
✗ Branch 2 → 34 not taken.
3361141 const Type *baseType = getBase();
205
206 // Check if the type itself is generic
207
2/2
✓ Branch 4 → 5 taken 544169 times.
✓ Branch 4 → 6 taken 2816972 times.
3361141 if (baseType->is(TY_GENERIC))
208 544169 return true;
209
210 // Check if the type has generic template types
211
1/2
✓ Branch 7 → 8 taken 2816972 times.
✗ Branch 7 → 34 not taken.
2816972 const auto templateTypes = baseType->getTemplateTypes();
212
3/4
✓ Branch 8 → 9 taken 2816972 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 232223 times.
✓ Branch 9 → 11 taken 2584749 times.
3453132 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
213 232223 return true;
214
215 // Check param and return types or functions/procedures
216
3/4
✓ Branch 11 → 12 taken 2584749 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 10265 times.
✓ Branch 12 → 24 taken 2574484 times.
2584749 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
217
2/4
✓ Branch 13 → 14 taken 10265 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 10265 times.
✗ Branch 14 → 31 not taken.
10265 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
218
3/4
✓ Branch 15 → 16 taken 10265 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 446 times.
✓ Branch 16 → 18 taken 9819 times.
28475 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
219 446 return true;
220
2/2
✓ Branch 20 → 21 taken 9819 times.
✓ Branch 20 → 23 taken 446 times.
10265 }
221
222 2584303 return false; // Does not have generic parts
223 2816972 }
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 878295 bool Type::isSameContainerTypeAs(const Type *other) const {
233
4/4
✓ Branch 3 → 4 taken 30952 times.
✓ Branch 3 → 7 taken 847343 times.
✓ Branch 5 → 6 taken 28493 times.
✓ Branch 5 → 7 taken 2459 times.
878295 const bool bothPtr = isPtr() && other->isPtr();
234
4/4
✓ Branch 9 → 10 taken 56025 times.
✓ Branch 9 → 13 taken 822270 times.
✓ Branch 11 → 12 taken 41699 times.
✓ Branch 11 → 13 taken 14326 times.
878295 const bool bothRef = isRef() && other->isRef();
235
3/4
✓ Branch 15 → 16 taken 856 times.
✓ Branch 15 → 19 taken 877439 times.
✓ Branch 17 → 18 taken 856 times.
✗ Branch 17 → 19 not taken.
878295 const bool bothArray = isArray() && other->isArray();
236
6/6
✓ Branch 20 → 21 taken 849802 times.
✓ Branch 20 → 23 taken 28493 times.
✓ Branch 21 → 22 taken 808103 times.
✓ Branch 21 → 23 taken 41699 times.
✓ Branch 22 → 23 taken 856 times.
✓ Branch 22 → 24 taken 807247 times.
878295 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 1014048 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 118898 times.
✓ Branch 4 → 6 taken 895150 times.
1014048 if (typeChain.size() != otherType->typeChain.size())
250 118898 return false;
251
252 // Compare the elements
253
2/2
✓ Branch 18 → 7 taken 996314 times.
✓ Branch 18 → 19 taken 602202 times.
1598516 for (size_t i = 0; i < typeChain.size(); i++) {
254 996314 const TypeChainElement &lhsElement = typeChain.at(i);
255 996314 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
256
257 // Ignore differences in array size
258
5/6
✓ Branch 9 → 10 taken 603951 times.
✓ Branch 9 → 13 taken 392363 times.
✓ Branch 10 → 11 taken 10 times.
✓ Branch 10 → 13 taken 603941 times.
✓ Branch 11 → 12 taken 10 times.
✗ Branch 11 → 13 not taken.
996314 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
259 10 continue;
260
261 // Not both types are arrays -> compare them as usual
262
2/2
✓ Branch 14 → 15 taken 292948 times.
✓ Branch 14 → 16 taken 703356 times.
996304 if (lhsElement != rhsElement)
263 292948 return false;
264 }
265
266 602202 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 5442882 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 7142938 times.
✓ Branch 18 → 19 taken 5442882 times.
18028702 for (const TypeChainElement &chainElement : typeChain)
281
2/4
✓ Branch 6 → 7 taken 7142938 times.
✗ Branch 6 → 22 not taken.
✓ Branch 7 → 8 taken 7142938 times.
✗ Branch 7 → 20 not taken.
7142938 name << chainElement.getName(withSize, ignorePublic, withAliases);
282 5442882 }
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 117529 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
293
1/2
✓ Branch 2 → 3 taken 117529 times.
✗ Branch 2 → 11 not taken.
117529 std::stringstream name;
294
1/2
✓ Branch 3 → 4 taken 117529 times.
✗ Branch 3 → 9 not taken.
117529 getName(name, withSize, ignorePublic, withAliases);
295
1/2
✓ Branch 4 → 5 taken 117529 times.
✗ Branch 4 → 9 not taken.
235058 return name.str();
296 117529 }
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 244111 const Type *Type::toPtr(const ASTNode *node) const {
305
2/2
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 12 taken 244107 times.
244111 if (is(TY_DYN))
306
2/4
✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 32 not taken.
✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 29 not taken.
12 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 244107 times.
244107 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 244107 times.
✗ Branch 22 → 50 not taken.
244107 TypeChain newTypeChain = typeChain;
312
1/2
✓ Branch 23 → 24 taken 244107 times.
✗ Branch 23 → 47 not taken.
244107 newTypeChain.emplace_back(TY_PTR);
313
314 // Register new type or return if already registered
315
1/2
✓ Branch 24 → 25 taken 244107 times.
✗ Branch 24 → 48 not taken.
488214 return TypeRegistry::getOrInsert(newTypeChain);
316 244107 }
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 114283 const Type *Type::toRef(const ASTNode *node) const {
325
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 114283 times.
114283 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 114283 times.
114283 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 114283 times.
✗ Branch 22 → 50 not taken.
114283 TypeChain newTypeChain = typeChain;
332
1/2
✓ Branch 23 → 24 taken 114283 times.
✗ Branch 23 → 47 not taken.
114283 newTypeChain.emplace_back(TY_REF);
333
334 // Register new type or return if already registered
335
1/2
✓ Branch 24 → 25 taken 114283 times.
✗ Branch 24 → 48 not taken.
228566 return TypeRegistry::getOrInsert(newTypeChain);
336 114283 }
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 1845 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
347
6/6
✓ Branch 2 → 3 taken 1179 times.
✓ Branch 2 → 6 taken 666 times.
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 1177 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 16 taken 1843 times.
1845 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
348
2/4
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 26 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 23 not taken.
6 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 1843 times.
✗ Branch 16 → 36 not taken.
1843 TypeChain newTypeChain = typeChain;
352
1/2
✓ Branch 17 → 18 taken 1843 times.
✗ Branch 17 → 32 not taken.
1843 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 1843 times.
✗ Branch 18 → 34 not taken.
3686 return TypeRegistry::getOrInsert(newTypeChain);
356 1843 }
357
358 /**
359 * Retrieve the base type of an array or a pointer
360 *
361 * @return Base type
362 */
363 1423832 const Type *Type::getContained() const {
364
2/2
✓ Branch 3 → 4 taken 3340 times.
✓ Branch 3 → 6 taken 1420492 times.
1423832 if (is(TY_STRING))
365
1/2
✓ Branch 4 → 5 taken 3340 times.
✗ Branch 4 → 18 not taken.
3340 return TypeRegistry::getOrInsert(TY_CHAR);
366
367 // Create new type chain
368
1/2
✓ Branch 6 → 7 taken 1420492 times.
✗ Branch 6 → 18 not taken.
1420492 TypeChain newTypeChain = typeChain;
369
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1420492 times.
1420492 assert(newTypeChain.size() > 1);
370 1420492 newTypeChain.pop_back();
371
372 // Register new type or return if already registered
373
1/2
✓ Branch 11 → 12 taken 1420492 times.
✗ Branch 11 → 16 not taken.
1420492 return TypeRegistry::getOrInsert(newTypeChain);
374 1420492 }
375
376 /**
377 * Replace the base type with another one
378 *
379 * @param newBaseType New base type
380 * @return The new type
381 */
382 155716 const Type *Type::replaceBase(const Type *newBaseType) const {
383
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 155716 times.
155716 assert(!typeChain.empty());
384
385 // Create new type
386
1/2
✓ Branch 5 → 6 taken 155716 times.
✗ Branch 5 → 27 not taken.
155716 TypeChain newTypeChain = newBaseType->typeChain;
387
4/4
✓ Branch 7 → 8 taken 7302 times.
✓ Branch 7 → 11 taken 148414 times.
✓ Branch 9 → 10 taken 144 times.
✓ Branch 9 → 11 taken 7158 times.
155716 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
388
2/2
✓ Branch 19 → 13 taken 19759 times.
✓ Branch 19 → 20 taken 155716 times.
175475 for (size_t i = 1; i < typeChain.size(); i++)
389
3/4
✓ Branch 13 → 14 taken 144 times.
✓ Branch 13 → 15 taken 19615 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 144 times.
19759 if (!doubleRef || i > 1)
390
2/4
✓ Branch 15 → 16 taken 19615 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 19615 times.
✗ Branch 16 → 25 not taken.
19615 newTypeChain.push_back(typeChain.at(i));
391
392 // Register new type or return if already registered
393
1/2
✓ Branch 20 → 21 taken 155716 times.
✗ Branch 20 → 25 not taken.
311432 return TypeRegistry::getOrInsert(newTypeChain);
394 155716 }
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 335190 times.
✗ Branch 3 → 6 not taken.
335190 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 18612232 const Type *Type::getBase() const {
409
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 18612232 times.
18612232 assert(!typeChain.empty());
410
411 // Create new type chain
412
3/6
✓ Branch 9 → 10 taken 18612232 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 18612232 times.
✓ Branch 12 → 14 taken 18612232 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
55836696 const TypeChain newTypeChain = {typeChain.front()};
413
414 // Register new type or return if already registered
415
1/2
✓ Branch 14 → 15 taken 18612232 times.
✗ Branch 14 → 32 not taken.
37224464 return TypeRegistry::getOrInsert(newTypeChain);
416
1/6
✓ Branch 6 → 7 taken 18612232 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.
37224464 }
417
418 /**
419 * Retrieve the same type, but with lambda captures
420 *
421 * @return Type with lambda captures
422 */
423 279 const Type *Type::getWithLambdaCaptures(bool enabled) const {
424
3/6
✓ Branch 2 → 3 taken 279 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 279 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 279 times.
279 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
425
426 // Create new type chain
427
1/2
✓ Branch 6 → 7 taken 279 times.
✗ Branch 6 → 16 not taken.
279 TypeChain newTypeChain = typeChain;
428 279 newTypeChain.front().data.hasCaptures = enabled;
429
430 // Register new type or return if already registered
431
1/2
✓ Branch 8 → 9 taken 279 times.
✗ Branch 8 → 14 not taken.
558 return TypeRegistry::getOrInsert(newTypeChain);
432 279 }
433
434 /**
435 * Retrieve the same type, but with the body scope removed
436 *
437 * @return Type with body scope removed
438 */
439 255112 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
440
3/6
✓ Branch 2 → 3 taken 255112 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 255112 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 255112 times.
255112 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
441
442 // Create new type chain
443
1/2
✓ Branch 6 → 7 taken 255112 times.
✗ Branch 6 → 16 not taken.
255112 TypeChain newTypeChain = typeChain;
444 255112 newTypeChain.front().data.bodyScope = bodyScope;
445
446 // Register new type or return if already registered
447
1/2
✓ Branch 8 → 9 taken 255112 times.
✗ Branch 8 → 14 not taken.
510224 return TypeRegistry::getOrInsert(newTypeChain);
448 255112 }
449
450 /**
451 * Retrieve the same type, but with the given template types
452 *
453 * @return Type with new template types
454 */
455 36399 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
456
2/4
✓ Branch 2 → 3 taken 36399 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 36399 times.
36399 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
457 36399 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 84018 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
466
3/6
✓ Branch 2 → 3 taken 84018 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 84018 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 84018 times.
84018 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
467
468 // Create new type chain
469
1/2
✓ Branch 6 → 7 taken 84018 times.
✗ Branch 6 → 17 not taken.
84018 TypeChain newTypeChain = typeChain;
470
1/2
✓ Branch 8 → 9 taken 84018 times.
✗ Branch 8 → 15 not taken.
84018 newTypeChain.front().templateTypes = templateTypes;
471
472 // Register new type or return if already registered
473
1/2
✓ Branch 9 → 10 taken 84018 times.
✗ Branch 9 → 15 not taken.
168036 return TypeRegistry::getOrInsert(newTypeChain);
474 84018 }
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 94189 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
482
3/6
✓ Branch 2 → 3 taken 94189 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 94189 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 94189 times.
94189 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
483
484 // Create new type chain
485
1/2
✓ Branch 6 → 7 taken 94189 times.
✗ Branch 6 → 17 not taken.
94189 TypeChain newTypeChain = typeChain;
486
1/2
✓ Branch 8 → 9 taken 94189 times.
✗ Branch 8 → 15 not taken.
94189 newTypeChain.front().paramTypes = paramAndReturnTypes;
487
488 // Register new type or return if already registered
489
1/2
✓ Branch 9 → 10 taken 94189 times.
✗ Branch 9 → 15 not taken.
188378 return TypeRegistry::getOrInsert(newTypeChain);
490 94189 }
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 81829 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
499
2/4
✓ Branch 3 → 4 taken 81829 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 81829 times.
✗ Branch 5 → 7 not taken.
81829 assert(!typeChain.empty() && !is(TY_INVALID));
500
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 81827 times.
81829 llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context;
501
502
10/12
✓ Branch 11 → 12 taken 81829 times.
✗ Branch 11 → 168 not taken.
✓ Branch 12 → 13 taken 41224 times.
✓ Branch 12 → 17 taken 40605 times.
✓ Branch 14 → 15 taken 995 times.
✓ Branch 14 → 18 taken 40229 times.
✓ Branch 15 → 16 taken 995 times.
✗ Branch 15 → 168 not taken.
✓ Branch 16 → 17 taken 142 times.
✓ Branch 16 → 18 taken 853 times.
✓ Branch 19 → 20 taken 40747 times.
✓ Branch 19 → 22 taken 41082 times.
81829 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
503 40747 return llvm::PointerType::get(context, 0);
504
505
2/2
✓ Branch 23 → 24 taken 853 times.
✓ Branch 23 → 32 taken 40229 times.
41082 if (isArray()) {
506
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 853 times.
853 assert(getArraySize() > 0);
507 853 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
508 853 return llvm::ArrayType::get(containedType, getArraySize());
509 }
510
511
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 40229 times.
40229 assert(!hasAnyGenericParts());
512
513
2/2
✓ Branch 36 → 37 taken 453 times.
✓ Branch 36 → 39 taken 39776 times.
40229 if (is(TY_DOUBLE))
514 453 return llvm::Type::getDoubleTy(context);
515
516
3/4
✓ Branch 39 → 40 taken 39776 times.
✗ Branch 39 → 169 not taken.
✓ Branch 40 → 41 taken 3951 times.
✓ Branch 40 → 43 taken 35825 times.
39776 if (isOneOf({TY_INT, TY_ENUM}))
517 3951 return llvm::Type::getInt32Ty(context);
518
519
2/2
✓ Branch 44 → 45 taken 294 times.
✓ Branch 44 → 47 taken 35531 times.
35825 if (is(TY_SHORT))
520 294 return llvm::Type::getInt16Ty(context);
521
522
2/2
✓ Branch 48 → 49 taken 2490 times.
✓ Branch 48 → 51 taken 33041 times.
35531 if (is(TY_LONG))
523 2490 return llvm::Type::getInt64Ty(context);
524
525
3/4
✓ Branch 51 → 52 taken 33041 times.
✗ Branch 51 → 170 not taken.
✓ Branch 52 → 53 taken 3024 times.
✓ Branch 52 → 55 taken 30017 times.
33041 if (isOneOf({TY_CHAR, TY_BYTE}))
526 3024 return llvm::Type::getInt8Ty(context);
527
528
2/2
✓ Branch 56 → 57 taken 3359 times.
✓ Branch 56 → 59 taken 26658 times.
30017 if (is(TY_BOOL))
529 3359 return llvm::Type::getInt1Ty(context);
530
531
3/4
✓ Branch 59 → 60 taken 26658 times.
✗ Branch 59 → 171 not taken.
✓ Branch 60 → 61 taken 25998 times.
✓ Branch 60 → 152 taken 660 times.
26658 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
532
1/2
✓ Branch 61 → 62 taken 25998 times.
✗ Branch 61 → 200 not taken.
25998 const Scope *structBodyScope = getBodyScope();
533
2/4
✓ Branch 63 → 64 taken 25998 times.
✗ Branch 63 → 200 not taken.
✓ Branch 64 → 65 taken 25998 times.
✗ Branch 64 → 200 not taken.
25998 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
534
1/2
✓ Branch 65 → 66 taken 25998 times.
✗ Branch 65 → 198 not taken.
25998 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
535
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 25998 times.
25998 assert(structSymbol != nullptr);
536
537 // Collect concrete field types
538 25998 std::string mangledName;
539 25998 std::vector<llvm::Type *> fieldTypes;
540 25998 bool isPacked = false;
541
2/2
✓ Branch 72 → 73 taken 23262 times.
✓ Branch 72 → 134 taken 2736 times.
25998 if (is(TY_STRUCT)) { // Struct
542
2/4
✓ Branch 73 → 74 taken 23262 times.
✗ Branch 73 → 194 not taken.
✓ Branch 74 → 75 taken 23262 times.
✗ Branch 74 → 194 not taken.
23262 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
543
1/2
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 23262 times.
23262 assert(spiceStruct != nullptr);
544
1/2
✓ Branch 77 → 78 taken 23262 times.
✗ Branch 77 → 172 not taken.
23262 mangledName = NameMangling::mangleStruct(*spiceStruct);
545
546
1/2
✓ Branch 80 → 81 taken 23262 times.
✗ Branch 80 → 194 not taken.
23262 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
547
1/2
✓ Branch 81 → 82 taken 23262 times.
✗ Branch 81 → 194 not taken.
23262 fieldTypes.reserve(totalFieldCount);
548
549 // If the struct implements interfaces, the first implicit field (added below via lookupField) is an interface
550 // type, which already lowers to a { ptr } struct carrying the vtable pointer. Only add an explicit ptr field
551 // here for structs without interfaces that still need a vtable (e.g. RTTI root types), to avoid duplicating it.
552
2/4
✓ Branch 82 → 83 taken 23262 times.
✗ Branch 82 → 194 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 23262 times.
23262 assert(structSymbol->declNode->isStructDef());
553
1/2
✓ Branch 85 → 86 taken 23262 times.
✗ Branch 85 → 87 not taken.
23262 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
554
3/4
✓ Branch 94 → 95 taken 23262 times.
✗ Branch 94 → 194 not taken.
✓ Branch 95 → 96 taken 218 times.
✓ Branch 95 → 99 taken 23044 times.
23262 if (spiceStruct->hasSynthesizedVTablePtr())
555
2/4
✓ Branch 96 → 97 taken 218 times.
✗ Branch 96 → 173 not taken.
✓ Branch 97 → 98 taken 218 times.
✗ Branch 97 → 173 not taken.
218 fieldTypes.push_back(llvm::PointerType::get(context, 0));
556
557 // Collect all field types
558
2/2
✓ Branch 112 → 100 taken 62276 times.
✓ Branch 112 → 113 taken 23262 times.
85538 for (size_t i = 0; i < totalFieldCount; i++) {
559
1/2
✗ Branch 100 → 101 not taken.
✓ Branch 100 → 102 taken 62276 times.
62276 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
560
1/2
✗ Branch 105 → 106 not taken.
✓ Branch 105 → 107 taken 62276 times.
62276 assert(fieldSymbol != nullptr);
561
3/6
✓ Branch 107 → 108 taken 62276 times.
✗ Branch 107 → 174 not taken.
✓ Branch 109 → 110 taken 62276 times.
✗ Branch 109 → 174 not taken.
✓ Branch 110 → 111 taken 62276 times.
✗ Branch 110 → 174 not taken.
62276 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
562 }
563
564 // Check if the struct is declared as packed
565
12/18
✓ Branch 113 → 114 taken 220 times.
✓ Branch 113 → 120 taken 23042 times.
✓ Branch 116 → 117 taken 220 times.
✗ Branch 116 → 175 not taken.
✓ Branch 117 → 118 taken 220 times.
✗ Branch 117 → 175 not taken.
✓ Branch 118 → 119 taken 2 times.
✓ Branch 118 → 120 taken 218 times.
✓ Branch 121 → 122 taken 220 times.
✓ Branch 121 → 123 taken 23042 times.
✓ Branch 123 → 124 taken 220 times.
✓ Branch 123 → 126 taken 23042 times.
✓ Branch 126 → 127 taken 2 times.
✓ Branch 126 → 144 taken 23260 times.
✗ Branch 175 → 176 not taken.
✗ Branch 175 → 177 not taken.
✗ Branch 179 → 180 not taken.
✗ Branch 179 → 182 not taken.
23702 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
566
2/4
✓ Branch 129 → 130 taken 2 times.
✗ Branch 129 → 186 not taken.
✓ Branch 130 → 131 taken 2 times.
✗ Branch 130 → 184 not taken.
6 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
567 } else { // Interface
568
2/4
✓ Branch 134 → 135 taken 2736 times.
✗ Branch 134 → 194 not taken.
✓ Branch 135 → 136 taken 2736 times.
✗ Branch 135 → 194 not taken.
2736 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
569
1/2
✗ Branch 136 → 137 not taken.
✓ Branch 136 → 138 taken 2736 times.
2736 assert(spiceInterface != nullptr);
570
1/2
✓ Branch 138 → 139 taken 2736 times.
✗ Branch 138 → 190 not taken.
2736 mangledName = NameMangling::mangleInterface(*spiceInterface);
571
572 // vtable pointer
573
2/4
✓ Branch 141 → 142 taken 2736 times.
✗ Branch 141 → 191 not taken.
✓ Branch 142 → 143 taken 2736 times.
✗ Branch 142 → 191 not taken.
2736 fieldTypes.push_back(llvm::PointerType::get(context, 0));
574 }
575
576
1/2
✓ Branch 146 → 147 taken 25998 times.
✗ Branch 146 → 192 not taken.
25998 return llvm::StructType::create(context, fieldTypes, mangledName, isPacked);
577 25998 }
578
579
2/4
✓ Branch 152 → 153 taken 660 times.
✗ Branch 152 → 201 not taken.
✓ Branch 153 → 154 taken 660 times.
✗ Branch 153 → 160 not taken.
660 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
580 // Lambda/function values are represented as a fat pointer with three slots:
581 // { fctPtr, capturePtr, captureSize }. The capture size (in bytes) travels with
582 // the value so that the std Lambda type can take ownership of the captures on the
583 // heap regardless of where the lambda came from. It is 0 if there is no owned
584 // capture struct (no captures, or a single capture stored inline in capturePtr).
585 660 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
586 660 llvm::IntegerType *int64Ty = llvm::Type::getInt64Ty(context);
587
1/2
✓ Branch 157 → 158 taken 660 times.
✗ Branch 157 → 202 not taken.
660 return llvm::StructType::get(context, {ptrTy, ptrTy, int64Ty});
588 }
589
590 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
591 }
592
593 /**
594 * Remove pointers / arrays / references if both types have them as far as possible.
595 *
596 * @param typeA Candidate type
597 * @param typeB Requested type
598 */
599 791623 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
600 // Unwrap both types as far as possible
601
2/2
✓ Branch 7 → 3 taken 65065 times.
✓ Branch 7 → 8 taken 791623 times.
856688 while (typeA->isSameContainerTypeAs(typeB)) {
602 65065 typeB = typeB->getContained();
603 65065 typeA = typeA->getContained();
604 }
605 791623 }
606
607 /**
608 * Remove pointers / arrays / references if both types have them as far as possible.
609 * Furthermore, remove reference wrappers if possible.
610 *
611 * @param typeA Candidate type
612 * @param typeB Requested type
613 */
614 775483 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
615 // Remove reference wrapper of front type if required
616
6/6
✓ Branch 3 → 4 taken 355380 times.
✓ Branch 3 → 7 taken 420103 times.
✓ Branch 5 → 6 taken 313763 times.
✓ Branch 5 → 7 taken 41617 times.
✓ Branch 8 → 9 taken 313763 times.
✓ Branch 8 → 11 taken 461720 times.
775483 if (typeA->isRef() && !typeB->isRef())
617 313763 typeA = typeA->removeReferenceWrapper();
618
619 // Remove reference wrapper of requested type if required
620
8/8
✓ Branch 12 → 13 taken 733866 times.
✓ Branch 12 → 18 taken 41617 times.
✓ Branch 14 → 15 taken 25920 times.
✓ Branch 14 → 18 taken 707946 times.
✓ Branch 16 → 17 taken 21427 times.
✓ Branch 16 → 18 taken 4493 times.
✓ Branch 19 → 20 taken 21427 times.
✓ Branch 19 → 22 taken 754056 times.
775483 if (!typeA->isRef() && typeB->isRef() && !typeA->isBase(TY_GENERIC))
621 21427 typeB = typeB->removeReferenceWrapper();
622
623 // Unwrap both types as far as possible
624 775483 unwrapBoth(typeA, typeB);
625 775483 }
626
627 /**
628 * Check if two types have the same type chain depth
629 *
630 * @param typeA First type
631 * @param typeB Second type
632 * @return Same depth or not
633 */
634 126453 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
635 126453 return typeA->typeChain.size() == typeB->typeChain.size();
636 }
637
638 } // namespace spice::compiler
639