GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/Type.cpp
Date: 2025-12-29 16:28:41
Coverage Exec Excl Total
Lines: 98.3% 229 1 234
Functions: 100.0% 45 0 45
Branches: 59.6% 268 6 456

Line Branch Exec Source
1 // Copyright (c) 2021-2025 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 5 → 6 taken 5321637 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 5321637 times.
✓ Branch 7 → 9 taken 5321637 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.
15964911 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
23
24
4/12
✓ Branch 4 → 5 taken 1835 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 1835 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 1835 times.
✓ Branch 8 → 10 taken 1835 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.
5505 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
25
26 1177 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
27 1177 const QualTypeList &templateTypes)
28
5/14
✓ Branch 4 → 5 taken 1177 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 1177 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 1177 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 1177 times.
✓ Branch 9 → 11 taken 1177 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.
3531 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
29
30 1513125 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 10310861 SuperType Type::getSuperType() const {
38
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 10310861 times.
10310861 assert(!typeChain.empty());
39 10310861 return typeChain.back().superType;
40 }
41
42 /**
43 * Get the sub type of the current type
44 *
45 * @return Sub type
46 */
47 298814 const std::string &Type::getSubType() const {
48
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 298814 times.
298814 assert(!typeChain.empty());
49
2/4
✓ Branch 5 → 6 taken 298814 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 298814 times.
298814 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
50 298814 return typeChain.back().subType;
51 }
52
53 /**
54 * Get the array size of the current type
55 *
56 * @return Array size
57 */
58 704 unsigned int Type::getArraySize() const {
59
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 704 times.
704 assert(isArray());
60 704 return typeChain.back().data.arraySize;
61 }
62
63 /**
64 * Get the body scope of the current type
65 *
66 * @return Body scope
67 */
68 136952 Scope *Type::getBodyScope() const {
69
2/4
✓ Branch 2 → 3 taken 136952 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 136952 times.
136952 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
70 136952 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 25156 const Type *Type::toPtr(const ASTNode *node) const {
80 // Do not allow pointers of dyn
81
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 12 taken 25154 times.
25156 if (is(TY_DYN))
82
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");
83
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 25154 times.
25154 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 22 → 23 taken 25154 times.
✗ Branch 22 → 50 not taken.
25154 TypeChain newTypeChain = typeChain;
88
1/2
✓ Branch 23 → 24 taken 25154 times.
✗ Branch 23 → 47 not taken.
25154 newTypeChain.emplace_back(TY_PTR);
89
90 // Register new type or return if already registered
91
1/2
✓ Branch 24 → 25 taken 25154 times.
✗ Branch 24 → 48 not taken.
50308 return TypeRegistry::getOrInsert(newTypeChain);
92 25154 }
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 12607 const Type *Type::toRef(const ASTNode *node) const {
101 // Do not allow references of dyn
102
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 12607 times.
12607 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 13 → 14 not taken.
✓ Branch 13 → 22 taken 12607 times.
12607 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 22 → 23 taken 12607 times.
✗ Branch 22 → 50 not taken.
12607 TypeChain newTypeChain = typeChain;
110
1/2
✓ Branch 23 → 24 taken 12607 times.
✗ Branch 23 → 47 not taken.
12607 newTypeChain.emplace_back(TY_REF);
111
112 // Register new type or return if already registered
113
1/2
✓ Branch 24 → 25 taken 12607 times.
✗ Branch 24 → 48 not taken.
25214 return TypeRegistry::getOrInsert(newTypeChain);
114 12607 }
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 * @param skipDynCheck Skip check if array base type is dyn
122 * @return Array type of the current type
123 */
124 227 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
125 // Do not allow arrays of dyn
126
6/6
✓ Branch 2 → 3 taken 150 times.
✓ Branch 2 → 6 taken 77 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 149 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 16 taken 226 times.
227 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
127
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");
128
129 // Create new type chain
130
1/2
✓ Branch 16 → 17 taken 226 times.
✗ Branch 16 → 36 not taken.
226 TypeChain newTypeChain = typeChain;
131
1/2
✓ Branch 17 → 18 taken 226 times.
✗ Branch 17 → 32 not taken.
226 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
132
133 // Register new type or return if already registered
134
1/2
✓ Branch 18 → 19 taken 226 times.
✗ Branch 18 → 34 not taken.
452 return TypeRegistry::getOrInsert(newTypeChain);
135 226 }
136
137 /**
138 * Retrieve the base type of an array or a pointer
139 *
140 * @return Base type
141 */
142 138525 const Type *Type::getContained() const {
143
2/2
✓ Branch 3 → 4 taken 1558 times.
✓ Branch 3 → 6 taken 136967 times.
138525 if (is(TY_STRING))
144
1/2
✓ Branch 4 → 5 taken 1558 times.
✗ Branch 4 → 18 not taken.
1558 return TypeRegistry::getOrInsert(TY_CHAR);
145
146 // Create new type chain
147
1/2
✓ Branch 6 → 7 taken 136967 times.
✗ Branch 6 → 18 not taken.
136967 TypeChain newTypeChain = typeChain;
148
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 136967 times.
136967 assert(newTypeChain.size() > 1);
149 136967 newTypeChain.pop_back();
150
151 // Register new type or return if already registered
152
1/2
✓ Branch 11 → 12 taken 136967 times.
✗ Branch 11 → 16 not taken.
136967 return TypeRegistry::getOrInsert(newTypeChain);
153 136967 }
154
155 /**
156 * Replace the base type with another one
157 *
158 * @param newBaseType New base type
159 * @return The new type
160 */
161 20750 const Type *Type::replaceBase(const Type *newBaseType) const {
162
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 20750 times.
20750 assert(!typeChain.empty());
163
164 // Create new type
165
1/2
✓ Branch 5 → 6 taken 20750 times.
✗ Branch 5 → 27 not taken.
20750 TypeChain newTypeChain = newBaseType->typeChain;
166
4/4
✓ Branch 7 → 8 taken 1011 times.
✓ Branch 7 → 11 taken 19739 times.
✓ Branch 9 → 10 taken 42 times.
✓ Branch 9 → 11 taken 969 times.
20750 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
167
2/2
✓ Branch 19 → 13 taken 1817 times.
✓ Branch 19 → 20 taken 20750 times.
22567 for (size_t i = 1; i < typeChain.size(); i++)
168
3/4
✓ Branch 13 → 14 taken 42 times.
✓ Branch 13 → 15 taken 1775 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 42 times.
1817 if (!doubleRef || i > 1)
169
2/4
✓ Branch 15 → 16 taken 1775 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 1775 times.
✗ Branch 16 → 25 not taken.
1775 newTypeChain.push_back(typeChain.at(i));
170
171 // Register new type or return if already registered
172
1/2
✓ Branch 20 → 21 taken 20750 times.
✗ Branch 20 → 25 not taken.
41500 return TypeRegistry::getOrInsert(newTypeChain);
173 20750 }
174
175 /**
176 * Remove reference wrapper from the current type
177 *
178 * @return Type without reference wrapper
179 */
180
1/2
✓ Branch 3 → 4 taken 37955 times.
✗ Branch 3 → 6 not taken.
37955 const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; }
181
182 /**
183 * Return the LLVM type for this symbol type
184 *
185 * @param sourceFile Referenced source file
186 * @return Corresponding LLVM type
187 */
188 8404 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
189
2/4
✓ Branch 3 → 4 taken 8404 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 8404 times.
✗ Branch 5 → 7 not taken.
8404 assert(!typeChain.empty() && !is(TY_INVALID));
190 8404 llvm::LLVMContext &context = sourceFile->llvmModule->getContext();
191
192
10/12
✓ Branch 10 → 11 taken 8404 times.
✗ Branch 10 → 163 not taken.
✓ Branch 11 → 12 taken 4350 times.
✓ Branch 11 → 16 taken 4054 times.
✓ Branch 13 → 14 taken 58 times.
✓ Branch 13 → 17 taken 4292 times.
✓ Branch 14 → 15 taken 58 times.
✗ Branch 14 → 163 not taken.
✓ Branch 15 → 16 taken 21 times.
✓ Branch 15 → 17 taken 37 times.
✓ Branch 18 → 19 taken 4075 times.
✓ Branch 18 → 21 taken 4329 times.
8404 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
193 4075 return llvm::PointerType::get(context, 0);
194
195
2/2
✓ Branch 22 → 23 taken 37 times.
✓ Branch 22 → 31 taken 4292 times.
4329 if (isArray()) {
196
1/2
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 37 times.
37 assert(getArraySize() > 0);
197 37 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
198 37 return llvm::ArrayType::get(containedType, getArraySize());
199 }
200
201
1/2
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 4292 times.
4292 assert(!hasAnyGenericParts());
202
203
2/2
✓ Branch 35 → 36 taken 79 times.
✓ Branch 35 → 38 taken 4213 times.
4292 if (is(TY_DOUBLE))
204 79 return llvm::Type::getDoubleTy(context);
205
206
3/4
✓ Branch 38 → 39 taken 4213 times.
✗ Branch 38 → 164 not taken.
✓ Branch 39 → 40 taken 706 times.
✓ Branch 39 → 42 taken 3507 times.
4213 if (isOneOf({TY_INT, TY_ENUM}))
207 706 return llvm::Type::getInt32Ty(context);
208
209
2/2
✓ Branch 43 → 44 taken 68 times.
✓ Branch 43 → 46 taken 3439 times.
3507 if (is(TY_SHORT))
210 68 return llvm::Type::getInt16Ty(context);
211
212
2/2
✓ Branch 47 → 48 taken 429 times.
✓ Branch 47 → 50 taken 3010 times.
3439 if (is(TY_LONG))
213 429 return llvm::Type::getInt64Ty(context);
214
215
3/4
✓ Branch 50 → 51 taken 3010 times.
✗ Branch 50 → 165 not taken.
✓ Branch 51 → 52 taken 387 times.
✓ Branch 51 → 54 taken 2623 times.
3010 if (isOneOf({TY_CHAR, TY_BYTE}))
216 387 return llvm::Type::getInt8Ty(context);
217
218
2/2
✓ Branch 55 → 56 taken 492 times.
✓ Branch 55 → 58 taken 2131 times.
2623 if (is(TY_BOOL))
219 492 return llvm::Type::getInt1Ty(context);
220
221
3/4
✓ Branch 58 → 59 taken 2131 times.
✗ Branch 58 → 166 not taken.
✓ Branch 59 → 60 taken 2052 times.
✓ Branch 59 → 148 taken 79 times.
2131 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
222
1/2
✓ Branch 60 → 61 taken 2052 times.
✗ Branch 60 → 198 not taken.
2052 const Scope *structBodyScope = getBodyScope();
223
2/4
✓ Branch 62 → 63 taken 2052 times.
✗ Branch 62 → 198 not taken.
✓ Branch 63 → 64 taken 2052 times.
✗ Branch 63 → 198 not taken.
2052 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
224
1/2
✓ Branch 64 → 65 taken 2052 times.
✗ Branch 64 → 196 not taken.
2052 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
225
1/2
✗ Branch 67 → 68 not taken.
✓ Branch 67 → 69 taken 2052 times.
2052 assert(structSymbol != nullptr);
226
227 // Collect concrete field types
228 llvm::StructType *structType;
229 2052 std::vector<llvm::Type *> fieldTypes;
230 2052 bool isPacked = false;
231
2/2
✓ Branch 70 → 71 taken 1795 times.
✓ Branch 70 → 132 taken 257 times.
2052 if (is(TY_STRUCT)) { // Struct
232
2/4
✓ Branch 71 → 72 taken 1795 times.
✗ Branch 71 → 187 not taken.
✓ Branch 72 → 73 taken 1795 times.
✗ Branch 72 → 187 not taken.
1795 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
233
1/2
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 75 taken 1795 times.
1795 assert(spiceStruct != nullptr);
234
1/2
✓ Branch 75 → 76 taken 1795 times.
✗ Branch 75 → 187 not taken.
1795 const std::string mangledName = NameMangling::mangleStruct(*spiceStruct);
235
1/2
✓ Branch 77 → 78 taken 1795 times.
✗ Branch 77 → 167 not taken.
1795 structType = llvm::StructType::create(context, mangledName);
236
237
1/2
✓ Branch 78 → 79 taken 1795 times.
✗ Branch 78 → 185 not taken.
1795 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
238
1/2
✓ Branch 79 → 80 taken 1795 times.
✗ Branch 79 → 185 not taken.
1795 fieldTypes.reserve(totalFieldCount);
239
240 // If the struct has no interface types, but a vtable was requested, add another ptr field type
241
2/4
✓ Branch 80 → 81 taken 1795 times.
✗ Branch 80 → 185 not taken.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 1795 times.
1795 assert(structSymbol->declNode->isStructDef());
242
1/2
✓ Branch 83 → 84 taken 1795 times.
✗ Branch 83 → 85 not taken.
1795 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
243
4/4
✓ Branch 90 → 91 taken 1430 times.
✓ Branch 90 → 95 taken 365 times.
✓ Branch 91 → 92 taken 48 times.
✓ Branch 91 → 95 taken 1382 times.
1795 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
244
2/4
✓ Branch 92 → 93 taken 48 times.
✗ Branch 92 → 168 not taken.
✓ Branch 93 → 94 taken 48 times.
✗ Branch 93 → 168 not taken.
48 fieldTypes.push_back(llvm::PointerType::get(context, 0));
245
246 // Collect all field types
247
2/2
✓ Branch 108 → 96 taken 4618 times.
✓ Branch 108 → 109 taken 1795 times.
6413 for (size_t i = 0; i < totalFieldCount; i++) {
248
1/2
✗ Branch 96 → 97 not taken.
✓ Branch 96 → 98 taken 4618 times.
4618 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
249
1/2
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 103 taken 4618 times.
4618 assert(fieldSymbol != nullptr);
250
3/6
✓ Branch 103 → 104 taken 4618 times.
✗ Branch 103 → 169 not taken.
✓ Branch 105 → 106 taken 4618 times.
✗ Branch 105 → 169 not taken.
✓ Branch 106 → 107 taken 4618 times.
✗ Branch 106 → 169 not taken.
4618 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
251 }
252
253 // Check if the struct is declared as packed
254
12/18
✓ Branch 109 → 110 taken 49 times.
✓ Branch 109 → 116 taken 1746 times.
✓ Branch 112 → 113 taken 49 times.
✗ Branch 112 → 170 not taken.
✓ Branch 113 → 114 taken 49 times.
✗ Branch 113 → 170 not taken.
✓ Branch 114 → 115 taken 1 time.
✓ Branch 114 → 116 taken 48 times.
✓ Branch 117 → 118 taken 49 times.
✓ Branch 117 → 119 taken 1746 times.
✓ Branch 119 → 120 taken 49 times.
✓ Branch 119 → 122 taken 1746 times.
✓ Branch 122 → 123 taken 1 time.
✓ Branch 122 → 130 taken 1794 times.
✗ Branch 170 → 171 not taken.
✗ Branch 170 → 172 not taken.
✗ Branch 174 → 175 not taken.
✗ Branch 174 → 177 not taken.
1893 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
255
2/4
✓ Branch 125 → 126 taken 1 time.
✗ Branch 125 → 181 not taken.
✓ Branch 126 → 127 taken 1 time.
✗ Branch 126 → 179 not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
256 1795 } else { // Interface
257
2/4
✓ Branch 132 → 133 taken 257 times.
✗ Branch 132 → 192 not taken.
✓ Branch 133 → 134 taken 257 times.
✗ Branch 133 → 192 not taken.
257 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
258
1/2
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 257 times.
257 assert(spiceInterface != nullptr);
259
1/2
✓ Branch 136 → 137 taken 257 times.
✗ Branch 136 → 192 not taken.
257 const std::string mangledName = NameMangling::mangleInterface(*spiceInterface);
260
1/2
✓ Branch 138 → 139 taken 257 times.
✗ Branch 138 → 188 not taken.
257 structType = llvm::StructType::create(context, mangledName);
261
262
2/4
✓ Branch 139 → 140 taken 257 times.
✗ Branch 139 → 189 not taken.
✓ Branch 140 → 141 taken 257 times.
✗ Branch 140 → 189 not taken.
257 fieldTypes.push_back(llvm::PointerType::get(context, 0));
263 257 }
264
265 // Set field types to struct type
266
1/2
✓ Branch 144 → 145 taken 2052 times.
✗ Branch 144 → 193 not taken.
2052 structType->setBody(fieldTypes, isPacked);
267
268 2052 return structType;
269 2052 }
270
271
2/4
✓ Branch 148 → 149 taken 79 times.
✗ Branch 148 → 199 not taken.
✓ Branch 149 → 150 taken 79 times.
✗ Branch 149 → 155 not taken.
79 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
272 79 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
273
1/2
✓ Branch 152 → 153 taken 79 times.
✗ Branch 152 → 200 not taken.
79 return llvm::StructType::get(context, {ptrTy, ptrTy});
274 }
275
276 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
277 }
278
279 /**
280 * Check if the base type of the current type chain is of a certain super type
281 *
282 * @param superType Super type to check for
283 * @return Applicable or not
284 */
285 480849 bool Type::isBase(SuperType superType) const {
286
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 480849 times.
480849 assert(!typeChain.empty());
287 480849 return typeChain.front().superType == superType;
288 }
289
290 /**
291 * Check if the current type is a primitive type
292 *
293 * @return Primitive type or not
294 */
295
1/2
✓ Branch 2 → 3 taken 121954 times.
✗ Branch 2 → 6 not taken.
121954 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
296
297 /**
298 * Check if the type is an extended primitive type
299 * The definition of extended primitive types contains all primitive types plus the following:
300 * - structs
301 * - interfaces
302 * - functions/procedures
303 *
304 * @return Extended primitive or not
305 */
306
6/8
✓ Branch 2 → 3 taken 97982 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 32879 times.
✓ Branch 3 → 6 taken 65103 times.
✓ Branch 4 → 5 taken 32879 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 22814 times.
✓ Branch 5 → 7 taken 10065 times.
97982 bool Type::isExtendedPrimitive() const { return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}); }
307
308 /**
309 * Check if the current type is a pointer type
310 *
311 * @return Pointer type or not
312 */
313 473381 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
314
315 /**
316 * Check if the current type is a reference type
317 *
318 * @return Reference type or not
319 */
320 1025516 bool Type::isRef() const { return getSuperType() == TY_REF; }
321
322 /**
323 * Check if the current type is an array type
324 *
325 * @return Array type or not
326 */
327 147845 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
328
329 /**
330 * Check if the current type is of the same container type like the other type.
331 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
332 *
333 * @param other Other symbol type
334 * @return Same container type or not
335 */
336 102693 bool Type::isSameContainerTypeAs(const Type *other) const {
337
4/4
✓ Branch 3 → 4 taken 2197 times.
✓ Branch 3 → 7 taken 100496 times.
✓ Branch 5 → 6 taken 1933 times.
✓ Branch 5 → 7 taken 264 times.
102693 const bool bothPtr = isPtr() && other->isPtr();
338
4/4
✓ Branch 9 → 10 taken 4940 times.
✓ Branch 9 → 13 taken 97753 times.
✓ Branch 11 → 12 taken 3841 times.
✓ Branch 11 → 13 taken 1099 times.
102693 const bool bothRef = isRef() && other->isRef();
339
3/4
✓ Branch 15 → 16 taken 66 times.
✓ Branch 15 → 19 taken 102627 times.
✓ Branch 17 → 18 taken 66 times.
✗ Branch 17 → 19 not taken.
102693 const bool bothArray = isArray() && other->isArray();
340
6/6
✓ Branch 20 → 21 taken 100760 times.
✓ Branch 20 → 23 taken 1933 times.
✓ Branch 21 → 22 taken 96919 times.
✓ Branch 21 → 23 taken 3841 times.
✓ Branch 22 → 23 taken 66 times.
✓ Branch 22 → 24 taken 96853 times.
102693 return bothPtr || bothRef || bothArray;
341 }
342
343 /**
344 * Retrieve the base type of the current type
345 *
346 * @return Base type
347 */
348 1270063 const Type *Type::getBase() const {
349
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1270063 times.
1270063 assert(!typeChain.empty());
350
351 // Create new type chain
352
3/6
✓ Branch 9 → 10 taken 1270063 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 1270063 times.
✓ Branch 12 → 14 taken 1270063 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
3810189 const TypeChain newTypeChain = {typeChain.front()};
353
354 // Register new type or return if already registered
355
1/2
✓ Branch 14 → 15 taken 1270063 times.
✗ Branch 14 → 32 not taken.
2540126 return TypeRegistry::getOrInsert(newTypeChain);
356
1/6
✓ Branch 6 → 7 taken 1270063 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.
2540126 }
357
358 /**
359 * Retrieve the same type, but with lambda captures
360 *
361 * @return Type with lambda captures
362 */
363 53 const Type *Type::getWithLambdaCaptures(bool enabled) const {
364
3/6
✓ Branch 2 → 3 taken 53 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 53 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 53 times.
53 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
365
366 // Create new type chain
367
1/2
✓ Branch 6 → 7 taken 53 times.
✗ Branch 6 → 16 not taken.
53 TypeChain newTypeChain = typeChain;
368 53 newTypeChain.front().data.hasCaptures = enabled;
369
370 // Register new type or return if already registered
371
1/2
✓ Branch 8 → 9 taken 53 times.
✗ Branch 8 → 14 not taken.
106 return TypeRegistry::getOrInsert(newTypeChain);
372 53 }
373
374 /**
375 * Retrieve the same type, but with the body scope removed
376 *
377 * @return Type with body scope removed
378 */
379 24161 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
380
3/6
✓ Branch 2 → 3 taken 24161 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 24161 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 24161 times.
24161 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
381
382 // Create new type chain
383
1/2
✓ Branch 6 → 7 taken 24161 times.
✗ Branch 6 → 16 not taken.
24161 TypeChain newTypeChain = typeChain;
384 24161 newTypeChain.front().data.bodyScope = bodyScope;
385
386 // Register new type or return if already registered
387
1/2
✓ Branch 8 → 9 taken 24161 times.
✗ Branch 8 → 14 not taken.
48322 return TypeRegistry::getOrInsert(newTypeChain);
388 24161 }
389
390 /**
391 * Retrieve the same type, but with the given template types
392 *
393 * @return Type with new template types
394 */
395 4058 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
396
2/4
✓ Branch 2 → 3 taken 4058 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 4058 times.
4058 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
397 4058 return getWithBaseTemplateTypes(templateTypes);
398 }
399
400 /**
401 * Retrieve the same type, but with the given base template types
402 *
403 * @return Type with new base template types
404 */
405 8997 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
406
3/6
✓ Branch 2 → 3 taken 8997 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 8997 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 8997 times.
8997 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
407
408 // Create new type chain
409
1/2
✓ Branch 6 → 7 taken 8997 times.
✗ Branch 6 → 17 not taken.
8997 TypeChain newTypeChain = typeChain;
410
1/2
✓ Branch 8 → 9 taken 8997 times.
✗ Branch 8 → 15 not taken.
8997 newTypeChain.front().templateTypes = templateTypes;
411
412 // Register new type or return if already registered
413
1/2
✓ Branch 9 → 10 taken 8997 times.
✗ Branch 9 → 15 not taken.
17994 return TypeRegistry::getOrInsert(newTypeChain);
414 8997 }
415
416 /**
417 * Retrieve the same type, but with the param and return types removed
418 *
419 * @return Type with param and return types removed
420 */
421 14147 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
422
3/6
✓ Branch 2 → 3 taken 14147 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 14147 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 14147 times.
14147 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
423
424 // Create new type chain
425
1/2
✓ Branch 6 → 7 taken 14147 times.
✗ Branch 6 → 17 not taken.
14147 TypeChain newTypeChain = typeChain;
426
1/2
✓ Branch 8 → 9 taken 14147 times.
✗ Branch 8 → 15 not taken.
14147 newTypeChain.front().paramTypes = paramAndReturnTypes;
427
428 // Register new type or return if already registered
429
1/2
✓ Branch 9 → 10 taken 14147 times.
✗ Branch 9 → 15 not taken.
28294 return TypeRegistry::getOrInsert(newTypeChain);
430 14147 }
431
432 /**
433 * Checks if the base type is generic itself or has generic parts in its template types
434 *
435 * @return Contains generic parts or not
436 */
437 374895 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
438
1/2
✓ Branch 2 → 3 taken 374895 times.
✗ Branch 2 → 34 not taken.
374895 const Type *baseType = getBase();
439
440 // Check if the type itself is generic
441
2/2
✓ Branch 4 → 5 taken 66406 times.
✓ Branch 4 → 6 taken 308489 times.
374895 if (baseType->is(TY_GENERIC))
442 66406 return true;
443
444 // Check if the type has generic template types
445
1/2
✓ Branch 7 → 8 taken 308489 times.
✗ Branch 7 → 34 not taken.
308489 const auto templateTypes = baseType->getTemplateTypes();
446
3/4
✓ Branch 8 → 9 taken 308489 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 22244 times.
✓ Branch 9 → 11 taken 286245 times.
373424 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
447 22244 return true;
448
449 // Check param and return types or functions/procedures
450
3/4
✓ Branch 11 → 12 taken 286245 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 490 times.
✓ Branch 12 → 24 taken 285755 times.
286245 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
451
2/4
✓ Branch 13 → 14 taken 490 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 490 times.
✗ Branch 14 → 31 not taken.
490 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
452
3/4
✓ Branch 15 → 16 taken 490 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 45 times.
✓ Branch 16 → 18 taken 445 times.
1271 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
453 45 return true;
454
2/2
✓ Branch 20 → 21 taken 445 times.
✓ Branch 20 → 23 taken 45 times.
490 }
455
456 286200 return false; // Does not have generic parts
457 308489 }
458
459 /**
460 * Retrieve template types of the current type
461 *
462 * @return Vector of template types
463 */
464 402943 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
465
466 /**
467 * Check if the current type is of a certain super type
468 *
469 * @return Applicable or not
470 */
471 7655857 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
472
473 /**
474 * Check if the current type is one of a list of super types
475 *
476 * @return Applicable or not
477 */
478 1611688 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
479 5345830 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
480 }
481
482 /**
483 * Get the name of the symbol type as a string
484 *
485 * @param name Get name of type
486 * @param withSize Include the array size for sized types
487 * @param ignorePublic Ignore any potential public qualifier
488 * @param withAliases Print aliases as is and not decompose them
489 * @return Symbol type name
490 */
491 493403 void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
492 // Loop through all chain elements
493
2/2
✓ Branch 10 → 4 taken 615070 times.
✓ Branch 10 → 11 taken 493403 times.
1108473 for (const TypeChainElement &chainElement : typeChain)
494
2/4
✓ Branch 5 → 6 taken 615070 times.
✗ Branch 5 → 14 not taken.
✓ Branch 6 → 7 taken 615070 times.
✗ Branch 6 → 12 not taken.
615070 name << chainElement.getName(withSize, ignorePublic, withAliases);
495 493403 }
496
497 /**
498 * Get the name of the symbol type as a string
499 *
500 * @param withSize Include the array size for sized types
501 * @param ignorePublic Ignore any potential public qualifier
502 * @param withAliases Print aliases as is and not decompose them
503 * @return Symbol type name
504 */
505 15506 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
506
1/2
✓ Branch 2 → 3 taken 15506 times.
✗ Branch 2 → 11 not taken.
15506 std::stringstream name;
507
1/2
✓ Branch 3 → 4 taken 15506 times.
✗ Branch 3 → 9 not taken.
15506 getName(name, withSize, ignorePublic, withAliases);
508
1/2
✓ Branch 4 → 5 taken 15506 times.
✗ Branch 4 → 9 not taken.
31012 return name.str();
509 15506 }
510
511 /**
512 * Get the return type of function type
513 *
514 * @return Function return type
515 */
516 39 const QualType &Type::getFunctionReturnType() const {
517
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 39 times.
39 assert(is(TY_FUNCTION));
518
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 39 times.
39 assert(!typeChain.back().paramTypes.empty());
519 39 return typeChain.back().paramTypes.front();
520 }
521
522 /**
523 * Get the param types of a function or procedure type
524 *
525 * @return Function param types
526 */
527 140 QualTypeList Type::getFunctionParamTypes() const {
528
2/4
✓ Branch 2 → 3 taken 140 times.
✗ Branch 2 → 20 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 140 times.
140 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
529
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 140 times.
140 if (typeChain.back().paramTypes.empty())
530 return {};
531
1/2
✓ Branch 16 → 17 taken 140 times.
✗ Branch 16 → 21 not taken.
420 return {typeChain.back().paramTypes.begin() + 1, typeChain.back().paramTypes.end()};
532 }
533
534 /**
535 * Check if a function or procedure type has captures
536 *
537 * @return Has captures
538 */
539 145 bool Type::hasLambdaCaptures() const {
540
2/4
✓ Branch 3 → 4 taken 145 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 145 times.
145 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
541 145 return typeChain.front().data.hasCaptures;
542 }
543
544 /**
545 * Get the param and return types of a function or procedure base type
546 *
547 * @return Function param and return types (first is return type, rest are param types)
548 */
549 544 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
550
2/4
✓ Branch 3 → 4 taken 544 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 544 times.
544 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
551 544 return typeChain.front().paramTypes;
552 }
553
554 /**
555 * Check for the matching compatibility of two types.
556 * Useful for struct and function matching as well as assignment type validation and function arg matching.
557 *
558 * @param otherType Type to compare against
559 * @param ignoreArraySize Ignore array sizes
560 * @return Matching or not
561 */
562 127936 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
563 // If the size does not match, it is not equal
564
2/2
✓ Branch 4 → 5 taken 14655 times.
✓ Branch 4 → 6 taken 113281 times.
127936 if (typeChain.size() != otherType->typeChain.size())
565 14655 return false;
566
567 // Compare the elements
568
2/2
✓ Branch 18 → 7 taken 121689 times.
✓ Branch 18 → 19 taken 76473 times.
198162 for (size_t i = 0; i < typeChain.size(); i++) {
569 121689 const TypeChainElement &lhsElement = typeChain.at(i);
570 121689 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
571
572 // Ignore differences in array size
573
5/6
✓ Branch 9 → 10 taken 75748 times.
✓ Branch 9 → 13 taken 45941 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 13 taken 75746 times.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 13 not taken.
121689 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
574 2 continue;
575
576 // Not both types are arrays -> compare them as usual
577
2/2
✓ Branch 14 → 15 taken 36808 times.
✓ Branch 14 → 16 taken 84879 times.
121687 if (lhsElement != rhsElement)
578 36808 return false;
579 }
580
581 76473 return true;
582 }
583
584 /**
585 * Remove pointers / arrays / references if both types have them as far as possible.
586 *
587 * @param typeA Candidate type
588 * @param typeB Requested type
589 */
590 94299 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
591 // Unwrap both types as far as possible
592
2/2
✓ Branch 7 → 3 taken 5693 times.
✓ Branch 7 → 8 taken 94299 times.
99992 while (typeA->isSameContainerTypeAs(typeB)) {
593 5693 typeB = typeB->getContained();
594 5693 typeA = typeA->getContained();
595 }
596 94299 }
597
598 /**
599 * Remove pointers / arrays / references if both types have them as far as possible.
600 * Furthermore, remove reference wrappers if possible.
601 *
602 * @param typeA Candidate type
603 * @param typeB Requested type
604 */
605 93156 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
606 // Remove reference wrapper of front type if required
607
6/6
✓ Branch 3 → 4 taken 39043 times.
✓ Branch 3 → 7 taken 54113 times.
✓ Branch 5 → 6 taken 35209 times.
✓ Branch 5 → 7 taken 3834 times.
✓ Branch 8 → 9 taken 35209 times.
✓ Branch 8 → 11 taken 57947 times.
93156 if (typeA->isRef() && !typeB->isRef())
608 35209 typeA = typeA->removeReferenceWrapper();
609
610 // Remove reference wrapper of requested type if required
611
8/8
✓ Branch 12 → 13 taken 89322 times.
✓ Branch 12 → 19 taken 3834 times.
✓ Branch 14 → 15 taken 3304 times.
✓ Branch 14 → 19 taken 86018 times.
✓ Branch 17 → 18 taken 2746 times.
✓ Branch 17 → 19 taken 558 times.
✓ Branch 20 → 21 taken 2746 times.
✓ Branch 20 → 23 taken 90410 times.
93156 if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC))
612 2746 typeB = typeB->removeReferenceWrapper();
613
614 // Unwrap both types as far as possible
615 93156 unwrapBoth(typeA, typeB);
616 93156 }
617
618 /**
619 * Check if two types have the same type chain depth
620 *
621 * @param typeA First type
622 * @param typeB Second type
623 * @return Same depth or not
624 */
625 20071 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
626 20071 return typeA->typeChain.size() == typeB->typeChain.size();
627 }
628
629 } // namespace spice::compiler
630