GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/Type.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 224 228 98.2%
Functions: 43 43 100.0%
Branches: 264 448 58.9%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 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 <exception/CompilerError.h>
10 #include <exception/SemanticError.h>
11 #include <global/TypeRegistry.h>
12 #include <irgenerator/NameMangling.h>
13 #include <model/Struct.h>
14 #include <symboltablebuilder/Scope.h>
15 #include <symboltablebuilder/SymbolTableEntry.h>
16
17 #include <llvm/IR/Module.h>
18 #include <llvm/IR/Type.h>
19
20 namespace spice::compiler {
21
22
3/10
✓ Branch 2 taken 7449427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7449427 times.
✓ Branch 5 taken 7449427 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
22348281 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
23
24
4/12
✓ Branch 1 taken 1253 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1253 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1253 times.
✓ Branch 8 taken 1253 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
3759 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
25
26 855 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
27 855 const QualTypeList &templateTypes)
28
5/14
✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 855 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 855 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 855 times.
✓ Branch 11 taken 855 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
2565 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
29
30 1302474 Type::Type(TypeChain typeChain) : typeChain(std::move(typeChain)) {}
31
32 /**
33 * Get the super type of the current type
34 *
35 * @return Super type
36 */
37 6835218 SuperType Type::getSuperType() const {
38
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6835218 times.
6835218 assert(!typeChain.empty());
39 6835218 return typeChain.back().superType;
40 }
41
42 /**
43 * Get the sub type of the current type
44 *
45 * @return Sub type
46 */
47 208148 const std::string &Type::getSubType() const {
48
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 208148 times.
208148 assert(!typeChain.empty());
49
2/4
✓ Branch 1 taken 208148 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 208148 times.
208148 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
50 208148 return typeChain.back().subType;
51 }
52
53 /**
54 * Get the array size of the current type
55 *
56 * @return Array size
57 */
58 522 unsigned int Type::getArraySize() const {
59
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 522 times.
522 assert(getSuperType() == TY_ARRAY);
60 522 return typeChain.back().data.arraySize;
61 }
62
63 /**
64 * Get the body scope of the current type
65 *
66 * @return Body scope
67 */
68 99885 Scope *Type::getBodyScope() const {
69
2/4
✓ Branch 1 taken 99885 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 99885 times.
99885 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
70 99885 return typeChain.back().data.bodyScope;
71 }
72
73 /**
74 * Get the pointer type of the current type as a new type
75 *
76 * @param node AST node for error messages
77 * @return Pointer type of the current type
78 */
79 10774 const Type *Type::toPtr(const ASTNode *node) const {
80 // Do not allow pointers of dyn
81
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10772 times.
10774 if (is(TY_DYN))
82
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
6 throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead");
83
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10772 times.
10772 if (isRef())
84 throw SemanticError(node, REF_POINTERS_ARE_NOT_ALLOWED, "Pointers to references are not allowed. Use pointer instead");
85
86 // Create new type chain
87
1/2
✓ Branch 1 taken 10772 times.
✗ Branch 2 not taken.
10772 TypeChain newTypeChain = typeChain;
88
1/2
✓ Branch 1 taken 10772 times.
✗ Branch 2 not taken.
10772 newTypeChain.emplace_back(TY_PTR);
89
90 // Register new type or return if already registered
91
1/2
✓ Branch 1 taken 10772 times.
✗ Branch 2 not taken.
21544 return TypeRegistry::getOrInsert(newTypeChain);
92 10772 }
93
94 /**
95 * Get the reference type of the current type as a new type
96 *
97 * @param node AST node for error messages
98 * @return Reference type of the current type
99 */
100 11992 const Type *Type::toRef(const ASTNode *node) const {
101 // Do not allow references of dyn
102
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11992 times.
11992 if (is(TY_DYN))
103 throw SemanticError(node, DYN_REFERENCES_NOT_ALLOWED, "Just use the dyn type without '&' instead");
104 // Do not allow references of references
105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11992 times.
11992 if (isRef())
106 throw SemanticError(node, MULTI_REF_NOT_ALLOWED, "References to references are not allowed");
107
108 // Create new type chain
109
1/2
✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
11992 TypeChain newTypeChain = typeChain;
110
1/2
✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
11992 newTypeChain.emplace_back(TY_REF);
111
112 // Register new type or return if already registered
113
1/2
✓ Branch 1 taken 11992 times.
✗ Branch 2 not taken.
23984 return TypeRegistry::getOrInsert(newTypeChain);
114 11992 }
115
116 /**
117 * Get the array type of the current type as a new type
118 *
119 * @param node AST node for error messages
120 * @param size Size of the array
121 * @return Array type of the current type
122 */
123 201 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck /*=false*/) const {
124 // Do not allow arrays of dyn
125
6/6
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 66 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 134 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 200 times.
201 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
126
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead");
127
128 // Create new type chain
129
1/2
✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
200 TypeChain newTypeChain = typeChain;
130
1/2
✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
200 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
131
132 // Register new type or return if already registered
133
1/2
✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
400 return TypeRegistry::getOrInsert(newTypeChain);
134 200 }
135
136 /**
137 * Retrieve the base type of an array or a pointer
138 *
139 * @return Base type
140 */
141 75447 const Type *Type::getContained() const {
142
2/2
✓ Branch 1 taken 1226 times.
✓ Branch 2 taken 74221 times.
75447 if (is(TY_STRING))
143
1/2
✓ Branch 1 taken 1226 times.
✗ Branch 2 not taken.
1226 return TypeRegistry::getOrInsert(TY_CHAR);
144
145 // Create new type chain
146
1/2
✓ Branch 1 taken 74221 times.
✗ Branch 2 not taken.
74221 TypeChain newTypeChain = typeChain;
147
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 74221 times.
74221 assert(newTypeChain.size() > 1);
148 74221 newTypeChain.pop_back();
149
150 // Register new type or return if already registered
151
1/2
✓ Branch 1 taken 74221 times.
✗ Branch 2 not taken.
74221 return TypeRegistry::getOrInsert(newTypeChain);
152 74221 }
153
154 /**
155 * Replace the base type with another one
156 *
157 * @param newBaseType New base type
158 * @return The new type
159 */
160 10152 const Type *Type::replaceBase(const Type *newBaseType) const {
161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10152 times.
10152 assert(!typeChain.empty());
162
163 // Create new type
164
1/2
✓ Branch 1 taken 10152 times.
✗ Branch 2 not taken.
10152 TypeChain newTypeChain = newBaseType->typeChain;
165
4/4
✓ Branch 1 taken 393 times.
✓ Branch 2 taken 9759 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 379 times.
10152 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
166
2/2
✓ Branch 1 taken 1703 times.
✓ Branch 2 taken 10152 times.
11855 for (size_t i = 1; i < typeChain.size(); i++)
167
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1689 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
1703 if (!doubleRef || i > 1)
168
2/4
✓ Branch 1 taken 1689 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1689 times.
✗ Branch 5 not taken.
1689 newTypeChain.push_back(typeChain.at(i));
169
170 // Register new type or return if already registered
171
1/2
✓ Branch 1 taken 10152 times.
✗ Branch 2 not taken.
20304 return TypeRegistry::getOrInsert(newTypeChain);
172 10152 }
173
174 /**
175 * Remove reference wrapper from the current type
176 *
177 * @return Type without reference wrapper
178 */
179
1/2
✓ Branch 1 taken 20593 times.
✗ Branch 2 not taken.
20593 const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; }
180
181 /**
182 * Return the LLVM type for this symbol type
183 *
184 * @param sourceFile Referenced source file
185 * @return Corresponding LLVM type
186 */
187 5171 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
188
2/4
✓ Branch 1 taken 5171 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5171 times.
✗ Branch 5 not taken.
5171 assert(!typeChain.empty() && !is(TY_INVALID));
189 5171 llvm::LLVMContext &context = sourceFile->llvmModule->getContext();
190
191
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 5107 times.
5171 if (is(TY_DOUBLE))
192 64 return llvm::Type::getDoubleTy(context);
193
194
3/4
✓ Branch 1 taken 5107 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 492 times.
✓ Branch 4 taken 4615 times.
5107 if (isOneOf({TY_INT, TY_ENUM}))
195 492 return llvm::Type::getInt32Ty(context);
196
197
2/2
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 4554 times.
4615 if (is(TY_SHORT))
198 61 return llvm::Type::getInt16Ty(context);
199
200
2/2
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 4234 times.
4554 if (is(TY_LONG))
201 320 return llvm::Type::getInt64Ty(context);
202
203
3/4
✓ Branch 1 taken 4234 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 164 times.
✓ Branch 4 taken 4070 times.
4234 if (isOneOf({TY_CHAR, TY_BYTE}))
204 164 return llvm::Type::getInt8Ty(context);
205
206
2/2
✓ Branch 1 taken 307 times.
✓ Branch 2 taken 3763 times.
4070 if (is(TY_BOOL))
207 307 return llvm::Type::getInt1Ty(context);
208
209
3/4
✓ Branch 1 taken 3763 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1318 times.
✓ Branch 4 taken 2445 times.
3763 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
210
1/2
✓ Branch 1 taken 1318 times.
✗ Branch 2 not taken.
1318 const Scope *structBodyScope = getBodyScope();
211
2/4
✓ Branch 2 taken 1318 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1318 times.
✗ Branch 6 not taken.
1318 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
212
1/2
✓ Branch 1 taken 1318 times.
✗ Branch 2 not taken.
1318 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1318 times.
1318 assert(structSymbol != nullptr);
214
215 // Collect concrete field types
216 llvm::StructType *structType;
217 1318 std::vector<llvm::Type *> fieldTypes;
218 1318 bool isPacked = false;
219
2/2
✓ Branch 1 taken 1176 times.
✓ Branch 2 taken 142 times.
1318 if (is(TY_STRUCT)) { // Struct
220
2/4
✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1176 times.
✗ Branch 5 not taken.
1176 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1176 times.
1176 assert(spiceStruct != nullptr);
222
1/2
✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
1176 const std::string mangledName = NameMangling::mangleStruct(*spiceStruct);
223
1/2
✓ Branch 2 taken 1176 times.
✗ Branch 3 not taken.
1176 structType = llvm::StructType::create(context, mangledName);
224
225
1/2
✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
1176 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
226
1/2
✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
1176 fieldTypes.reserve(totalFieldCount);
227
228 // If the struct has no interface types, but a vtable was requested, add another ptr field type
229
2/4
✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1176 times.
1176 assert(structSymbol->declNode->isStructDef());
230
1/2
✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
1176 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
231
4/4
✓ Branch 0 taken 935 times.
✓ Branch 1 taken 241 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 899 times.
1176 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
232
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 fieldTypes.push_back(llvm::PointerType::get(context, 0));
233
234 // Collect all field types
235
2/2
✓ Branch 0 taken 3134 times.
✓ Branch 1 taken 1176 times.
4310 for (size_t i = 0; i < totalFieldCount; i++) {
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3134 times.
3134 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3134 times.
3134 assert(fieldSymbol != nullptr);
238
3/6
✓ Branch 1 taken 3134 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3134 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3134 times.
✗ Branch 9 not taken.
3134 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
239 }
240
241 // Check if the struct is declared as packed
242
15/24
✓ Branch 1 taken 1176 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 1139 times.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 37 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 37 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 36 times.
✓ Branch 19 taken 37 times.
✓ Branch 20 taken 1139 times.
✓ Branch 22 taken 37 times.
✓ Branch 23 taken 1139 times.
✓ Branch 24 taken 1 times.
✓ Branch 25 taken 1175 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
1250 if (structDeclNode->attrs() && structDeclNode->attrs()->attrLst()->hasAttr(ATTR_CORE_COMPILER_PACKED))
243
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
3 isPacked = structDeclNode->attrs()->attrLst()->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
244 1176 } else { // Interface
245
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
142 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 assert(spiceInterface != nullptr);
247
1/2
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
142 const std::string mangledName = NameMangling::mangleInterface(*spiceInterface);
248
1/2
✓ Branch 2 taken 142 times.
✗ Branch 3 not taken.
142 structType = llvm::StructType::create(context, mangledName);
249
250
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
142 fieldTypes.push_back(llvm::PointerType::get(context, 0));
251 142 }
252
253 // Set field types to struct type
254
1/2
✓ Branch 2 taken 1318 times.
✗ Branch 3 not taken.
1318 structType->setBody(fieldTypes, isPacked);
255
256 1318 return structType;
257 1318 }
258
259
9/10
✓ Branch 1 taken 2445 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 125 times.
✓ Branch 4 taken 2320 times.
✓ Branch 6 taken 55 times.
✓ Branch 7 taken 70 times.
✓ Branch 9 taken 20 times.
✓ Branch 10 taken 35 times.
✓ Branch 11 taken 2340 times.
✓ Branch 12 taken 105 times.
2445 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
260 2340 return llvm::PointerType::get(context, 0);
261
262
3/4
✓ Branch 1 taken 105 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 35 times.
105 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
263 70 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
264
1/2
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
70 return llvm::StructType::get(context, {ptrTy, ptrTy});
265 }
266
267
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 if (isArray()) {
268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
35 assert(getArraySize() > 0);
269 35 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
270 35 return llvm::ArrayType::get(containedType, getArraySize());
271 }
272
273 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true)); // GCOVR_EXCL_LINE
274 }
275
276 /**
277 * Check if the base type of the current type chain is of a certain super type
278 *
279 * @param superType Super type to check for
280 * @return Applicable or not
281 */
282 370339 bool Type::isBase(SuperType superType) const {
283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 370339 times.
370339 assert(!typeChain.empty());
284 370339 return typeChain.front().superType == superType;
285 }
286
287 /**
288 * Check if the current type is a primitive type
289 *
290 * @return Primitive type or not
291 */
292
1/2
✓ Branch 1 taken 63053 times.
✗ Branch 2 not taken.
63053 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
293
294 /**
295 * Check if the current type is a pointer type
296 *
297 * @return Pointer type or not
298 */
299 222584 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
300
301 /**
302 * Check if the current type is a reference type
303 *
304 * @return Reference type or not
305 */
306 641357 bool Type::isRef() const { return getSuperType() == TY_REF; }
307
308 /**
309 * Check if the current type is an array type
310 *
311 * @return Array type or not
312 */
313 114175 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
314
315 /**
316 * Check if the current type is of the same container type like the other type.
317 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
318 *
319 * @param other Other symbol type
320 * @return Same container type or not
321 */
322 69887 bool Type::isSameContainerTypeAs(const Type *other) const {
323
4/4
✓ Branch 1 taken 1654 times.
✓ Branch 2 taken 68233 times.
✓ Branch 4 taken 1347 times.
✓ Branch 5 taken 307 times.
69887 const bool bothPtr = isPtr() && other->isPtr();
324
3/4
✓ Branch 1 taken 4302 times.
✓ Branch 2 taken 65585 times.
✓ Branch 4 taken 4302 times.
✗ Branch 5 not taken.
69887 const bool bothRef = isRef() && other->isRef();
325
3/4
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 69837 times.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
69887 const bool bothArray = isArray() && other->isArray();
326
6/6
✓ Branch 0 taken 68540 times.
✓ Branch 1 taken 1347 times.
✓ Branch 2 taken 64238 times.
✓ Branch 3 taken 4302 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 64188 times.
69887 return bothPtr || bothRef || bothArray;
327 }
328
329 /**
330 * Retrieve the base type of the current type
331 *
332 * @return Base type
333 */
334 1160846 const Type *Type::getBase() const {
335
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1160846 times.
1160846 assert(!typeChain.empty());
336
337 // Create new type chain
338
3/6
✓ Branch 1 taken 1160846 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1160846 times.
✓ Branch 4 taken 1160846 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3482538 const TypeChain newTypeChain = {typeChain.front()};
339
340 // Register new type or return if already registered
341
1/2
✓ Branch 1 taken 1160846 times.
✗ Branch 2 not taken.
2321692 return TypeRegistry::getOrInsert(newTypeChain);
342
1/6
✓ Branch 2 taken 1160846 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
2321692 }
343
344 /**
345 * Retrieve the same type, but with lambda captures
346 *
347 * @return Type with lambda captures
348 */
349 42 const Type *Type::getWithLambdaCaptures(bool enabled) const {
350
3/6
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 42 times.
42 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
351
352 // Create new type chain
353
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 TypeChain newTypeChain = typeChain;
354 42 newTypeChain.front().data.hasCaptures = enabled;
355
356 // Register new type or return if already registered
357
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
84 return TypeRegistry::getOrInsert(newTypeChain);
358 42 }
359
360 /**
361 * Retrieve the same type, but with the body scope removed
362 *
363 * @return Type with body scope removed
364 */
365 19609 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
366
3/6
✓ Branch 1 taken 19609 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19609 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 19609 times.
19609 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
367
368 // Create new type chain
369
1/2
✓ Branch 1 taken 19609 times.
✗ Branch 2 not taken.
19609 TypeChain newTypeChain = typeChain;
370 19609 newTypeChain.front().data.bodyScope = bodyScope;
371
372 // Register new type or return if already registered
373
1/2
✓ Branch 1 taken 19609 times.
✗ Branch 2 not taken.
39218 return TypeRegistry::getOrInsert(newTypeChain);
374 19609 }
375
376 /**
377 * Retrieve the same type, but with the given template types
378 *
379 * @return Type with new template types
380 */
381 2656 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
382
2/4
✓ Branch 1 taken 2656 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2656 times.
2656 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
383 2656 return getWithBaseTemplateTypes(templateTypes);
384 }
385
386 /**
387 * Retrieve the same type, but with the given base template types
388 *
389 * @return Type with new base template types
390 */
391 6284 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
392
3/6
✓ Branch 1 taken 6284 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6284 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6284 times.
6284 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
393
394 // Create new type chain
395
1/2
✓ Branch 1 taken 6284 times.
✗ Branch 2 not taken.
6284 TypeChain newTypeChain = typeChain;
396
1/2
✓ Branch 2 taken 6284 times.
✗ Branch 3 not taken.
6284 newTypeChain.front().templateTypes = templateTypes;
397
398 // Register new type or return if already registered
399
1/2
✓ Branch 1 taken 6284 times.
✗ Branch 2 not taken.
12568 return TypeRegistry::getOrInsert(newTypeChain);
400 6284 }
401
402 /**
403 * Retrieve the same type, but with the param and return types removed
404 *
405 * @return Type with param and return types removed
406 */
407 8356 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
408
3/6
✓ Branch 1 taken 8356 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8356 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8356 times.
8356 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
409
410 // Create new type chain
411
1/2
✓ Branch 1 taken 8356 times.
✗ Branch 2 not taken.
8356 TypeChain newTypeChain = typeChain;
412
1/2
✓ Branch 2 taken 8356 times.
✗ Branch 3 not taken.
8356 newTypeChain.front().paramTypes = paramAndReturnTypes;
413
414 // Register new type or return if already registered
415
1/2
✓ Branch 1 taken 8356 times.
✗ Branch 2 not taken.
16712 return TypeRegistry::getOrInsert(newTypeChain);
416 8356 }
417
418 /**
419 * Checks if the base type is generic itself or has generic parts in its template types
420 *
421 * @return Contains generic parts or not
422 */
423 282985 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
424
1/2
✓ Branch 1 taken 282985 times.
✗ Branch 2 not taken.
282985 const Type *baseType = getBase();
425
426 // Check if the type itself is generic
427
2/2
✓ Branch 1 taken 39038 times.
✓ Branch 2 taken 243947 times.
282985 if (baseType->is(TY_GENERIC))
428 39038 return true;
429
430 // Check if the type has generic template types
431
1/2
✓ Branch 2 taken 243947 times.
✗ Branch 3 not taken.
243947 const auto templateTypes = baseType->getTemplateTypes();
432
3/4
✓ Branch 1 taken 243947 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13741 times.
✓ Branch 4 taken 230206 times.
317080 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
433 13741 return true;
434
435 // Check param and return types or functions/procedures
436
3/4
✓ Branch 1 taken 230206 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 514 times.
✓ Branch 4 taken 229692 times.
230206 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
437
2/4
✓ Branch 1 taken 514 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 514 times.
✗ Branch 5 not taken.
514 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
438
3/4
✓ Branch 1 taken 514 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 104 times.
✓ Branch 4 taken 410 times.
1344 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
439 104 return true;
440
2/2
✓ Branch 1 taken 410 times.
✓ Branch 2 taken 104 times.
514 }
441
442 230102 return false; // Does not have generic parts
443 243947 }
444
445 /**
446 * Retrieve template types of the current type
447 *
448 * @return Vector of template types
449 */
450 317936 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
451
452 /**
453 * Check if the current type is of a certain super type
454 *
455 * @return Applicable or not
456 */
457 4940681 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
458
459 /**
460 * Check if the current type is one of a list of super types
461 *
462 * @return Applicable or not
463 */
464 1034592 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
465 3402645 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
466 }
467
468 /**
469 * Get the name of the symbol type as a string
470 *
471 * @param withSize Include the array size for sized types
472 * @return Symbol type name
473 */
474 619699 void Type::getName(std::stringstream &name, bool withSize) const { // NOLINT(misc-no-recursion)
475 // Loop through all chain elements
476
2/2
✓ Branch 4 taken 788878 times.
✓ Branch 5 taken 619699 times.
1408577 for (const TypeChainElement &chainElement : typeChain)
477
2/4
✓ Branch 1 taken 788878 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 788878 times.
✗ Branch 5 not taken.
788878 name << chainElement.getName(withSize);
478 619699 }
479
480 /**
481 * Get the name of the symbol type as a string
482 *
483 * @param withSize Include the array size for sized types
484 * @param ignorePublic Ignore any potential public specifier
485 * @return Symbol type name
486 */
487 10544 std::string Type::getName(bool withSize) const {
488
1/2
✓ Branch 1 taken 10544 times.
✗ Branch 2 not taken.
10544 std::stringstream name;
489
1/2
✓ Branch 1 taken 10544 times.
✗ Branch 2 not taken.
10544 getName(name, withSize);
490
1/2
✓ Branch 1 taken 10544 times.
✗ Branch 2 not taken.
21088 return name.str();
491 10544 }
492
493 /**
494 * Get the return type of a function type
495 *
496 * @return Function return type
497 */
498 21 const QualType &Type::getFunctionReturnType() const {
499
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 assert(is(TY_FUNCTION));
500
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 assert(!typeChain.back().paramTypes.empty());
501 21 return typeChain.back().paramTypes.front();
502 }
503
504 /**
505 * Get the param types of a function or procedure type
506 *
507 * @return Function param types
508 */
509 97 QualTypeList Type::getFunctionParamTypes() const {
510
2/4
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
97 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
511
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
97 if (typeChain.back().paramTypes.empty())
512 return {};
513
1/2
✓ Branch 6 taken 97 times.
✗ Branch 7 not taken.
291 return {typeChain.back().paramTypes.begin() + 1, typeChain.back().paramTypes.end()};
514 }
515
516 /**
517 * Check if a function or procedure type has captures
518 *
519 * @return Has captures
520 */
521 134 bool Type::hasLambdaCaptures() const {
522
2/4
✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 134 times.
134 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
523 134 return typeChain.front().data.hasCaptures;
524 }
525
526 /**
527 * Get the param and return types of a function or procedure base type
528 *
529 * @return Function param and return types (first is return type, rest are param types)
530 */
531 613 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
532
2/4
✓ Branch 2 taken 613 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 613 times.
613 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
533 613 return typeChain.front().paramTypes;
534 }
535
536 /**
537 * Check for the matching compatibility of two types.
538 * Useful for struct and function matching as well as assignment type validation and function arg matching.
539 *
540 * @param otherType Type to compare against
541 * @param ignoreArraySize Ignore array sizes
542 * @return Matching or not
543 */
544 79883 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
545 // If the size does not match, it is not equal
546
2/2
✓ Branch 2 taken 5365 times.
✓ Branch 3 taken 74518 times.
79883 if (typeChain.size() != otherType->typeChain.size())
547 5365 return false;
548
549 // Compare the elements
550
2/2
✓ Branch 1 taken 79461 times.
✓ Branch 2 taken 51436 times.
130897 for (size_t i = 0; i < typeChain.size(); i++) {
551 79461 const TypeChainElement &lhsElement = typeChain.at(i);
552 79461 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
553
554 // Ignore differences in array size
555
5/6
✓ Branch 0 taken 56305 times.
✓ Branch 1 taken 23156 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 56304 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
79461 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
556 1 continue;
557
558 // Not both types are arrays -> compare them as usual
559
2/2
✓ Branch 1 taken 23082 times.
✓ Branch 2 taken 56378 times.
79460 if (lhsElement != rhsElement)
560 23082 return false;
561 }
562
563 // Ignore or compare specifiers
564 51436 return true;
565 }
566
567 /**
568 * Remove pointers / arrays / references if both types have them as far as possible.
569 * Furthermore, remove reference wrappers if possible.
570 *
571 * @param typeA Candidate type
572 * @param typeB Requested type
573 */
574 62031 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
575 // Remove reference wrapper of front type if required
576
6/6
✓ Branch 1 taken 21467 times.
✓ Branch 2 taken 40564 times.
✓ Branch 4 taken 17165 times.
✓ Branch 5 taken 4302 times.
✓ Branch 6 taken 17165 times.
✓ Branch 7 taken 44866 times.
62031 if (typeA->isRef() && !typeB->isRef())
577 17165 typeA = typeA->removeReferenceWrapper();
578
579 // Remove reference wrapper of requested type if required
580
8/8
✓ Branch 1 taken 57729 times.
✓ Branch 2 taken 4302 times.
✓ Branch 4 taken 3738 times.
✓ Branch 5 taken 53991 times.
✓ Branch 8 taken 3428 times.
✓ Branch 9 taken 310 times.
✓ Branch 10 taken 3428 times.
✓ Branch 11 taken 58603 times.
62031 if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC))
581 3428 typeB = typeB->removeReferenceWrapper();
582
583 // Unwrap both types as far as possible
584
2/2
✓ Branch 1 taken 5499 times.
✓ Branch 2 taken 62031 times.
67530 while (typeA->isSameContainerTypeAs(typeB)) {
585 5499 typeB = typeB->getContained();
586 5499 typeA = typeA->getContained();
587 }
588 62031 }
589
590 /**
591 * Check if two types have the same type chain depth
592 *
593 * @param typeA First type
594 * @param typeB Second type
595 * @return Same depth or not
596 */
597 13391 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
598 13391 return typeA->typeChain.size() == typeB->typeChain.size();
599 }
600
601 } // namespace spice::compiler
602