GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/Type.cpp
Date: 2025-03-05 01:50:32
Exec Total Coverage
Lines: 226 231 97.8%
Functions: 44 44 100.0%
Branches: 266 450 59.1%

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 0 (5→6) taken 4176610 times.
✗ Branch 1 (5→11) not taken.
✓ Branch 2 (7→8) taken 4176610 times.
✓ Branch 3 (7→9) taken 4176610 times.
✗ Branch 4 (12→13) not taken.
✗ Branch 5 (12→14) not taken.
✗ Branch 6 (15→16) not taken.
✗ Branch 7 (15→19) not taken.
✗ Branch 8 (17→18) not taken.
✗ Branch 9 (17→19) not taken.
12529830 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
23
24
4/12
✓ Branch 0 (4→5) taken 1518 times.
✗ Branch 1 (4→19) not taken.
✓ Branch 2 (6→7) taken 1518 times.
✗ Branch 3 (6→13) not taken.
✓ Branch 4 (8→9) taken 1518 times.
✓ Branch 5 (8→10) taken 1518 times.
✗ Branch 6 (14→15) not taken.
✗ Branch 7 (14→16) not taken.
✗ Branch 8 (20→21) not taken.
✗ Branch 9 (20→24) not taken.
✗ Branch 10 (22→23) not taken.
✗ Branch 11 (22→24) not taken.
4554 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
25
26 1003 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
27 1003 const QualTypeList &templateTypes)
28
5/14
✓ Branch 0 (4→5) taken 1003 times.
✗ Branch 1 (4→24) not taken.
✓ Branch 2 (5→6) taken 1003 times.
✗ Branch 3 (5→21) not taken.
✓ Branch 4 (7→8) taken 1003 times.
✗ Branch 5 (7→15) not taken.
✓ Branch 6 (9→10) taken 1003 times.
✓ Branch 7 (9→11) taken 1003 times.
✗ Branch 8 (16→17) not taken.
✗ Branch 9 (16→18) not taken.
✗ Branch 10 (25→26) not taken.
✗ Branch 11 (25→29) not taken.
✗ Branch 12 (27→28) not taken.
✗ Branch 13 (27→29) not taken.
3009 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
29
30 1107912 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 7261355 SuperType Type::getSuperType() const {
38
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 7261355 times.
7261355 assert(!typeChain.empty());
39 7261355 return typeChain.back().superType;
40 }
41
42 /**
43 * Get the sub type of the current type
44 *
45 * @return Sub type
46 */
47 191401 const std::string &Type::getSubType() const {
48
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 191401 times.
191401 assert(!typeChain.empty());
49
2/4
✓ Branch 0 (5→6) taken 191401 times.
✗ Branch 1 (5→11) not taken.
✗ Branch 2 (6→7) not taken.
✓ Branch 3 (6→8) taken 191401 times.
191401 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
50 191401 return typeChain.back().subType;
51 }
52
53 /**
54 * Get the array size of the current type
55 *
56 * @return Array size
57 */
58 561 unsigned int Type::getArraySize() const {
59
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 561 times.
561 assert(isArray());
60 561 return typeChain.back().data.arraySize;
61 }
62
63 /**
64 * Get the body scope of the current type
65 *
66 * @return Body scope
67 */
68 122690 Scope *Type::getBodyScope() const {
69
2/4
✓ Branch 0 (2→3) taken 122690 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 122690 times.
122690 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
70 122690 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 12956 const Type *Type::toPtr(const ASTNode *node) const {
80 // Do not allow pointers of dyn
81
2/2
✓ Branch 0 (3→4) taken 2 times.
✓ Branch 1 (3→12) taken 12954 times.
12956 if (is(TY_DYN))
82
2/4
✓ Branch 0 (7→8) taken 2 times.
✗ Branch 1 (7→32) not taken.
✓ Branch 2 (8→9) taken 2 times.
✗ Branch 3 (8→29) not taken.
6 throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead");
83
1/2
✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→22) taken 12954 times.
12954 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 0 (22→23) taken 12954 times.
✗ Branch 1 (22→50) not taken.
12954 TypeChain newTypeChain = typeChain;
88
1/2
✓ Branch 0 (23→24) taken 12954 times.
✗ Branch 1 (23→47) not taken.
12954 newTypeChain.emplace_back(TY_PTR);
89
90 // Register new type or return if already registered
91
1/2
✓ Branch 0 (24→25) taken 12954 times.
✗ Branch 1 (24→48) not taken.
25908 return TypeRegistry::getOrInsert(newTypeChain);
92 12954 }
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 10388 const Type *Type::toRef(const ASTNode *node) const {
101 // Do not allow references of dyn
102
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→12) taken 10388 times.
10388 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 0 (13→14) not taken.
✓ Branch 1 (13→22) taken 10388 times.
10388 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 0 (22→23) taken 10388 times.
✗ Branch 1 (22→50) not taken.
10388 TypeChain newTypeChain = typeChain;
110
1/2
✓ Branch 0 (23→24) taken 10388 times.
✗ Branch 1 (23→47) not taken.
10388 newTypeChain.emplace_back(TY_REF);
111
112 // Register new type or return if already registered
113
1/2
✓ Branch 0 (24→25) taken 10388 times.
✗ Branch 1 (24→48) not taken.
20776 return TypeRegistry::getOrInsert(newTypeChain);
114 10388 }
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 219 const Type *Type::toArr(const ASTNode *node, unsigned int size, bool skipDynCheck) const {
125 // Do not allow arrays of dyn
126
6/6
✓ Branch 0 (2→3) taken 147 times.
✓ Branch 1 (2→6) taken 72 times.
✓ Branch 2 (4→5) taken 1 times.
✓ Branch 3 (4→6) taken 146 times.
✓ Branch 4 (7→8) taken 1 times.
✓ Branch 5 (7→16) taken 218 times.
219 if (!skipDynCheck && typeChain.back().superType == TY_DYN)
127
2/4
✓ Branch 0 (11→12) taken 1 times.
✗ Branch 1 (11→26) not taken.
✓ Branch 2 (12→13) taken 1 times.
✗ Branch 3 (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 0 (16→17) taken 218 times.
✗ Branch 1 (16→36) not taken.
218 TypeChain newTypeChain = typeChain;
131
1/2
✓ Branch 0 (17→18) taken 218 times.
✗ Branch 1 (17→32) not taken.
218 newTypeChain.emplace_back(TY_ARRAY, TypeChainElementData{.arraySize = size});
132
133 // Register new type or return if already registered
134
1/2
✓ Branch 0 (18→19) taken 218 times.
✗ Branch 1 (18→34) not taken.
436 return TypeRegistry::getOrInsert(newTypeChain);
135 218 }
136
137 /**
138 * Retrieve the base type of an array or a pointer
139 *
140 * @return Base type
141 */
142 91517 const Type *Type::getContained() const {
143
2/2
✓ Branch 0 (3→4) taken 1326 times.
✓ Branch 1 (3→6) taken 90191 times.
91517 if (is(TY_STRING))
144
1/2
✓ Branch 0 (4→5) taken 1326 times.
✗ Branch 1 (4→18) not taken.
1326 return TypeRegistry::getOrInsert(TY_CHAR);
145
146 // Create new type chain
147
1/2
✓ Branch 0 (6→7) taken 90191 times.
✗ Branch 1 (6→18) not taken.
90191 TypeChain newTypeChain = typeChain;
148
1/2
✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 90191 times.
90191 assert(newTypeChain.size() > 1);
149 90191 newTypeChain.pop_back();
150
151 // Register new type or return if already registered
152
1/2
✓ Branch 0 (11→12) taken 90191 times.
✗ Branch 1 (11→16) not taken.
90191 return TypeRegistry::getOrInsert(newTypeChain);
153 90191 }
154
155 /**
156 * Replace the base type with another one
157 *
158 * @param newBaseType New base type
159 * @return The new type
160 */
161 8539 const Type *Type::replaceBase(const Type *newBaseType) const {
162
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 8539 times.
8539 assert(!typeChain.empty());
163
164 // Create new type
165
1/2
✓ Branch 0 (5→6) taken 8539 times.
✗ Branch 1 (5→27) not taken.
8539 TypeChain newTypeChain = newBaseType->typeChain;
166
4/4
✓ Branch 0 (7→8) taken 464 times.
✓ Branch 1 (7→11) taken 8075 times.
✓ Branch 2 (9→10) taken 14 times.
✓ Branch 3 (9→11) taken 450 times.
8539 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
167
2/2
✓ Branch 0 (19→13) taken 1356 times.
✓ Branch 1 (19→20) taken 8539 times.
9895 for (size_t i = 1; i < typeChain.size(); i++)
168
3/4
✓ Branch 0 (13→14) taken 14 times.
✓ Branch 1 (13→15) taken 1342 times.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→17) taken 14 times.
1356 if (!doubleRef || i > 1)
169
2/4
✓ Branch 0 (15→16) taken 1342 times.
✗ Branch 1 (15→25) not taken.
✓ Branch 2 (16→17) taken 1342 times.
✗ Branch 3 (16→25) not taken.
1342 newTypeChain.push_back(typeChain.at(i));
170
171 // Register new type or return if already registered
172
1/2
✓ Branch 0 (20→21) taken 8539 times.
✗ Branch 1 (20→25) not taken.
17078 return TypeRegistry::getOrInsert(newTypeChain);
173 8539 }
174
175 /**
176 * Remove reference wrapper from the current type
177 *
178 * @return Type without reference wrapper
179 */
180
1/2
✓ Branch 0 (3→4) taken 30723 times.
✗ Branch 1 (3→6) not taken.
30723 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 6218 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
189
2/4
✓ Branch 0 (3→4) taken 6218 times.
✗ Branch 1 (3→7) not taken.
✓ Branch 2 (5→6) taken 6218 times.
✗ Branch 3 (5→7) not taken.
6218 assert(!typeChain.empty() && !is(TY_INVALID));
190 6218 llvm::LLVMContext &context = sourceFile->llvmModule->getContext();
191
192
10/12
✓ Branch 0 (10→11) taken 6218 times.
✗ Branch 1 (10→163) not taken.
✓ Branch 2 (11→12) taken 3467 times.
✓ Branch 3 (11→16) taken 2751 times.
✓ Branch 4 (13→14) taken 57 times.
✓ Branch 5 (13→17) taken 3410 times.
✓ Branch 6 (14→15) taken 57 times.
✗ Branch 7 (14→163) not taken.
✓ Branch 8 (15→16) taken 21 times.
✓ Branch 9 (15→17) taken 36 times.
✓ Branch 10 (18→19) taken 2772 times.
✓ Branch 11 (18→21) taken 3446 times.
6218 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
193 2772 return llvm::PointerType::get(context, 0);
194
195
2/2
✓ Branch 0 (22→23) taken 36 times.
✓ Branch 1 (22→31) taken 3410 times.
3446 if (isArray()) {
196
1/2
✗ Branch 0 (24→25) not taken.
✓ Branch 1 (24→26) taken 36 times.
36 assert(getArraySize() > 0);
197 36 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
198 36 return llvm::ArrayType::get(containedType, getArraySize());
199 }
200
201
1/2
✗ Branch 0 (32→33) not taken.
✓ Branch 1 (32→34) taken 3410 times.
3410 assert(!hasAnyGenericParts());
202
203
2/2
✓ Branch 0 (35→36) taken 77 times.
✓ Branch 1 (35→38) taken 3333 times.
3410 if (is(TY_DOUBLE))
204 77 return llvm::Type::getDoubleTy(context);
205
206
3/4
✓ Branch 0 (38→39) taken 3333 times.
✗ Branch 1 (38→164) not taken.
✓ Branch 2 (39→40) taken 542 times.
✓ Branch 3 (39→42) taken 2791 times.
3333 if (isOneOf({TY_INT, TY_ENUM}))
207 542 return llvm::Type::getInt32Ty(context);
208
209
2/2
✓ Branch 0 (43→44) taken 68 times.
✓ Branch 1 (43→46) taken 2723 times.
2791 if (is(TY_SHORT))
210 68 return llvm::Type::getInt16Ty(context);
211
212
2/2
✓ Branch 0 (47→48) taken 356 times.
✓ Branch 1 (47→50) taken 2367 times.
2723 if (is(TY_LONG))
213 356 return llvm::Type::getInt64Ty(context);
214
215
3/4
✓ Branch 0 (50→51) taken 2367 times.
✗ Branch 1 (50→165) not taken.
✓ Branch 2 (51→52) taken 259 times.
✓ Branch 3 (51→54) taken 2108 times.
2367 if (isOneOf({TY_CHAR, TY_BYTE}))
216 259 return llvm::Type::getInt8Ty(context);
217
218
2/2
✓ Branch 0 (55→56) taken 411 times.
✓ Branch 1 (55→58) taken 1697 times.
2108 if (is(TY_BOOL))
219 411 return llvm::Type::getInt1Ty(context);
220
221
3/4
✓ Branch 0 (58→59) taken 1697 times.
✗ Branch 1 (58→166) not taken.
✓ Branch 2 (59→60) taken 1624 times.
✓ Branch 3 (59→148) taken 73 times.
1697 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
222
1/2
✓ Branch 0 (60→61) taken 1624 times.
✗ Branch 1 (60→198) not taken.
1624 const Scope *structBodyScope = getBodyScope();
223
2/4
✓ Branch 0 (62→63) taken 1624 times.
✗ Branch 1 (62→198) not taken.
✓ Branch 2 (63→64) taken 1624 times.
✗ Branch 3 (63→198) not taken.
1624 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
224
1/2
✓ Branch 0 (64→65) taken 1624 times.
✗ Branch 1 (64→196) not taken.
1624 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
225
1/2
✗ Branch 0 (67→68) not taken.
✓ Branch 1 (67→69) taken 1624 times.
1624 assert(structSymbol != nullptr);
226
227 // Collect concrete field types
228 llvm::StructType *structType;
229 1624 std::vector<llvm::Type *> fieldTypes;
230 1624 bool isPacked = false;
231
2/2
✓ Branch 0 (70→71) taken 1446 times.
✓ Branch 1 (70→132) taken 178 times.
1624 if (is(TY_STRUCT)) { // Struct
232
2/4
✓ Branch 0 (71→72) taken 1446 times.
✗ Branch 1 (71→187) not taken.
✓ Branch 2 (72→73) taken 1446 times.
✗ Branch 3 (72→187) not taken.
1446 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
233
1/2
✗ Branch 0 (73→74) not taken.
✓ Branch 1 (73→75) taken 1446 times.
1446 assert(spiceStruct != nullptr);
234
1/2
✓ Branch 0 (75→76) taken 1446 times.
✗ Branch 1 (75→187) not taken.
1446 const std::string mangledName = NameMangling::mangleStruct(*spiceStruct);
235
1/2
✓ Branch 0 (77→78) taken 1446 times.
✗ Branch 1 (77→167) not taken.
1446 structType = llvm::StructType::create(context, mangledName);
236
237
1/2
✓ Branch 0 (78→79) taken 1446 times.
✗ Branch 1 (78→185) not taken.
1446 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
238
1/2
✓ Branch 0 (79→80) taken 1446 times.
✗ Branch 1 (79→185) not taken.
1446 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 0 (80→81) taken 1446 times.
✗ Branch 1 (80→185) not taken.
✗ Branch 2 (81→82) not taken.
✓ Branch 3 (81→83) taken 1446 times.
1446 assert(structSymbol->declNode->isStructDef());
242
1/2
✓ Branch 0 (83→84) taken 1446 times.
✗ Branch 1 (83→85) not taken.
1446 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
243
4/4
✓ Branch 0 (90→91) taken 1164 times.
✓ Branch 1 (90→95) taken 282 times.
✓ Branch 2 (91→92) taken 39 times.
✓ Branch 3 (91→95) taken 1125 times.
1446 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
244
2/4
✓ Branch 0 (92→93) taken 39 times.
✗ Branch 1 (92→168) not taken.
✓ Branch 2 (93→94) taken 39 times.
✗ Branch 3 (93→168) not taken.
39 fieldTypes.push_back(llvm::PointerType::get(context, 0));
245
246 // Collect all field types
247
2/2
✓ Branch 0 (108→96) taken 3754 times.
✓ Branch 1 (108→109) taken 1446 times.
5200 for (size_t i = 0; i < totalFieldCount; i++) {
248
1/2
✗ Branch 0 (96→97) not taken.
✓ Branch 1 (96→98) taken 3754 times.
3754 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
249
1/2
✗ Branch 0 (101→102) not taken.
✓ Branch 1 (101→103) taken 3754 times.
3754 assert(fieldSymbol != nullptr);
250
3/6
✓ Branch 0 (103→104) taken 3754 times.
✗ Branch 1 (103→169) not taken.
✓ Branch 2 (105→106) taken 3754 times.
✗ Branch 3 (105→169) not taken.
✓ Branch 4 (106→107) taken 3754 times.
✗ Branch 5 (106→169) not taken.
3754 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
251 }
252
253 // Check if the struct is declared as packed
254
12/18
✓ Branch 0 (109→110) taken 40 times.
✓ Branch 1 (109→116) taken 1406 times.
✓ Branch 2 (112→113) taken 40 times.
✗ Branch 3 (112→170) not taken.
✓ Branch 4 (113→114) taken 40 times.
✗ Branch 5 (113→170) not taken.
✓ Branch 6 (114→115) taken 1 times.
✓ Branch 7 (114→116) taken 39 times.
✓ Branch 8 (117→118) taken 40 times.
✓ Branch 9 (117→119) taken 1406 times.
✓ Branch 10 (119→120) taken 40 times.
✓ Branch 11 (119→122) taken 1406 times.
✓ Branch 12 (122→123) taken 1 times.
✓ Branch 13 (122→130) taken 1445 times.
✗ Branch 14 (170→171) not taken.
✗ Branch 15 (170→172) not taken.
✗ Branch 16 (174→175) not taken.
✗ Branch 17 (174→177) not taken.
1526 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
255
2/4
✓ Branch 0 (125→126) taken 1 times.
✗ Branch 1 (125→181) not taken.
✓ Branch 2 (126→127) taken 1 times.
✗ Branch 3 (126→179) not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
256 1446 } else { // Interface
257
2/4
✓ Branch 0 (132→133) taken 178 times.
✗ Branch 1 (132→192) not taken.
✓ Branch 2 (133→134) taken 178 times.
✗ Branch 3 (133→192) not taken.
178 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
258
1/2
✗ Branch 0 (134→135) not taken.
✓ Branch 1 (134→136) taken 178 times.
178 assert(spiceInterface != nullptr);
259
1/2
✓ Branch 0 (136→137) taken 178 times.
✗ Branch 1 (136→192) not taken.
178 const std::string mangledName = NameMangling::mangleInterface(*spiceInterface);
260
1/2
✓ Branch 0 (138→139) taken 178 times.
✗ Branch 1 (138→188) not taken.
178 structType = llvm::StructType::create(context, mangledName);
261
262
2/4
✓ Branch 0 (139→140) taken 178 times.
✗ Branch 1 (139→189) not taken.
✓ Branch 2 (140→141) taken 178 times.
✗ Branch 3 (140→189) not taken.
178 fieldTypes.push_back(llvm::PointerType::get(context, 0));
263 178 }
264
265 // Set field types to struct type
266
1/2
✓ Branch 0 (144→145) taken 1624 times.
✗ Branch 1 (144→193) not taken.
1624 structType->setBody(fieldTypes, isPacked);
267
268 1624 return structType;
269 1624 }
270
271
2/4
✓ Branch 0 (148→149) taken 73 times.
✗ Branch 1 (148→199) not taken.
✓ Branch 2 (149→150) taken 73 times.
✗ Branch 3 (149→155) not taken.
73 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
272 73 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
273
1/2
✓ Branch 0 (152→153) taken 73 times.
✗ Branch 1 (152→200) not taken.
73 return llvm::StructType::get(context, {ptrTy, ptrTy});
274 }
275
276 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(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 560153 bool Type::isBase(SuperType superType) const {
286
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 560153 times.
560153 assert(!typeChain.empty());
287 560153 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 0 (2→3) taken 91216 times.
✗ Branch 1 (2→6) not taken.
91216 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 72361 bool Type::isExtendedPrimitive() const {
307
6/8
✓ Branch 0 (2→3) taken 72361 times.
✗ Branch 1 (2→11) not taken.
✓ Branch 2 (3→4) taken 21724 times.
✓ Branch 3 (3→6) taken 50637 times.
✓ Branch 4 (4→5) taken 21724 times.
✗ Branch 5 (4→11) not taken.
✓ Branch 6 (5→6) taken 19374 times.
✓ Branch 7 (5→7) taken 2350 times.
72361 return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE});
308 }
309
310 /**
311 * Check if the current type is a pointer type
312 *
313 * @return Pointer type or not
314 */
315 228449 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 780230 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 116879 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 80427 bool Type::isSameContainerTypeAs(const Type *other) const {
339
4/4
✓ Branch 0 (3→4) taken 1700 times.
✓ Branch 1 (3→7) taken 78727 times.
✓ Branch 2 (5→6) taken 1546 times.
✓ Branch 3 (5→7) taken 154 times.
80427 const bool bothPtr = isPtr() && other->isPtr();
340
4/4
✓ Branch 0 (9→10) taken 3328 times.
✓ Branch 1 (9→13) taken 77099 times.
✓ Branch 2 (11→12) taken 3229 times.
✓ Branch 3 (11→13) taken 99 times.
80427 const bool bothRef = isRef() && other->isRef();
341
3/4
✓ Branch 0 (15→16) taken 52 times.
✓ Branch 1 (15→19) taken 80375 times.
✓ Branch 2 (17→18) taken 52 times.
✗ Branch 3 (17→19) not taken.
80427 const bool bothArray = isArray() && other->isArray();
342
6/6
✓ Branch 0 (20→21) taken 78881 times.
✓ Branch 1 (20→23) taken 1546 times.
✓ Branch 2 (21→22) taken 75652 times.
✓ Branch 3 (21→23) taken 3229 times.
✓ Branch 4 (22→23) taken 52 times.
✓ Branch 5 (22→24) taken 75600 times.
80427 return bothPtr || bothRef || bothArray;
343 }
344
345 /**
346 * Retrieve the base type of the current type
347 *
348 * @return Base type
349 */
350 947650 const Type *Type::getBase() const {
351
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 947650 times.
947650 assert(!typeChain.empty());
352
353 // Create new type chain
354
3/6
✓ Branch 0 (9→10) taken 947650 times.
✗ Branch 1 (9→19) not taken.
✓ Branch 2 (12→13) taken 947650 times.
✓ Branch 3 (12→14) taken 947650 times.
✗ Branch 4 (23→24) not taken.
✗ Branch 5 (23→25) not taken.
2842950 const TypeChain newTypeChain = {typeChain.front()};
355
356 // Register new type or return if already registered
357
1/2
✓ Branch 0 (14→15) taken 947650 times.
✗ Branch 1 (14→32) not taken.
1895300 return TypeRegistry::getOrInsert(newTypeChain);
358
1/6
✓ Branch 0 (6→7) taken 947650 times.
✗ Branch 1 (6→26) not taken.
✗ Branch 2 (26→27) not taken.
✗ Branch 3 (26→30) not taken.
✗ Branch 4 (28→29) not taken.
✗ Branch 5 (28→30) not taken.
1895300 }
359
360 /**
361 * Retrieve the same type, but with lambda captures
362 *
363 * @return Type with lambda captures
364 */
365 45 const Type *Type::getWithLambdaCaptures(bool enabled) const {
366
3/6
✓ Branch 0 (2→3) taken 45 times.
✗ Branch 1 (2→16) not taken.
✓ Branch 2 (3→4) taken 45 times.
✗ Branch 3 (3→13) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 45 times.
45 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
367
368 // Create new type chain
369
1/2
✓ Branch 0 (6→7) taken 45 times.
✗ Branch 1 (6→16) not taken.
45 TypeChain newTypeChain = typeChain;
370 45 newTypeChain.front().data.hasCaptures = enabled;
371
372 // Register new type or return if already registered
373
1/2
✓ Branch 0 (8→9) taken 45 times.
✗ Branch 1 (8→14) not taken.
90 return TypeRegistry::getOrInsert(newTypeChain);
374 45 }
375
376 /**
377 * Retrieve the same type, but with the body scope removed
378 *
379 * @return Type with body scope removed
380 */
381 19907 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
382
3/6
✓ Branch 0 (2→3) taken 19907 times.
✗ Branch 1 (2→16) not taken.
✓ Branch 2 (3→4) taken 19907 times.
✗ Branch 3 (3→13) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 19907 times.
19907 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
383
384 // Create new type chain
385
1/2
✓ Branch 0 (6→7) taken 19907 times.
✗ Branch 1 (6→16) not taken.
19907 TypeChain newTypeChain = typeChain;
386 19907 newTypeChain.front().data.bodyScope = bodyScope;
387
388 // Register new type or return if already registered
389
1/2
✓ Branch 0 (8→9) taken 19907 times.
✗ Branch 1 (8→14) not taken.
39814 return TypeRegistry::getOrInsert(newTypeChain);
390 19907 }
391
392 /**
393 * Retrieve the same type, but with the given template types
394 *
395 * @return Type with new template types
396 */
397 3078 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
398
2/4
✓ Branch 0 (2→3) taken 3078 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 3078 times.
3078 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
399 3078 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 6817 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
408
3/6
✓ Branch 0 (2→3) taken 6817 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 6817 times.
✗ Branch 3 (3→14) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 6817 times.
6817 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
409
410 // Create new type chain
411
1/2
✓ Branch 0 (6→7) taken 6817 times.
✗ Branch 1 (6→17) not taken.
6817 TypeChain newTypeChain = typeChain;
412
1/2
✓ Branch 0 (8→9) taken 6817 times.
✗ Branch 1 (8→15) not taken.
6817 newTypeChain.front().templateTypes = templateTypes;
413
414 // Register new type or return if already registered
415
1/2
✓ Branch 0 (9→10) taken 6817 times.
✗ Branch 1 (9→15) not taken.
13634 return TypeRegistry::getOrInsert(newTypeChain);
416 6817 }
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 11203 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
424
3/6
✓ Branch 0 (2→3) taken 11203 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 11203 times.
✗ Branch 3 (3→14) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 11203 times.
11203 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
425
426 // Create new type chain
427
1/2
✓ Branch 0 (6→7) taken 11203 times.
✗ Branch 1 (6→17) not taken.
11203 TypeChain newTypeChain = typeChain;
428
1/2
✓ Branch 0 (8→9) taken 11203 times.
✗ Branch 1 (8→15) not taken.
11203 newTypeChain.front().paramTypes = paramAndReturnTypes;
429
430 // Register new type or return if already registered
431
1/2
✓ Branch 0 (9→10) taken 11203 times.
✗ Branch 1 (9→15) not taken.
22406 return TypeRegistry::getOrInsert(newTypeChain);
432 11203 }
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 275020 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
440
1/2
✓ Branch 0 (2→3) taken 275020 times.
✗ Branch 1 (2→34) not taken.
275020 const Type *baseType = getBase();
441
442 // Check if the type itself is generic
443
2/2
✓ Branch 0 (4→5) taken 44673 times.
✓ Branch 1 (4→6) taken 230347 times.
275020 if (baseType->is(TY_GENERIC))
444 44673 return true;
445
446 // Check if the type has generic template types
447
1/2
✓ Branch 0 (7→8) taken 230347 times.
✗ Branch 1 (7→34) not taken.
230347 const auto templateTypes = baseType->getTemplateTypes();
448
3/4
✓ Branch 0 (8→9) taken 230347 times.
✗ Branch 1 (8→32) not taken.
✓ Branch 2 (9→10) taken 16981 times.
✓ Branch 3 (9→11) taken 213366 times.
278540 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
449 16981 return true;
450
451 // Check param and return types or functions/procedures
452
3/4
✓ Branch 0 (11→12) taken 213366 times.
✗ Branch 1 (11→28) not taken.
✓ Branch 2 (12→13) taken 379 times.
✓ Branch 3 (12→24) taken 212987 times.
213366 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
453
2/4
✓ Branch 0 (13→14) taken 379 times.
✗ Branch 1 (13→31) not taken.
✓ Branch 2 (14→15) taken 379 times.
✗ Branch 3 (14→31) not taken.
379 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
454
3/4
✓ Branch 0 (15→16) taken 379 times.
✗ Branch 1 (15→29) not taken.
✓ Branch 2 (16→17) taken 45 times.
✓ Branch 3 (16→18) taken 334 times.
917 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
455 45 return true;
456
2/2
✓ Branch 0 (20→21) taken 334 times.
✓ Branch 1 (20→23) taken 45 times.
379 }
457
458 213321 return false; // Does not have generic parts
459 230347 }
460
461 /**
462 * Retrieve template types of the current type
463 *
464 * @return Vector of template types
465 */
466 321104 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 5403861 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 1182034 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
481 3732199 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 * @return Symbol type name
490 */
491 350570 void Type::getName(std::stringstream &name, bool withSize) const { // NOLINT(misc-no-recursion)
492 // Loop through all chain elements
493
2/2
✓ Branch 0 (10→4) taken 438396 times.
✓ Branch 1 (10→11) taken 350570 times.
788966 for (const TypeChainElement &chainElement : typeChain)
494
2/4
✓ Branch 0 (5→6) taken 438396 times.
✗ Branch 1 (5→14) not taken.
✓ Branch 2 (6→7) taken 438396 times.
✗ Branch 3 (6→12) not taken.
438396 name << chainElement.getName(withSize);
495 350570 }
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 * @return Symbol type name
502 */
503 12747 std::string Type::getName(bool withSize) const {
504
1/2
✓ Branch 0 (2→3) taken 12747 times.
✗ Branch 1 (2→11) not taken.
12747 std::stringstream name;
505
1/2
✓ Branch 0 (3→4) taken 12747 times.
✗ Branch 1 (3→9) not taken.
12747 getName(name, withSize);
506
1/2
✓ Branch 0 (4→5) taken 12747 times.
✗ Branch 1 (4→9) not taken.
25494 return name.str();
507 12747 }
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 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 39 times.
39 assert(is(TY_FUNCTION));
516
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (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 140 QualTypeList Type::getFunctionParamTypes() const {
526
2/4
✓ Branch 0 (2→3) taken 140 times.
✗ Branch 1 (2→20) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 140 times.
140 assert(isOneOf({TY_FUNCTION, TY_PROCEDURE}));
527
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 140 times.
140 if (typeChain.back().paramTypes.empty())
528 return {};
529
1/2
✓ Branch 0 (16→17) taken 140 times.
✗ Branch 1 (16→21) not taken.
420 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 123 bool Type::hasLambdaCaptures() const {
538
2/4
✓ Branch 0 (3→4) taken 123 times.
✗ Branch 1 (3→9) not taken.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 123 times.
123 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
539 123 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 429 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
548
2/4
✓ Branch 0 (3→4) taken 429 times.
✗ Branch 1 (3→9) not taken.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 429 times.
429 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
549 429 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 92780 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
561 // If the size does not match, it is not equal
562
2/2
✓ Branch 0 (4→5) taken 12170 times.
✓ Branch 1 (4→6) taken 80610 times.
92780 if (typeChain.size() != otherType->typeChain.size())
563 12170 return false;
564
565 // Compare the elements
566
2/2
✓ Branch 0 (18→7) taken 86707 times.
✓ Branch 1 (18→19) taken 52297 times.
139004 for (size_t i = 0; i < typeChain.size(); i++) {
567 86707 const TypeChainElement &lhsElement = typeChain.at(i);
568 86707 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
569
570 // Ignore differences in array size
571
3/6
✓ Branch 0 (9→10) taken 54484 times.
✓ Branch 1 (9→13) taken 32223 times.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (10→13) taken 54484 times.
✗ Branch 4 (11→12) not taken.
✗ Branch 5 (11→13) not taken.
86707 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
572 continue;
573
574 // Not both types are arrays -> compare them as usual
575
2/2
✓ Branch 0 (14→15) taken 28313 times.
✓ Branch 1 (14→16) taken 58394 times.
86707 if (lhsElement != rhsElement)
576 28313 return false;
577 }
578
579 52297 return true;
580 }
581
582 /**
583 * Remove pointers / arrays / references if both types have them as far as possible.
584 * Furthermore, remove reference wrappers if possible.
585 *
586 * @param typeA Candidate type
587 * @param typeB Requested type
588 */
589 73928 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
590 // Remove reference wrapper of front type if required
591
6/6
✓ Branch 0 (3→4) taken 31612 times.
✓ Branch 1 (3→7) taken 42316 times.
✓ Branch 2 (5→6) taken 28383 times.
✓ Branch 3 (5→7) taken 3229 times.
✓ Branch 4 (8→9) taken 28383 times.
✓ Branch 5 (8→11) taken 45545 times.
73928 if (typeA->isRef() && !typeB->isRef())
592 28383 typeA = typeA->removeReferenceWrapper();
593
594 // Remove reference wrapper of requested type if required
595
8/8
✓ Branch 0 (12→13) taken 70699 times.
✓ Branch 1 (12→19) taken 3229 times.
✓ Branch 2 (14→15) taken 2726 times.
✓ Branch 3 (14→19) taken 67973 times.
✓ Branch 4 (17→18) taken 2340 times.
✓ Branch 5 (17→19) taken 386 times.
✓ Branch 6 (20→21) taken 2340 times.
✓ Branch 7 (20→23) taken 71588 times.
73928 if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC))
596 2340 typeB = typeB->removeReferenceWrapper();
597
598 // Unwrap both types as far as possible
599
2/2
✓ Branch 0 (28→24) taken 4705 times.
✓ Branch 1 (28→29) taken 73928 times.
78633 while (typeA->isSameContainerTypeAs(typeB)) {
600 4705 typeB = typeB->getContained();
601 4705 typeA = typeA->getContained();
602 }
603 73928 }
604
605 /**
606 * Check if two types have the same type chain depth
607 *
608 * @param typeA First type
609 * @param typeB Second type
610 * @return Same depth or not
611 */
612 16481 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
613 16481 return typeA->typeChain.size() == typeB->typeChain.size();
614 }
615
616 } // namespace spice::compiler
617