GCC Code Coverage Report


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

src/symboltablebuilder/Type.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "Type.h"
4
5 #include <utility>
6
7 #include <SourceFile.h>
8 #include <ast/Attributes.h>
9 #include <driver/Driver.h>
10 #include <exception/CompilerError.h>
11 #include <exception/SemanticError.h>
12 #include <global/GlobalResourceManager.h>
13 #include <global/TypeRegistry.h>
14 #include <irgenerator/NameMangling.h>
15 #include <model/Struct.h>
16 #include <symboltablebuilder/Scope.h>
17 #include <symboltablebuilder/SymbolTableEntry.h>
18
19 #include <llvm/IR/Module.h>
20 #include <llvm/IR/Type.h>
21
22 namespace spice::compiler {
23
24
3/10
✓ Branch 5 → 6 taken 1557038 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 1557038 times.
✓ Branch 7 → 9 taken 1557038 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.
4671114 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
25
26
4/12
✓ Branch 4 → 5 taken 1991 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 1991 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 1991 times.
✓ Branch 8 → 10 taken 1991 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.
5973 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
27
28 1349 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
29 1349 const QualTypeList &templateTypes)
30
5/14
✓ Branch 4 → 5 taken 1349 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 1349 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 1349 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 1349 times.
✓ Branch 9 → 11 taken 1349 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.
4047 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
31
32 1747038 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 11324049 SuperType Type::getSuperType() const {
40
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11324049 times.
11324049 assert(!typeChain.empty());
41 11324049 return typeChain.back().superType;
42 }
43
44 /**
45 * Get the sub type of the current type
46 *
47 * @return Sub type
48 */
49 336975 const std::string &Type::getSubType() const {
50
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 336975 times.
336975 assert(!typeChain.empty());
51
2/4
✓ Branch 5 → 6 taken 336975 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 336975 times.
336975 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
52 336975 return typeChain.back().subType;
53 }
54
55 /**
56 * Get the array size of the current type
57 *
58 * @return Array size
59 */
60 721 unsigned int Type::getArraySize() const {
61
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 721 times.
721 assert(isArray());
62 721 return typeChain.back().data.arraySize;
63 }
64
65 /**
66 * Get the body scope of the current type
67 *
68 * @return Body scope
69 */
70 168052 Scope *Type::getBodyScope() const {
71
2/4
✓ Branch 2 → 3 taken 168052 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 168052 times.
168052 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
72 168052 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 27629 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 27627 times.
27629 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 27627 times.
27627 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 27627 times.
✗ Branch 22 → 50 not taken.
27627 TypeChain newTypeChain = typeChain;
90
1/2
✓ Branch 23 → 24 taken 27627 times.
✗ Branch 23 → 47 not taken.
27627 newTypeChain.emplace_back(TY_PTR);
91
92 // Register new type or return if already registered
93
1/2
✓ Branch 24 → 25 taken 27627 times.
✗ Branch 24 → 48 not taken.
55254 return TypeRegistry::getOrInsert(newTypeChain);
94 27627 }
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 13889 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 13889 times.
13889 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 13889 times.
13889 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 13889 times.
✗ Branch 22 → 50 not taken.
13889 TypeChain newTypeChain = typeChain;
112
1/2
✓ Branch 23 → 24 taken 13889 times.
✗ Branch 23 → 47 not taken.
13889 newTypeChain.emplace_back(TY_REF);
113
114 // Register new type or return if already registered
115
1/2
✓ Branch 24 → 25 taken 13889 times.
✗ Branch 24 → 48 not taken.
27778 return TypeRegistry::getOrInsert(newTypeChain);
116 13889 }
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 239 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 160 times.
✓ Branch 2 → 6 taken 79 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 159 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 16 taken 238 times.
239 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 238 times.
✗ Branch 16 → 36 not taken.
238 TypeChain newTypeChain = typeChain;
133
1/2
✓ Branch 17 → 18 taken 238 times.
✗ Branch 17 → 32 not taken.
238 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 238 times.
✗ Branch 18 → 34 not taken.
476 return TypeRegistry::getOrInsert(newTypeChain);
137 238 }
138
139 /**
140 * Retrieve the base type of an array or a pointer
141 *
142 * @return Base type
143 */
144 154628 const Type *Type::getContained() const {
145
2/2
✓ Branch 3 → 4 taken 1690 times.
✓ Branch 3 → 6 taken 152938 times.
154628 if (is(TY_STRING))
146
1/2
✓ Branch 4 → 5 taken 1690 times.
✗ Branch 4 → 18 not taken.
1690 return TypeRegistry::getOrInsert(TY_CHAR);
147
148 // Create new type chain
149
1/2
✓ Branch 6 → 7 taken 152938 times.
✗ Branch 6 → 18 not taken.
152938 TypeChain newTypeChain = typeChain;
150
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 152938 times.
152938 assert(newTypeChain.size() > 1);
151 152938 newTypeChain.pop_back();
152
153 // Register new type or return if already registered
154
1/2
✓ Branch 11 → 12 taken 152938 times.
✗ Branch 11 → 16 not taken.
152938 return TypeRegistry::getOrInsert(newTypeChain);
155 152938 }
156
157 /**
158 * Replace the base type with another one
159 *
160 * @param newBaseType New base type
161 * @return The new type
162 */
163 23029 const Type *Type::replaceBase(const Type *newBaseType) const {
164
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 23029 times.
23029 assert(!typeChain.empty());
165
166 // Create new type
167
1/2
✓ Branch 5 → 6 taken 23029 times.
✗ Branch 5 → 27 not taken.
23029 TypeChain newTypeChain = newBaseType->typeChain;
168
4/4
✓ Branch 7 → 8 taken 1097 times.
✓ Branch 7 → 11 taken 21932 times.
✓ Branch 9 → 10 taken 40 times.
✓ Branch 9 → 11 taken 1057 times.
23029 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
169
2/2
✓ Branch 19 → 13 taken 2089 times.
✓ Branch 19 → 20 taken 23029 times.
25118 for (size_t i = 1; i < typeChain.size(); i++)
170
3/4
✓ Branch 13 → 14 taken 40 times.
✓ Branch 13 → 15 taken 2049 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 40 times.
2089 if (!doubleRef || i > 1)
171
2/4
✓ Branch 15 → 16 taken 2049 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 2049 times.
✗ Branch 16 → 25 not taken.
2049 newTypeChain.push_back(typeChain.at(i));
172
173 // Register new type or return if already registered
174
1/2
✓ Branch 20 → 21 taken 23029 times.
✗ Branch 20 → 25 not taken.
46058 return TypeRegistry::getOrInsert(newTypeChain);
175 23029 }
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 41011 times.
✗ Branch 3 → 6 not taken.
41011 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 9259 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
191
2/4
✓ Branch 3 → 4 taken 9259 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 9259 times.
✗ Branch 5 → 7 not taken.
9259 assert(!typeChain.empty() && !is(TY_INVALID));
192
2/2
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 9257 times.
9259 llvm::LLVMContext &context = sourceFile->cliOptions.useLTO ? sourceFile->resourceManager.ltoContext : sourceFile->context;
193
194
10/12
✓ Branch 11 → 12 taken 9259 times.
✗ Branch 11 → 165 not taken.
✓ Branch 12 → 13 taken 4789 times.
✓ Branch 12 → 17 taken 4470 times.
✓ Branch 14 → 15 taken 63 times.
✓ Branch 14 → 18 taken 4726 times.
✓ Branch 15 → 16 taken 63 times.
✗ Branch 15 → 165 not taken.
✓ Branch 16 → 17 taken 25 times.
✓ Branch 16 → 18 taken 38 times.
✓ Branch 19 → 20 taken 4495 times.
✓ Branch 19 → 22 taken 4764 times.
9259 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
195 4495 return llvm::PointerType::get(context, 0);
196
197
2/2
✓ Branch 23 → 24 taken 38 times.
✓ Branch 23 → 32 taken 4726 times.
4764 if (isArray()) {
198
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 38 times.
38 assert(getArraySize() > 0);
199 38 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
200 38 return llvm::ArrayType::get(containedType, getArraySize());
201 }
202
203
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 4726 times.
4726 assert(!hasAnyGenericParts());
204
205
2/2
✓ Branch 36 → 37 taken 84 times.
✓ Branch 36 → 39 taken 4642 times.
4726 if (is(TY_DOUBLE))
206 84 return llvm::Type::getDoubleTy(context);
207
208
3/4
✓ Branch 39 → 40 taken 4642 times.
✗ Branch 39 → 166 not taken.
✓ Branch 40 → 41 taken 765 times.
✓ Branch 40 → 43 taken 3877 times.
4642 if (isOneOf({TY_INT, TY_ENUM}))
209 765 return llvm::Type::getInt32Ty(context);
210
211
2/2
✓ Branch 44 → 45 taken 68 times.
✓ Branch 44 → 47 taken 3809 times.
3877 if (is(TY_SHORT))
212 68 return llvm::Type::getInt16Ty(context);
213
214
2/2
✓ Branch 48 → 49 taken 461 times.
✓ Branch 48 → 51 taken 3348 times.
3809 if (is(TY_LONG))
215 461 return llvm::Type::getInt64Ty(context);
216
217
3/4
✓ Branch 51 → 52 taken 3348 times.
✗ Branch 51 → 167 not taken.
✓ Branch 52 → 53 taken 424 times.
✓ Branch 52 → 55 taken 2924 times.
3348 if (isOneOf({TY_CHAR, TY_BYTE}))
218 424 return llvm::Type::getInt8Ty(context);
219
220
2/2
✓ Branch 56 → 57 taken 531 times.
✓ Branch 56 → 59 taken 2393 times.
2924 if (is(TY_BOOL))
221 531 return llvm::Type::getInt1Ty(context);
222
223
3/4
✓ Branch 59 → 60 taken 2393 times.
✗ Branch 59 → 168 not taken.
✓ Branch 60 → 61 taken 2308 times.
✓ Branch 60 → 150 taken 85 times.
2393 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
224
1/2
✓ Branch 61 → 62 taken 2308 times.
✗ Branch 61 → 197 not taken.
2308 const Scope *structBodyScope = getBodyScope();
225
2/4
✓ Branch 63 → 64 taken 2308 times.
✗ Branch 63 → 197 not taken.
✓ Branch 64 → 65 taken 2308 times.
✗ Branch 64 → 197 not taken.
2308 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
226
1/2
✓ Branch 65 → 66 taken 2308 times.
✗ Branch 65 → 195 not taken.
2308 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
227
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 2308 times.
2308 assert(structSymbol != nullptr);
228
229 // Collect concrete field types
230 2308 std::string mangledName;
231 2308 std::vector<llvm::Type *> fieldTypes;
232 2308 bool isPacked = false;
233
2/2
✓ Branch 72 → 73 taken 2021 times.
✓ Branch 72 → 132 taken 287 times.
2308 if (is(TY_STRUCT)) { // Struct
234
2/4
✓ Branch 73 → 74 taken 2021 times.
✗ Branch 73 → 191 not taken.
✓ Branch 74 → 75 taken 2021 times.
✗ Branch 74 → 191 not taken.
2021 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
235
1/2
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 2021 times.
2021 assert(spiceStruct != nullptr);
236
1/2
✓ Branch 77 → 78 taken 2021 times.
✗ Branch 77 → 169 not taken.
2021 mangledName = NameMangling::mangleStruct(*spiceStruct);
237
238
1/2
✓ Branch 80 → 81 taken 2021 times.
✗ Branch 80 → 191 not taken.
2021 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
239
1/2
✓ Branch 81 → 82 taken 2021 times.
✗ Branch 81 → 191 not taken.
2021 fieldTypes.reserve(totalFieldCount);
240
241 // If the struct has no interface types, but a vtable was requested, add another ptr field type
242
2/4
✓ Branch 82 → 83 taken 2021 times.
✗ Branch 82 → 191 not taken.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 2021 times.
2021 assert(structSymbol->declNode->isStructDef());
243
1/2
✓ Branch 85 → 86 taken 2021 times.
✗ Branch 85 → 87 not taken.
2021 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
244
4/4
✓ Branch 92 → 93 taken 1589 times.
✓ Branch 92 → 97 taken 432 times.
✓ Branch 93 → 94 taken 51 times.
✓ Branch 93 → 97 taken 1538 times.
2021 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
245
2/4
✓ Branch 94 → 95 taken 51 times.
✗ Branch 94 → 170 not taken.
✓ Branch 95 → 96 taken 51 times.
✗ Branch 95 → 170 not taken.
51 fieldTypes.push_back(llvm::PointerType::get(context, 0));
246
247 // Collect all field types
248
2/2
✓ Branch 110 → 98 taken 5131 times.
✓ Branch 110 → 111 taken 2021 times.
7152 for (size_t i = 0; i < totalFieldCount; i++) {
249
1/2
✗ Branch 98 → 99 not taken.
✓ Branch 98 → 100 taken 5131 times.
5131 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
250
1/2
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 105 taken 5131 times.
5131 assert(fieldSymbol != nullptr);
251
3/6
✓ Branch 105 → 106 taken 5131 times.
✗ Branch 105 → 171 not taken.
✓ Branch 107 → 108 taken 5131 times.
✗ Branch 107 → 171 not taken.
✓ Branch 108 → 109 taken 5131 times.
✗ Branch 108 → 171 not taken.
5131 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
252 }
253
254 // Check if the struct is declared as packed
255
12/18
✓ Branch 111 → 112 taken 52 times.
✓ Branch 111 → 118 taken 1969 times.
✓ Branch 114 → 115 taken 52 times.
✗ Branch 114 → 172 not taken.
✓ Branch 115 → 116 taken 52 times.
✗ Branch 115 → 172 not taken.
✓ Branch 116 → 117 taken 1 time.
✓ Branch 116 → 118 taken 51 times.
✓ Branch 119 → 120 taken 52 times.
✓ Branch 119 → 121 taken 1969 times.
✓ Branch 121 → 122 taken 52 times.
✓ Branch 121 → 124 taken 1969 times.
✓ Branch 124 → 125 taken 1 time.
✓ Branch 124 → 142 taken 2020 times.
✗ Branch 172 → 173 not taken.
✗ Branch 172 → 174 not taken.
✗ Branch 176 → 177 not taken.
✗ Branch 176 → 179 not taken.
2125 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
256
2/4
✓ Branch 127 → 128 taken 1 time.
✗ Branch 127 → 183 not taken.
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 181 not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
257 } else { // Interface
258
2/4
✓ Branch 132 → 133 taken 287 times.
✗ Branch 132 → 191 not taken.
✓ Branch 133 → 134 taken 287 times.
✗ Branch 133 → 191 not taken.
287 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
259
1/2
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 287 times.
287 assert(spiceInterface != nullptr);
260
1/2
✓ Branch 136 → 137 taken 287 times.
✗ Branch 136 → 187 not taken.
287 mangledName = NameMangling::mangleInterface(*spiceInterface);
261
262 // vtable pointer
263
2/4
✓ Branch 139 → 140 taken 287 times.
✗ Branch 139 → 188 not taken.
✓ Branch 140 → 141 taken 287 times.
✗ Branch 140 → 188 not taken.
287 fieldTypes.push_back(llvm::PointerType::get(context, 0));
264 }
265
266
1/2
✓ Branch 144 → 145 taken 2308 times.
✗ Branch 144 → 189 not taken.
2308 return llvm::StructType::create(context, fieldTypes, mangledName, isPacked);
267 2308 }
268
269
2/4
✓ Branch 150 → 151 taken 85 times.
✗ Branch 150 → 198 not taken.
✓ Branch 151 → 152 taken 85 times.
✗ Branch 151 → 157 not taken.
85 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
270 85 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
271
1/2
✓ Branch 154 → 155 taken 85 times.
✗ Branch 154 → 199 not taken.
85 return llvm::StructType::get(context, {ptrTy, ptrTy});
272 }
273
274 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(true, true, true)); // GCOVR_EXCL_LINE
275 }
276
277 /**
278 * Check if the base type of the current type chain is of a certain super type
279 *
280 * @param superType Super type to check for
281 * @return Applicable or not
282 */
283 564725 bool Type::isBase(SuperType superType) const {
284
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 564725 times.
564725 assert(!typeChain.empty());
285 564725 return typeChain.front().superType == superType;
286 }
287
288 /**
289 * Check if the current type is a primitive type
290 *
291 * @return Primitive type or not
292 */
293
1/2
✓ Branch 2 → 3 taken 136737 times.
✗ Branch 2 → 6 not taken.
136737 bool Type::isPrimitive() const { return isOneOf({TY_DOUBLE, TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_STRING, TY_BOOL}); }
294
295 /**
296 * Check if the type is an extended primitive type
297 * The definition of extended primitive types contains all primitive types plus the following:
298 * - structs
299 * - interfaces
300 * - functions/procedures
301 *
302 * @return Extended primitive or not
303 */
304
6/8
✓ Branch 2 → 3 taken 109289 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 37835 times.
✓ Branch 3 → 6 taken 71454 times.
✓ Branch 4 → 5 taken 37835 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 26258 times.
✓ Branch 5 → 7 taken 11577 times.
109289 bool Type::isExtendedPrimitive() const { return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}); }
305
306 /**
307 * Check if the current type is a pointer type
308 *
309 * @return Pointer type or not
310 */
311 517835 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
312
313 /**
314 * Check if the current type is a reference type
315 *
316 * @return Reference type or not
317 */
318 1126457 bool Type::isRef() const { return getSuperType() == TY_REF; }
319
320 /**
321 * Check if the current type is an array type
322 *
323 * @return Array type or not
324 */
325 162466 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
326
327 /**
328 * Check if the current type is of the same container type like the other type.
329 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
330 *
331 * @param other Other symbol type
332 * @return Same container type or not
333 */
334 111831 bool Type::isSameContainerTypeAs(const Type *other) const {
335
4/4
✓ Branch 3 → 4 taken 2455 times.
✓ Branch 3 → 7 taken 109376 times.
✓ Branch 5 → 6 taken 2164 times.
✓ Branch 5 → 7 taken 291 times.
111831 const bool bothPtr = isPtr() && other->isPtr();
336
4/4
✓ Branch 9 → 10 taken 5542 times.
✓ Branch 9 → 13 taken 106289 times.
✓ Branch 11 → 12 taken 4345 times.
✓ Branch 11 → 13 taken 1197 times.
111831 const bool bothRef = isRef() && other->isRef();
337
3/4
✓ Branch 15 → 16 taken 70 times.
✓ Branch 15 → 19 taken 111761 times.
✓ Branch 17 → 18 taken 70 times.
✗ Branch 17 → 19 not taken.
111831 const bool bothArray = isArray() && other->isArray();
338
6/6
✓ Branch 20 → 21 taken 109667 times.
✓ Branch 20 → 23 taken 2164 times.
✓ Branch 21 → 22 taken 105322 times.
✓ Branch 21 → 23 taken 4345 times.
✓ Branch 22 → 23 taken 70 times.
✓ Branch 22 → 24 taken 105252 times.
111831 return bothPtr || bothRef || bothArray;
339 }
340
341 /**
342 * Retrieve the base type of the current type
343 *
344 * @return Base type
345 */
346 1476243 const Type *Type::getBase() const {
347
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1476243 times.
1476243 assert(!typeChain.empty());
348
349 // Create new type chain
350
3/6
✓ Branch 9 → 10 taken 1476243 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 1476243 times.
✓ Branch 12 → 14 taken 1476243 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
4428729 const TypeChain newTypeChain = {typeChain.front()};
351
352 // Register new type or return if already registered
353
1/2
✓ Branch 14 → 15 taken 1476243 times.
✗ Branch 14 → 32 not taken.
2952486 return TypeRegistry::getOrInsert(newTypeChain);
354
1/6
✓ Branch 6 → 7 taken 1476243 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.
2952486 }
355
356 /**
357 * Retrieve the same type, but with lambda captures
358 *
359 * @return Type with lambda captures
360 */
361 40 const Type *Type::getWithLambdaCaptures(bool enabled) const {
362
3/6
✓ Branch 2 → 3 taken 40 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 40 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 40 times.
40 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
363
364 // Create new type chain
365
1/2
✓ Branch 6 → 7 taken 40 times.
✗ Branch 6 → 16 not taken.
40 TypeChain newTypeChain = typeChain;
366 40 newTypeChain.front().data.hasCaptures = enabled;
367
368 // Register new type or return if already registered
369
1/2
✓ Branch 8 → 9 taken 40 times.
✗ Branch 8 → 14 not taken.
80 return TypeRegistry::getOrInsert(newTypeChain);
370 40 }
371
372 /**
373 * Retrieve the same type, but with the body scope removed
374 *
375 * @return Type with body scope removed
376 */
377 27106 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
378
3/6
✓ Branch 2 → 3 taken 27106 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 27106 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 27106 times.
27106 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
379
380 // Create new type chain
381
1/2
✓ Branch 6 → 7 taken 27106 times.
✗ Branch 6 → 16 not taken.
27106 TypeChain newTypeChain = typeChain;
382 27106 newTypeChain.front().data.bodyScope = bodyScope;
383
384 // Register new type or return if already registered
385
1/2
✓ Branch 8 → 9 taken 27106 times.
✗ Branch 8 → 14 not taken.
54212 return TypeRegistry::getOrInsert(newTypeChain);
386 27106 }
387
388 /**
389 * Retrieve the same type, but with the given template types
390 *
391 * @return Type with new template types
392 */
393 4712 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
394
2/4
✓ Branch 2 → 3 taken 4712 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 4712 times.
4712 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
395 4712 return getWithBaseTemplateTypes(templateTypes);
396 }
397
398 /**
399 * Retrieve the same type, but with the given base template types
400 *
401 * @return Type with new base template types
402 */
403 10476 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
404
3/6
✓ Branch 2 → 3 taken 10476 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 10476 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 10476 times.
10476 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
405
406 // Create new type chain
407
1/2
✓ Branch 6 → 7 taken 10476 times.
✗ Branch 6 → 17 not taken.
10476 TypeChain newTypeChain = typeChain;
408
1/2
✓ Branch 8 → 9 taken 10476 times.
✗ Branch 8 → 15 not taken.
10476 newTypeChain.front().templateTypes = templateTypes;
409
410 // Register new type or return if already registered
411
1/2
✓ Branch 9 → 10 taken 10476 times.
✗ Branch 9 → 15 not taken.
20952 return TypeRegistry::getOrInsert(newTypeChain);
412 10476 }
413
414 /**
415 * Retrieve the same type, but with the param and return types removed
416 *
417 * @return Type with param and return types removed
418 */
419 15452 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
420
3/6
✓ Branch 2 → 3 taken 15452 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 15452 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 15452 times.
15452 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
421
422 // Create new type chain
423
1/2
✓ Branch 6 → 7 taken 15452 times.
✗ Branch 6 → 17 not taken.
15452 TypeChain newTypeChain = typeChain;
424
1/2
✓ Branch 8 → 9 taken 15452 times.
✗ Branch 8 → 15 not taken.
15452 newTypeChain.front().paramTypes = paramAndReturnTypes;
425
426 // Register new type or return if already registered
427
1/2
✓ Branch 9 → 10 taken 15452 times.
✗ Branch 9 → 15 not taken.
30904 return TypeRegistry::getOrInsert(newTypeChain);
428 15452 }
429
430 /**
431 * Checks if the base type is generic itself or has generic parts in its template types
432 *
433 * @return Contains generic parts or not
434 */
435 414755 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
436
1/2
✓ Branch 2 → 3 taken 414755 times.
✗ Branch 2 → 34 not taken.
414755 const Type *baseType = getBase();
437
438 // Check if the type itself is generic
439
2/2
✓ Branch 4 → 5 taken 75412 times.
✓ Branch 4 → 6 taken 339343 times.
414755 if (baseType->is(TY_GENERIC))
440 75412 return true;
441
442 // Check if the type has generic template types
443
1/2
✓ Branch 7 → 8 taken 339343 times.
✗ Branch 7 → 34 not taken.
339343 const auto templateTypes = baseType->getTemplateTypes();
444
3/4
✓ Branch 8 → 9 taken 339343 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 25978 times.
✓ Branch 9 → 11 taken 313365 times.
420414 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
445 25978 return true;
446
447 // Check param and return types or functions/procedures
448
3/4
✓ Branch 11 → 12 taken 313365 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 378 times.
✓ Branch 12 → 24 taken 312987 times.
313365 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
449
2/4
✓ Branch 13 → 14 taken 378 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 378 times.
✗ Branch 14 → 31 not taken.
378 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
450
3/4
✓ Branch 15 → 16 taken 378 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 55 times.
✓ Branch 16 → 18 taken 323 times.
1131 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
451 55 return true;
452
2/2
✓ Branch 20 → 21 taken 323 times.
✓ Branch 20 → 23 taken 55 times.
378 }
453
454 313310 return false; // Does not have generic parts
455 339343 }
456
457 /**
458 * Retrieve template types of the current type
459 *
460 * @return Vector of template types
461 */
462 444771 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
463
464 /**
465 * Check if the current type is of a certain super type
466 *
467 * @return Applicable or not
468 */
469 8352085 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
470
471 /**
472 * Check if the current type is one of a list of super types
473 *
474 * @return Applicable or not
475 */
476 1799999 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
477 5968487 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
478 }
479
480 /**
481 * Get the name of the symbol type as a string
482 *
483 * @param name Get name of type
484 * @param withSize Include the array size for sized types
485 * @param ignorePublic Ignore any potential public qualifier
486 * @param withAliases Print aliases as is and not decompose them
487 * @return Symbol type name
488 */
489 604463 void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic, bool withAliases) const {
490 // Loop through all chain elements
491
2/2
✓ Branch 10 → 4 taken 752228 times.
✓ Branch 10 → 11 taken 604463 times.
1356691 for (const TypeChainElement &chainElement : typeChain)
492
2/4
✓ Branch 5 → 6 taken 752228 times.
✗ Branch 5 → 14 not taken.
✓ Branch 6 → 7 taken 752228 times.
✗ Branch 6 → 12 not taken.
752228 name << chainElement.getName(withSize, ignorePublic, withAliases);
493 604463 }
494
495 /**
496 * Get the name of the symbol type as a string
497 *
498 * @param withSize Include the array size for sized types
499 * @param ignorePublic Ignore any potential public qualifier
500 * @param withAliases Print aliases as is and not decompose them
501 * @return Symbol type name
502 */
503 17578 std::string Type::getName(bool withSize, bool ignorePublic, bool withAliases) const {
504
1/2
✓ Branch 2 → 3 taken 17578 times.
✗ Branch 2 → 11 not taken.
17578 std::stringstream name;
505
1/2
✓ Branch 3 → 4 taken 17578 times.
✗ Branch 3 → 9 not taken.
17578 getName(name, withSize, ignorePublic, withAliases);
506
1/2
✓ Branch 4 → 5 taken 17578 times.
✗ Branch 4 → 9 not taken.
35156 return name.str();
507 17578 }
508
509 /**
510 * Get the return type of function type
511 *
512 * @return Function return type
513 */
514 39 const QualType &Type::getFunctionReturnType() const {
515
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 39 times.
39 assert(is(TY_FUNCTION));
516
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 39 times.
39 assert(!typeChain.back().paramTypes.empty());
517 39 return typeChain.back().paramTypes.front();
518 }
519
520 /**
521 * Get the param types of a function or procedure type
522 *
523 * @return Function param types
524 */
525 138 QualTypeList Type::getFunctionParamTypes() const {
526
2/4
✓ Branch 2 → 3 taken 138 times.
✗ Branch 2 → 20 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 138 times.
138 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
527
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 138 times.
138 if (typeChain.back().paramTypes.empty())
528 return {};
529
1/2
✓ Branch 16 → 17 taken 138 times.
✗ Branch 16 → 21 not taken.
414 return {typeChain.back().paramTypes.begin() + 1, typeChain.back().paramTypes.end()};
530 }
531
532 /**
533 * Check if a function or procedure type has captures
534 *
535 * @return Has captures
536 */
537 151 bool Type::hasLambdaCaptures() const {
538
2/4
✓ Branch 3 → 4 taken 151 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 151 times.
151 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
539 151 return typeChain.front().data.hasCaptures;
540 }
541
542 /**
543 * Get the param and return types of a function or procedure base type
544 *
545 * @return Function param and return types (first is return type, rest are param types)
546 */
547 440 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
548
2/4
✓ Branch 3 → 4 taken 440 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 440 times.
440 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
549 440 return typeChain.front().paramTypes;
550 }
551
552 /**
553 * Check for the matching compatibility of two types.
554 * Useful for struct and function matching as well as assignment type validation and function arg matching.
555 *
556 * @param otherType Type to compare against
557 * @param ignoreArraySize Ignore array sizes
558 * @return Matching or not
559 */
560 139133 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
561 // If the size does not match, it is not equal
562
2/2
✓ Branch 4 → 5 taken 15848 times.
✓ Branch 4 → 6 taken 123285 times.
139133 if (typeChain.size() != otherType->typeChain.size())
563 15848 return false;
564
565 // Compare the elements
566
2/2
✓ Branch 18 → 7 taken 133191 times.
✓ Branch 18 → 19 taken 83025 times.
216216 for (size_t i = 0; i < typeChain.size(); i++) {
567 133191 const TypeChainElement &lhsElement = typeChain.at(i);
568 133191 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
569
570 // Ignore differences in array size
571
5/6
✓ Branch 9 → 10 taken 82089 times.
✓ Branch 9 → 13 taken 51102 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 13 taken 82087 times.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 13 not taken.
133191 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
572 2 continue;
573
574 // Not both types are arrays -> compare them as usual
575
2/2
✓ Branch 14 → 15 taken 40260 times.
✓ Branch 14 → 16 taken 92929 times.
133189 if (lhsElement != rhsElement)
576 40260 return false;
577 }
578
579 83025 return true;
580 }
581
582 /**
583 * Remove pointers / arrays / references if both types have them as far as possible.
584 *
585 * @param typeA Candidate type
586 * @param typeB Requested type
587 */
588 102449 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
589 // Unwrap both types as far as possible
590
2/2
✓ Branch 7 → 3 taken 6407 times.
✓ Branch 7 → 8 taken 102449 times.
108856 while (typeA->isSameContainerTypeAs(typeB)) {
591 6407 typeB = typeB->getContained();
592 6407 typeA = typeA->getContained();
593 }
594 102449 }
595
596 /**
597 * Remove pointers / arrays / references if both types have them as far as possible.
598 * Furthermore, remove reference wrappers if possible.
599 *
600 * @param typeA Candidate type
601 * @param typeB Requested type
602 */
603 101199 void Type::unwrapBothWithRefWrappers(const Type *&typeA, const Type *&typeB) {
604 // Remove reference wrapper of front type if required
605
6/6
✓ Branch 3 → 4 taken 42497 times.
✓ Branch 3 → 7 taken 58702 times.
✓ Branch 5 → 6 taken 38162 times.
✓ Branch 5 → 7 taken 4335 times.
✓ Branch 8 → 9 taken 38162 times.
✓ Branch 8 → 11 taken 63037 times.
101199 if (typeA->isRef() && !typeB->isRef())
606 38162 typeA = typeA->removeReferenceWrapper();
607
608 // Remove reference wrapper of requested type if required
609
8/8
✓ Branch 12 → 13 taken 96864 times.
✓ Branch 12 → 19 taken 4335 times.
✓ Branch 14 → 15 taken 3450 times.
✓ Branch 14 → 19 taken 93414 times.
✓ Branch 17 → 18 taken 2849 times.
✓ Branch 17 → 19 taken 601 times.
✓ Branch 20 → 21 taken 2849 times.
✓ Branch 20 → 23 taken 98350 times.
101199 if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC))
610 2849 typeB = typeB->removeReferenceWrapper();
611
612 // Unwrap both types as far as possible
613 101199 unwrapBoth(typeA, typeB);
614 101199 }
615
616 /**
617 * Check if two types have the same type chain depth
618 *
619 * @param typeA First type
620 * @param typeB Second type
621 * @return Same depth or not
622 */
623 22110 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
624 22110 return typeA->typeChain.size() == typeB->typeChain.size();
625 }
626
627 } // namespace spice::compiler
628