GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 98.3% 229 / 1 / 234
Functions: 100.0% 45 / 0 / 45
Branches: 59.7% 270 / 6 / 458

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 5440753 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 5440753 times.
✓ Branch 7 → 9 taken 5440753 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.
16322259 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
25
26
4/12
✓ Branch 4 → 5 taken 1877 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 1877 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 1877 times.
✓ Branch 8 → 10 taken 1877 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.
5631 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
27
28 1211 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
29 1211 const QualTypeList &templateTypes)
30
5/14
✓ Branch 4 → 5 taken 1211 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 1211 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 1211 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 1211 times.
✓ Branch 9 → 11 taken 1211 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.
3633 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
31
32 1552951 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 10631021 SuperType Type::getSuperType() const {
40
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 10631021 times.
10631021 assert(!typeChain.empty());
41 10631021 return typeChain.back().superType;
42 }
43
44 /**
45 * Get the sub type of the current type
46 *
47 * @return Sub type
48 */
49 323922 const std::string &Type::getSubType() const {
50
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 323922 times.
323922 assert(!typeChain.empty());
51
2/4
✓ Branch 5 → 6 taken 323922 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 323922 times.
323922 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
52 323922 return typeChain.back().subType;
53 }
54
55 /**
56 * Get the array size of the current type
57 *
58 * @return Array size
59 */
60 680 unsigned int Type::getArraySize() const {
61
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 680 times.
680 assert(isArray());
62 680 return typeChain.back().data.arraySize;
63 }
64
65 /**
66 * Get the body scope of the current type
67 *
68 * @return Body scope
69 */
70 139698 Scope *Type::getBodyScope() const {
71
2/4
✓ Branch 2 → 3 taken 139698 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 139698 times.
139698 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
72 139698 return typeChain.back().data.bodyScope;
73 }
74
75 /**
76 * Get the pointer type of the current type as a new type
77 *
78 * @param node AST node for error messages
79 * @return Pointer type of the current type
80 */
81 25574 const Type *Type::toPtr(const ASTNode *node) const {
82 // Do not allow pointers of dyn
83
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 12 taken 25572 times.
25574 if (is(TY_DYN))
84
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");
85
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 25572 times.
25572 if (isRef())
86 throw SemanticError(node, REF_POINTERS_ARE_NOT_ALLOWED, "Pointers to references are not allowed. Use pointer instead");
87
88 // Create new type chain
89
1/2
✓ Branch 22 → 23 taken 25572 times.
✗ Branch 22 → 50 not taken.
25572 TypeChain newTypeChain = typeChain;
90
1/2
✓ Branch 23 → 24 taken 25572 times.
✗ Branch 23 → 47 not taken.
25572 newTypeChain.emplace_back(TY_PTR);
91
92 // Register new type or return if already registered
93
1/2
✓ Branch 24 → 25 taken 25572 times.
✗ Branch 24 → 48 not taken.
51144 return TypeRegistry::getOrInsert(newTypeChain);
94 25572 }
95
96 /**
97 * Get the reference type of the current type as a new type
98 *
99 * @param node AST node for error messages
100 * @return Reference type of the current type
101 */
102 13177 const Type *Type::toRef(const ASTNode *node) const {
103 // Do not allow references of dyn
104
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 13177 times.
13177 if (is(TY_DYN))
105 throw SemanticError(node, DYN_REFERENCES_NOT_ALLOWED, "Just use the dyn type without '&' instead");
106 // Do not allow references of references
107
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 13177 times.
13177 if (isRef())
108 throw SemanticError(node, MULTI_REF_NOT_ALLOWED, "References to references are not allowed");
109
110 // Create new type chain
111
1/2
✓ Branch 22 → 23 taken 13177 times.
✗ Branch 22 → 50 not taken.
13177 TypeChain newTypeChain = typeChain;
112
1/2
✓ Branch 23 → 24 taken 13177 times.
✗ Branch 23 → 47 not taken.
13177 newTypeChain.emplace_back(TY_REF);
113
114 // Register new type or return if already registered
115
1/2
✓ Branch 24 → 25 taken 13177 times.
✗ Branch 24 → 48 not taken.
26354 return TypeRegistry::getOrInsert(newTypeChain);
116 13177 }
117
118 /**
119 * Get the array type of the current type as a new type
120 *
121 * @param node AST node for error messages
122 * @param size Size of the array
123 * @param skipDynCheck Skip check if array base type is dyn
124 * @return Array type of the current type
125 */
126 227 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
127 // Do not allow arrays of dyn
128
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)
129
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");
130
131 // Create new type chain
132
1/2
✓ Branch 16 → 17 taken 226 times.
✗ Branch 16 → 36 not taken.
226 TypeChain newTypeChain = typeChain;
133
1/2
✓ Branch 17 → 18 taken 226 times.
✗ Branch 17 → 32 not taken.
226 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
134
135 // Register new type or return if already registered
136
1/2
✓ Branch 18 → 19 taken 226 times.
✗ Branch 18 → 34 not taken.
452 return TypeRegistry::getOrInsert(newTypeChain);
137 226 }
138
139 /**
140 * Retrieve the base type of an array or a pointer
141 *
142 * @return Base type
143 */
144 141850 const Type *Type::getContained() const {
145
2/2
✓ Branch 3 → 4 taken 1606 times.
✓ Branch 3 → 6 taken 140244 times.
141850 if (is(TY_STRING))
146
1/2
✓ Branch 4 → 5 taken 1606 times.
✗ Branch 4 → 18 not taken.
1606 return TypeRegistry::getOrInsert(TY_CHAR);
147
148 // Create new type chain
149
1/2
✓ Branch 6 → 7 taken 140244 times.
✗ Branch 6 → 18 not taken.
140244 TypeChain newTypeChain = typeChain;
150
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 140244 times.
140244 assert(newTypeChain.size() > 1);
151 140244 newTypeChain.pop_back();
152
153 // Register new type or return if already registered
154
1/2
✓ Branch 11 → 12 taken 140244 times.
✗ Branch 11 → 16 not taken.
140244 return TypeRegistry::getOrInsert(newTypeChain);
155 140244 }
156
157 /**
158 * Replace the base type with another one
159 *
160 * @param newBaseType New base type
161 * @return The new type
162 */
163 21432 const Type *Type::replaceBase(const Type *newBaseType) const {
164
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 21432 times.
21432 assert(!typeChain.empty());
165
166 // Create new type
167
1/2
✓ Branch 5 → 6 taken 21432 times.
✗ Branch 5 → 27 not taken.
21432 TypeChain newTypeChain = newBaseType->typeChain;
168
4/4
✓ Branch 7 → 8 taken 1025 times.
✓ Branch 7 → 11 taken 20407 times.
✓ Branch 9 → 10 taken 42 times.
✓ Branch 9 → 11 taken 983 times.
21432 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
169
2/2
✓ Branch 19 → 13 taken 1829 times.
✓ Branch 19 → 20 taken 21432 times.
23261 for (size_t i = 1; i < typeChain.size(); i++)
170
3/4
✓ Branch 13 → 14 taken 42 times.
✓ Branch 13 → 15 taken 1787 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 42 times.
1829 if (!doubleRef || i > 1)
171
2/4
✓ Branch 15 → 16 taken 1787 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 1787 times.
✗ Branch 16 → 25 not taken.
1787 newTypeChain.push_back(typeChain.at(i));
172
173 // Register new type or return if already registered
174
1/2
✓ Branch 20 → 21 taken 21432 times.
✗ Branch 20 → 25 not taken.
42864 return TypeRegistry::getOrInsert(newTypeChain);
175 21432 }
176
177 /**
178 * Remove reference wrapper from the current type
179 *
180 * @return Type without reference wrapper
181 */
182
1/2
✓ Branch 3 → 4 taken 38791 times.
✗ Branch 3 → 6 not taken.
38791 const Type *Type::removeReferenceWrapper() const { return isRef() ? getContained() : this; }
183
184 /**
185 * Return the LLVM type for this symbol type
186 *
187 * @param sourceFile Referenced source file
188 * @return Corresponding LLVM type
189 */
190 8534 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
191
2/4
✓ Branch 3 → 4 taken 8534 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 8534 times.
✗ Branch 5 → 7 not taken.
8534 assert(!typeChain.empty() && !is(TY_INVALID));
192
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 8532 times.
8534 llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context;
193
194
10/12
✓ Branch 11 → 12 taken 8534 times.
✗ Branch 11 → 164 not taken.
✓ Branch 12 → 13 taken 4424 times.
✓ Branch 12 → 17 taken 4110 times.
✓ Branch 14 → 15 taken 58 times.
✓ Branch 14 → 18 taken 4366 times.
✓ Branch 15 → 16 taken 58 times.
✗ Branch 15 → 164 not taken.
✓ Branch 16 → 17 taken 21 times.
✓ Branch 16 → 18 taken 37 times.
✓ Branch 19 → 20 taken 4131 times.
✓ Branch 19 → 22 taken 4403 times.
8534 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
195 4131 return llvm::PointerType::get(context, 0);
196
197
2/2
✓ Branch 23 → 24 taken 37 times.
✓ Branch 23 → 32 taken 4366 times.
4403 if (isArray()) {
198
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 37 times.
37 assert(getArraySize() > 0);
199 37 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
200 37 return llvm::ArrayType::get(containedType, getArraySize());
201 }
202
203
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 4366 times.
4366 assert(!hasAnyGenericParts());
204
205
2/2
✓ Branch 36 → 37 taken 79 times.
✓ Branch 36 → 39 taken 4287 times.
4366 if (is(TY_DOUBLE))
206 79 return llvm::Type::getDoubleTy(context);
207
208
3/4
✓ Branch 39 → 40 taken 4287 times.
✗ Branch 39 → 165 not taken.
✓ Branch 40 → 41 taken 721 times.
✓ Branch 40 → 43 taken 3566 times.
4287 if (isOneOf({TY_INT, TY_ENUM}))
209 721 return llvm::Type::getInt32Ty(context);
210
211
2/2
✓ Branch 44 → 45 taken 68 times.
✓ Branch 44 → 47 taken 3498 times.
3566 if (is(TY_SHORT))
212 68 return llvm::Type::getInt16Ty(context);
213
214
2/2
✓ Branch 48 → 49 taken 437 times.
✓ Branch 48 → 51 taken 3061 times.
3498 if (is(TY_LONG))
215 437 return llvm::Type::getInt64Ty(context);
216
217
3/4
✓ Branch 51 → 52 taken 3061 times.
✗ Branch 51 → 166 not taken.
✓ Branch 52 → 53 taken 393 times.
✓ Branch 52 → 55 taken 2668 times.
3061 if (isOneOf({TY_CHAR, TY_BYTE}))
218 393 return llvm::Type::getInt8Ty(context);
219
220
2/2
✓ Branch 56 → 57 taken 507 times.
✓ Branch 56 → 59 taken 2161 times.
2668 if (is(TY_BOOL))
221 507 return llvm::Type::getInt1Ty(context);
222
223
3/4
✓ Branch 59 → 60 taken 2161 times.
✗ Branch 59 → 167 not taken.
✓ Branch 60 → 61 taken 2082 times.
✓ Branch 60 → 149 taken 79 times.
2161 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
224
1/2
✓ Branch 61 → 62 taken 2082 times.
✗ Branch 61 → 199 not taken.
2082 const Scope *structBodyScope = getBodyScope();
225
2/4
✓ Branch 63 → 64 taken 2082 times.
✗ Branch 63 → 199 not taken.
✓ Branch 64 → 65 taken 2082 times.
✗ Branch 64 → 199 not taken.
2082 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
226
1/2
✓ Branch 65 → 66 taken 2082 times.
✗ Branch 65 → 197 not taken.
2082 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
227
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 2082 times.
2082 assert(structSymbol != nullptr);
228
229 // Collect concrete field types
230 llvm::StructType *structType;
231 2082 std::vector<llvm::Type *> fieldTypes;
232 2082 bool isPacked = false;
233
2/2
✓ Branch 71 → 72 taken 1820 times.
✓ Branch 71 → 133 taken 262 times.
2082 if (is(TY_STRUCT)) { // Struct
234
2/4
✓ Branch 72 → 73 taken 1820 times.
✗ Branch 72 → 188 not taken.
✓ Branch 73 → 74 taken 1820 times.
✗ Branch 73 → 188 not taken.
1820 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
235
1/2
✗ Branch 74 → 75 not taken.
✓ Branch 74 → 76 taken 1820 times.
1820 assert(spiceStruct != nullptr);
236
1/2
✓ Branch 76 → 77 taken 1820 times.
✗ Branch 76 → 188 not taken.
1820 const std::string mangledName = NameMangling::mangleStruct(*spiceStruct);
237
1/2
✓ Branch 78 → 79 taken 1820 times.
✗ Branch 78 → 168 not taken.
1820 structType = llvm::StructType::create(context, mangledName);
238
239
1/2
✓ Branch 79 → 80 taken 1820 times.
✗ Branch 79 → 186 not taken.
1820 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
240
1/2
✓ Branch 80 → 81 taken 1820 times.
✗ Branch 80 → 186 not taken.
1820 fieldTypes.reserve(totalFieldCount);
241
242 // If the struct has no interface types, but a vtable was requested, add another ptr field type
243
2/4
✓ Branch 81 → 82 taken 1820 times.
✗ Branch 81 → 186 not taken.
✗ Branch 82 → 83 not taken.
✓ Branch 82 → 84 taken 1820 times.
1820 assert(structSymbol->declNode->isStructDef());
244
1/2
✓ Branch 84 → 85 taken 1820 times.
✗ Branch 84 → 86 not taken.
1820 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
245
4/4
✓ Branch 91 → 92 taken 1450 times.
✓ Branch 91 → 96 taken 370 times.
✓ Branch 92 → 93 taken 51 times.
✓ Branch 92 → 96 taken 1399 times.
1820 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
246
2/4
✓ Branch 93 → 94 taken 51 times.
✗ Branch 93 → 169 not taken.
✓ Branch 94 → 95 taken 51 times.
✗ Branch 94 → 169 not taken.
51 fieldTypes.push_back(llvm::PointerType::get(context, 0));
247
248 // Collect all field types
249
2/2
✓ Branch 109 → 97 taken 4663 times.
✓ Branch 109 → 110 taken 1820 times.
6483 for (size_t i = 0; i < totalFieldCount; i++) {
250
1/2
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 99 taken 4663 times.
4663 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
251
1/2
✗ Branch 102 → 103 not taken.
✓ Branch 102 → 104 taken 4663 times.
4663 assert(fieldSymbol != nullptr);
252
3/6
✓ Branch 104 → 105 taken 4663 times.
✗ Branch 104 → 170 not taken.
✓ Branch 106 → 107 taken 4663 times.
✗ Branch 106 → 170 not taken.
✓ Branch 107 → 108 taken 4663 times.
✗ Branch 107 → 170 not taken.
4663 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
253 }
254
255 // Check if the struct is declared as packed
256
12/18
✓ Branch 110 → 111 taken 52 times.
✓ Branch 110 → 117 taken 1768 times.
✓ Branch 113 → 114 taken 52 times.
✗ Branch 113 → 171 not taken.
✓ Branch 114 → 115 taken 52 times.
✗ Branch 114 → 171 not taken.
✓ Branch 115 → 116 taken 1 time.
✓ Branch 115 → 117 taken 51 times.
✓ Branch 118 → 119 taken 52 times.
✓ Branch 118 → 120 taken 1768 times.
✓ Branch 120 → 121 taken 52 times.
✓ Branch 120 → 123 taken 1768 times.
✓ Branch 123 → 124 taken 1 time.
✓ Branch 123 → 131 taken 1819 times.
✗ Branch 171 → 172 not taken.
✗ Branch 171 → 173 not taken.
✗ Branch 175 → 176 not taken.
✗ Branch 175 → 178 not taken.
1924 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
257
2/4
✓ Branch 126 → 127 taken 1 time.
✗ Branch 126 → 182 not taken.
✓ Branch 127 → 128 taken 1 time.
✗ Branch 127 → 180 not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
258 1820 } else { // Interface
259
2/4
✓ Branch 133 → 134 taken 262 times.
✗ Branch 133 → 193 not taken.
✓ Branch 134 → 135 taken 262 times.
✗ Branch 134 → 193 not taken.
262 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
260
1/2
✗ Branch 135 → 136 not taken.
✓ Branch 135 → 137 taken 262 times.
262 assert(spiceInterface != nullptr);
261
1/2
✓ Branch 137 → 138 taken 262 times.
✗ Branch 137 → 193 not taken.
262 const std::string mangledName = NameMangling::mangleInterface(*spiceInterface);
262
1/2
✓ Branch 139 → 140 taken 262 times.
✗ Branch 139 → 189 not taken.
262 structType = llvm::StructType::create(context, mangledName);
263
264
2/4
✓ Branch 140 → 141 taken 262 times.
✗ Branch 140 → 190 not taken.
✓ Branch 141 → 142 taken 262 times.
✗ Branch 141 → 190 not taken.
262 fieldTypes.push_back(llvm::PointerType::get(context, 0));
265 262 }
266
267 // Set field types to struct type
268
1/2
✓ Branch 145 → 146 taken 2082 times.
✗ Branch 145 → 194 not taken.
2082 structType->setBody(fieldTypes, isPacked);
269
270 2082 return structType;
271 2082 }
272
273
2/4
✓ Branch 149 → 150 taken 79 times.
✗ Branch 149 → 200 not taken.
✓ Branch 150 → 151 taken 79 times.
✗ Branch 150 → 156 not taken.
79 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
274 79 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
275
1/2
✓ Branch 153 → 154 taken 79 times.
✗ Branch 153 → 201 not taken.
79 return llvm::StructType::get(context, {ptrTy, ptrTy});
276 }
277
278 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
279 }
280
281 /**
282 * Check if the base type of the current type chain is of a certain super type
283 *
284 * @param superType Super type to check for
285 * @return Applicable or not
286 */
287 485282 bool Type::isBase(SuperType superType) const {
288
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 485282 times.
485282 assert(!typeChain.empty());
289 485282 return typeChain.front().superType == superType;
290 }
291
292 /**
293 * Check if the current type is a primitive type
294 *
295 * @return Primitive type or not
296 */
297
1/2
✓ Branch 2 → 3 taken 125750 times.
✗ Branch 2 → 6 not taken.
125750 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
298
299 /**
300 * Check if the type is an extended primitive type
301 * The definition of extended primitive types contains all primitive types plus the following:
302 * - structs
303 * - interfaces
304 * - functions/procedures
305 *
306 * @return Extended primitive or not
307 */
308
6/8
✓ Branch 2 → 3 taken 100241 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 33640 times.
✓ Branch 3 → 6 taken 66601 times.
✓ Branch 4 → 5 taken 33640 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 23311 times.
✓ Branch 5 → 7 taken 10329 times.
100241 bool Type::isExtendedPrimitive() const { return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}); }
309
310 /**
311 * Check if the current type is a pointer type
312 *
313 * @return Pointer type or not
314 */
315 485470 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
316
317 /**
318 * Check if the current type is a reference type
319 *
320 * @return Reference type or not
321 */
322 1052143 bool Type::isRef() const { return getSuperType() == TY_REF; }
323
324 /**
325 * Check if the current type is an array type
326 *
327 * @return Array type or not
328 */
329 152657 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
330
331 /**
332 * Check if the current type is of the same container type like the other type.
333 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
334 *
335 * @param other Other symbol type
336 * @return Same container type or not
337 */
338 105845 bool Type::isSameContainerTypeAs(const Type *other) const {
339
4/4
✓ Branch 3 → 4 taken 2224 times.
✓ Branch 3 → 7 taken 103621 times.
✓ Branch 5 → 6 taken 1957 times.
✓ Branch 5 → 7 taken 267 times.
105845 const bool bothPtr = isPtr() && other->isPtr();
340
4/4
✓ Branch 9 → 10 taken 5215 times.
✓ Branch 9 → 13 taken 100630 times.
✓ Branch 11 → 12 taken 4112 times.
✓ Branch 11 → 13 taken 1103 times.
105845 const bool bothRef = isRef() && other->isRef();
341
3/4
✓ Branch 15 → 16 taken 66 times.
✓ Branch 15 → 19 taken 105779 times.
✓ Branch 17 → 18 taken 66 times.
✗ Branch 17 → 19 not taken.
105845 const bool bothArray = isArray() && other->isArray();
342
6/6
✓ Branch 20 → 21 taken 103888 times.
✓ Branch 20 → 23 taken 1957 times.
✓ Branch 21 → 22 taken 99776 times.
✓ Branch 21 → 23 taken 4112 times.
✓ Branch 22 → 23 taken 66 times.
✓ Branch 22 → 24 taken 99710 times.
105845 return bothPtr || bothRef || bothArray;
343 }
344
345 /**
346 * Retrieve the base type of the current type
347 *
348 * @return Base type
349 */
350 1303607 const Type *Type::getBase() const {
351
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1303607 times.
1303607 assert(!typeChain.empty());
352
353 // Create new type chain
354
3/6
✓ Branch 9 → 10 taken 1303607 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 1303607 times.
✓ Branch 12 → 14 taken 1303607 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
3910821 const TypeChain newTypeChain = {typeChain.front()};
355
356 // Register new type or return if already registered
357
1/2
✓ Branch 14 → 15 taken 1303607 times.
✗ Branch 14 → 32 not taken.
2607214 return TypeRegistry::getOrInsert(newTypeChain);
358
1/6
✓ Branch 6 → 7 taken 1303607 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.
2607214 }
359
360 /**
361 * Retrieve the same type, but with lambda captures
362 *
363 * @return Type with lambda captures
364 */
365 53 const Type *Type::getWithLambdaCaptures(bool enabled) const {
366
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}));
367
368 // Create new type chain
369
1/2
✓ Branch 6 → 7 taken 53 times.
✗ Branch 6 → 16 not taken.
53 TypeChain newTypeChain = typeChain;
370 53 newTypeChain.front().data.hasCaptures = enabled;
371
372 // Register new type or return if already registered
373
1/2
✓ Branch 8 → 9 taken 53 times.
✗ Branch 8 → 14 not taken.
106 return TypeRegistry::getOrInsert(newTypeChain);
374 53 }
375
376 /**
377 * Retrieve the same type, but with the body scope removed
378 *
379 * @return Type with body scope removed
380 */
381 24911 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
382
3/6
✓ Branch 2 → 3 taken 24911 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 24911 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 24911 times.
24911 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
383
384 // Create new type chain
385
1/2
✓ Branch 6 → 7 taken 24911 times.
✗ Branch 6 → 16 not taken.
24911 TypeChain newTypeChain = typeChain;
386 24911 newTypeChain.front().data.bodyScope = bodyScope;
387
388 // Register new type or return if already registered
389
1/2
✓ Branch 8 → 9 taken 24911 times.
✗ Branch 8 → 14 not taken.
49822 return TypeRegistry::getOrInsert(newTypeChain);
390 24911 }
391
392 /**
393 * Retrieve the same type, but with the given template types
394 *
395 * @return Type with new template types
396 */
397 4093 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
398
2/4
✓ Branch 2 → 3 taken 4093 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 4093 times.
4093 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
399 4093 return getWithBaseTemplateTypes(templateTypes);
400 }
401
402 /**
403 * Retrieve the same type, but with the given base template types
404 *
405 * @return Type with new base template types
406 */
407 9269 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
408
3/6
✓ Branch 2 → 3 taken 9269 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 9269 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 9269 times.
9269 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
409
410 // Create new type chain
411
1/2
✓ Branch 6 → 7 taken 9269 times.
✗ Branch 6 → 17 not taken.
9269 TypeChain newTypeChain = typeChain;
412
1/2
✓ Branch 8 → 9 taken 9269 times.
✗ Branch 8 → 15 not taken.
9269 newTypeChain.front().templateTypes = templateTypes;
413
414 // Register new type or return if already registered
415
1/2
✓ Branch 9 → 10 taken 9269 times.
✗ Branch 9 → 15 not taken.
18538 return TypeRegistry::getOrInsert(newTypeChain);
416 9269 }
417
418 /**
419 * Retrieve the same type, but with the param and return types removed
420 *
421 * @return Type with param and return types removed
422 */
423 14460 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
424
3/6
✓ Branch 2 → 3 taken 14460 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 14460 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 14460 times.
14460 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
425
426 // Create new type chain
427
1/2
✓ Branch 6 → 7 taken 14460 times.
✗ Branch 6 → 17 not taken.
14460 TypeChain newTypeChain = typeChain;
428
1/2
✓ Branch 8 → 9 taken 14460 times.
✗ Branch 8 → 15 not taken.
14460 newTypeChain.front().paramTypes = paramAndReturnTypes;
429
430 // Register new type or return if already registered
431
1/2
✓ Branch 9 → 10 taken 14460 times.
✗ Branch 9 → 15 not taken.
28920 return TypeRegistry::getOrInsert(newTypeChain);
432 14460 }
433
434 /**
435 * Checks if the base type is generic itself or has generic parts in its template types
436 *
437 * @return Contains generic parts or not
438 */
439 377039 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
440
1/2
✓ Branch 2 → 3 taken 377039 times.
✗ Branch 2 → 34 not taken.
377039 const Type *baseType = getBase();
441
442 // Check if the type itself is generic
443
2/2
✓ Branch 4 → 5 taken 70101 times.
✓ Branch 4 → 6 taken 306938 times.
377039 if (baseType->is(TY_GENERIC))
444 70101 return true;
445
446 // Check if the type has generic template types
447
1/2
✓ Branch 7 → 8 taken 306938 times.
✗ Branch 7 → 34 not taken.
306938 const auto templateTypes = baseType->getTemplateTypes();
448
3/4
✓ Branch 8 → 9 taken 306938 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 24053 times.
✓ Branch 9 → 11 taken 282885 times.
371801 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
449 24053 return true;
450
451 // Check param and return types or functions/procedures
452
3/4
✓ Branch 11 → 12 taken 282885 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 495 times.
✓ Branch 12 → 24 taken 282390 times.
282885 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
453
2/4
✓ Branch 13 → 14 taken 495 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 495 times.
✗ Branch 14 → 31 not taken.
495 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
454
3/4
✓ Branch 15 → 16 taken 495 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 49 times.
✓ Branch 16 → 18 taken 446 times.
1285 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
455 49 return true;
456
2/2
✓ Branch 20 → 21 taken 446 times.
✓ Branch 20 → 23 taken 49 times.
495 }
457
458 282836 return false; // Does not have generic parts
459 306938 }
460
461 /**
462 * Retrieve template types of the current type
463 *
464 * @return Vector of template types
465 */
466 404199 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
467
468 /**
469 * Check if the current type is of a certain super type
470 *
471 * @return Applicable or not
472 */
473 7897207 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
474
475 /**
476 * Check if the current type is one of a list of super types
477 *
478 * @return Applicable or not
479 */
480 1658425 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
481 5543591 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
482 }
483
484 /**
485 * Get the name of the symbol type as a string
486 *
487 * @param name Get name of type
488 * @param withSize Include the array size for sized types
489 * @param ignorePublic Ignore any potential public qualifier
490 * @param withAliases Print aliases as is and not decompose them
491 * @return Symbol type name
492 */
493 515950 void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
494 // Loop through all chain elements
495
2/2
✓ Branch 10 → 4 taken 639767 times.
✓ Branch 10 → 11 taken 515950 times.
1155717 for (const TypeChainElement &chainElement : typeChain)
496
2/4
✓ Branch 5 → 6 taken 639767 times.
✗ Branch 5 → 14 not taken.
✓ Branch 6 → 7 taken 639767 times.
✗ Branch 6 → 12 not taken.
639767 name << chainElement.getName(withSize, ignorePublic, withAliases);
497 515950 }
498
499 /**
500 * Get the name of the symbol type as a string
501 *
502 * @param withSize Include the array size for sized types
503 * @param ignorePublic Ignore any potential public qualifier
504 * @param withAliases Print aliases as is and not decompose them
505 * @return Symbol type name
506 */
507 15911 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
508
1/2
✓ Branch 2 → 3 taken 15911 times.
✗ Branch 2 → 11 not taken.
15911 std::stringstream name;
509
1/2
✓ Branch 3 → 4 taken 15911 times.
✗ Branch 3 → 9 not taken.
15911 getName(name, withSize, ignorePublic, withAliases);
510
1/2
✓ Branch 4 → 5 taken 15911 times.
✗ Branch 4 → 9 not taken.
31822 return name.str();
511 15911 }
512
513 /**
514 * Get the return type of function type
515 *
516 * @return Function return type
517 */
518 39 const QualType &Type::getFunctionReturnType() const {
519
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 39 times.
39 assert(is(TY_FUNCTION));
520
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 39 times.
39 assert(!typeChain.back().paramTypes.empty());
521 39 return typeChain.back().paramTypes.front();
522 }
523
524 /**
525 * Get the param types of a function or procedure type
526 *
527 * @return Function param types
528 */
529 140 QualTypeList Type::getFunctionParamTypes() const {
530
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}));
531
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 140 times.
140 if (typeChain.back().paramTypes.empty())
532 return {};
533
1/2
✓ Branch 16 → 17 taken 140 times.
✗ Branch 16 → 21 not taken.
420 return {typeChain.back().paramTypes.begin() + 1, typeChain.back().paramTypes.end()};
534 }
535
536 /**
537 * Check if a function or procedure type has captures
538 *
539 * @return Has captures
540 */
541 145 bool Type::hasLambdaCaptures() const {
542
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}));
543 145 return typeChain.front().data.hasCaptures;
544 }
545
546 /**
547 * Get the param and return types of a function or procedure base type
548 *
549 * @return Function param and return types (first is return type, rest are param types)
550 */
551 549 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
552
2/4
✓ Branch 3 → 4 taken 549 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 549 times.
549 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
553 549 return typeChain.front().paramTypes;
554 }
555
556 /**
557 * Check for the matching compatibility of two types.
558 * Useful for struct and function matching as well as assignment type validation and function arg matching.
559 *
560 * @param otherType Type to compare against
561 * @param ignoreArraySize Ignore array sizes
562 * @return Matching or not
563 */
564 131125 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
565 // If the size does not match, it is not equal
566
2/2
✓ Branch 4 → 5 taken 15008 times.
✓ Branch 4 → 6 taken 116117 times.
131125 if (typeChain.size() != otherType->typeChain.size())
567 15008 return false;
568
569 // Compare the elements
570
2/2
✓ Branch 18 → 7 taken 124636 times.
✓ Branch 18 → 19 taken 78354 times.
202990 for (size_t i = 0; i < typeChain.size(); i++) {
571 124636 const TypeChainElement &lhsElement = typeChain.at(i);
572 124636 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
573
574 // Ignore differences in array size
575
5/6
✓ Branch 9 → 10 taken 78007 times.
✓ Branch 9 → 13 taken 46629 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 13 taken 78005 times.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 13 not taken.
124636 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
576 2 continue;
577
578 // Not both types are arrays -> compare them as usual
579
2/2
✓ Branch 14 → 15 taken 37763 times.
✓ Branch 14 → 16 taken 86871 times.
124634 if (lhsElement != rhsElement)
580 37763 return false;
581 }
582
583 78354 return true;
584 }
585
586 /**
587 * Remove pointers / arrays / references if both types have them as far as possible.
588 *
589 * @param typeA Candidate type
590 * @param typeB Requested type
591 */
592 97111 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
593 // Unwrap both types as far as possible
594
2/2
✓ Branch 7 → 3 taken 5988 times.
✓ Branch 7 → 8 taken 97111 times.
103099 while (typeA->isSameContainerTypeAs(typeB)) {
595 5988 typeB = typeB->getContained();
596 5988 typeA = typeA->getContained();
597 }
598 97111 }
599
600 /**
601 * Remove pointers / arrays / references if both types have them as far as possible.
602 * Furthermore, remove reference wrappers if possible.
603 *
604 * @param typeA Candidate type
605 * @param typeB Requested type
606 */
607 95964 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
608 // Remove reference wrapper of front type if required
609
6/6
✓ Branch 3 → 4 taken 40043 times.
✓ Branch 3 → 7 taken 55921 times.
✓ Branch 5 → 6 taken 35938 times.
✓ Branch 5 → 7 taken 4105 times.
✓ Branch 8 → 9 taken 35938 times.
✓ Branch 8 → 11 taken 60026 times.
95964 if (typeA->isRef() && !typeB->isRef())
610 35938 typeA = typeA->removeReferenceWrapper();
611
612 // Remove reference wrapper of requested type if required
613
8/8
✓ Branch 12 → 13 taken 91859 times.
✓ Branch 12 → 19 taken 4105 times.
✓ Branch 14 → 15 taken 3416 times.
✓ Branch 14 → 19 taken 88443 times.
✓ Branch 17 → 18 taken 2853 times.
✓ Branch 17 → 19 taken 563 times.
✓ Branch 20 → 21 taken 2853 times.
✓ Branch 20 → 23 taken 93111 times.
95964 if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC))
614 2853 typeB = typeB->removeReferenceWrapper();
615
616 // Unwrap both types as far as possible
617 95964 unwrapBoth(typeA, typeB);
618 95964 }
619
620 /**
621 * Check if two types have the same type chain depth
622 *
623 * @param typeA First type
624 * @param typeB Second type
625 * @return Same depth or not
626 */
627 20601 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
628 20601 return typeA->typeChain.size() == typeB->typeChain.size();
629 }
630
631 } // namespace spice::compiler
632