GCC Code Coverage Report


Directory: ../
File: src/symboltablebuilder/Type.cpp
Date: 2025-02-05 01:09:36
Exec Total Coverage
Lines: 226 230 98.3%
Functions: 44 44 100.0%
Branches: 267 448 59.6%

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 3752991 times.
✗ Branch 1 (5→11) not taken.
✓ Branch 2 (7→8) taken 3752991 times.
✓ Branch 3 (7→9) taken 3752991 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.
11258973 Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {}
23
24
4/12
✓ Branch 0 (4→5) taken 1397 times.
✗ Branch 1 (4→19) not taken.
✓ Branch 2 (6→7) taken 1397 times.
✗ Branch 3 (6→13) not taken.
✓ Branch 4 (8→9) taken 1397 times.
✓ Branch 5 (8→10) taken 1397 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.
4191 Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {}
25
26 944 Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data,
27 944 const QualTypeList &templateTypes)
28
5/14
✓ Branch 0 (4→5) taken 944 times.
✗ Branch 1 (4→24) not taken.
✓ Branch 2 (5→6) taken 944 times.
✗ Branch 3 (5→21) not taken.
✓ Branch 4 (7→8) taken 944 times.
✗ Branch 5 (7→15) not taken.
✓ Branch 6 (9→10) taken 944 times.
✓ Branch 7 (9→11) taken 944 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.
2832 : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {}
29
30 1047468 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 7069307 SuperType Type::getSuperType() const {
38
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 7069307 times.
7069307 assert(!typeChain.empty());
39 7069307 return typeChain.back().superType;
40 }
41
42 /**
43 * Get the sub type of the current type
44 *
45 * @return Sub type
46 */
47 169170 const std::string &Type::getSubType() const {
48
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 169170 times.
169170 assert(!typeChain.empty());
49
2/4
✓ Branch 0 (5→6) taken 169170 times.
✗ Branch 1 (5→11) not taken.
✗ Branch 2 (6→7) not taken.
✓ Branch 3 (6→8) taken 169170 times.
169170 assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC}));
50 169170 return typeChain.back().subType;
51 }
52
53 /**
54 * Get the array size of the current type
55 *
56 * @return Array size
57 */
58 518 unsigned int Type::getArraySize() const {
59
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 518 times.
518 assert(isArray());
60 518 return typeChain.back().data.arraySize;
61 }
62
63 /**
64 * Get the body scope of the current type
65 *
66 * @return Body scope
67 */
68 124384 Scope *Type::getBodyScope() const {
69
2/4
✓ Branch 0 (2→3) taken 124384 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 124384 times.
124384 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
70 124384 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 12270 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 12268 times.
12270 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 12268 times.
12268 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 12268 times.
✗ Branch 1 (22→50) not taken.
12268 TypeChain newTypeChain = typeChain;
88
1/2
✓ Branch 0 (23→24) taken 12268 times.
✗ Branch 1 (23→47) not taken.
12268 newTypeChain.emplace_back(TY_PTR);
89
90 // Register new type or return if already registered
91
1/2
✓ Branch 0 (24→25) taken 12268 times.
✗ Branch 1 (24→48) not taken.
24536 return TypeRegistry::getOrInsert(newTypeChain);
92 12268 }
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 10310 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 10310 times.
10310 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 10310 times.
10310 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 10310 times.
✗ Branch 1 (22→50) not taken.
10310 TypeChain newTypeChain = typeChain;
110
1/2
✓ Branch 0 (23→24) taken 10310 times.
✗ Branch 1 (23→47) not taken.
10310 newTypeChain.emplace_back(TY_REF);
111
112 // Register new type or return if already registered
113
1/2
✓ Branch 0 (24→25) taken 10310 times.
✗ Branch 1 (24→48) not taken.
20620 return TypeRegistry::getOrInsert(newTypeChain);
114 10310 }
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 199 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 135 times.
✓ Branch 1 (2→6) taken 64 times.
✓ Branch 2 (4→5) taken 1 times.
✓ Branch 3 (4→6) taken 134 times.
✓ Branch 4 (7→8) taken 1 times.
✓ Branch 5 (7→16) taken 198 times.
199 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 198 times.
✗ Branch 1 (16→36) not taken.
198 TypeChain newTypeChain = typeChain;
131
1/2
✓ Branch 0 (17→18) taken 198 times.
✗ Branch 1 (17→32) not taken.
198 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 198 times.
✗ Branch 1 (18→34) not taken.
396 return TypeRegistry::getOrInsert(newTypeChain);
135 198 }
136
137 /**
138 * Retrieve the base type of an array or a pointer
139 *
140 * @return Base type
141 */
142 90340 const Type *Type::getContained() const {
143
2/2
✓ Branch 0 (3→4) taken 1290 times.
✓ Branch 1 (3→6) taken 89050 times.
90340 if (is(TY_STRING))
144
1/2
✓ Branch 0 (4→5) taken 1290 times.
✗ Branch 1 (4→18) not taken.
1290 return TypeRegistry::getOrInsert(TY_CHAR);
145
146 // Create new type chain
147
1/2
✓ Branch 0 (6→7) taken 89050 times.
✗ Branch 1 (6→18) not taken.
89050 TypeChain newTypeChain = typeChain;
148
1/2
✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 89050 times.
89050 assert(newTypeChain.size() > 1);
149 89050 newTypeChain.pop_back();
150
151 // Register new type or return if already registered
152
1/2
✓ Branch 0 (11→12) taken 89050 times.
✗ Branch 1 (11→16) not taken.
89050 return TypeRegistry::getOrInsert(newTypeChain);
153 89050 }
154
155 /**
156 * Replace the base type with another one
157 *
158 * @param newBaseType New base type
159 * @return The new type
160 */
161 11312 const Type *Type::replaceBase(const Type *newBaseType) const {
162
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 11312 times.
11312 assert(!typeChain.empty());
163
164 // Create new type
165
1/2
✓ Branch 0 (5→6) taken 11312 times.
✗ Branch 1 (5→27) not taken.
11312 TypeChain newTypeChain = newBaseType->typeChain;
166
4/4
✓ Branch 0 (7→8) taken 434 times.
✓ Branch 1 (7→11) taken 10878 times.
✓ Branch 2 (9→10) taken 14 times.
✓ Branch 3 (9→11) taken 420 times.
11312 const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF;
167
2/2
✓ Branch 0 (19→13) taken 1752 times.
✓ Branch 1 (19→20) taken 11312 times.
13064 for (size_t i = 1; i < typeChain.size(); i++)
168
3/4
✓ Branch 0 (13→14) taken 14 times.
✓ Branch 1 (13→15) taken 1738 times.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→17) taken 14 times.
1752 if (!doubleRef || i > 1)
169
2/4
✓ Branch 0 (15→16) taken 1738 times.
✗ Branch 1 (15→25) not taken.
✓ Branch 2 (16→17) taken 1738 times.
✗ Branch 3 (16→25) not taken.
1738 newTypeChain.push_back(typeChain.at(i));
170
171 // Register new type or return if already registered
172
1/2
✓ Branch 0 (20→21) taken 11312 times.
✗ Branch 1 (20→25) not taken.
22624 return TypeRegistry::getOrInsert(newTypeChain);
173 11312 }
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 29996 times.
✗ Branch 1 (3→6) not taken.
29996 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 5866 llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion)
189
2/4
✓ Branch 0 (3→4) taken 5866 times.
✗ Branch 1 (3→7) not taken.
✓ Branch 2 (5→6) taken 5866 times.
✗ Branch 3 (5→7) not taken.
5866 assert(!typeChain.empty() && !is(TY_INVALID));
190 5866 llvm::LLVMContext &context = sourceFile->llvmModule->getContext();
191
192
2/2
✓ Branch 0 (11→12) taken 65 times.
✓ Branch 1 (11→14) taken 5801 times.
5866 if (is(TY_DOUBLE))
193 65 return llvm::Type::getDoubleTy(context);
194
195
3/4
✓ Branch 0 (14→15) taken 5801 times.
✗ Branch 1 (14→160) not taken.
✓ Branch 2 (15→16) taken 521 times.
✓ Branch 3 (15→18) taken 5280 times.
5801 if (isOneOf({TY_INT, TY_ENUM}))
196 521 return llvm::Type::getInt32Ty(context);
197
198
2/2
✓ Branch 0 (19→20) taken 62 times.
✓ Branch 1 (19→22) taken 5218 times.
5280 if (is(TY_SHORT))
199 62 return llvm::Type::getInt16Ty(context);
200
201
2/2
✓ Branch 0 (23→24) taken 338 times.
✓ Branch 1 (23→26) taken 4880 times.
5218 if (is(TY_LONG))
202 338 return llvm::Type::getInt64Ty(context);
203
204
3/4
✓ Branch 0 (26→27) taken 4880 times.
✗ Branch 1 (26→161) not taken.
✓ Branch 2 (27→28) taken 241 times.
✓ Branch 3 (27→30) taken 4639 times.
4880 if (isOneOf({TY_CHAR, TY_BYTE}))
205 241 return llvm::Type::getInt8Ty(context);
206
207
2/2
✓ Branch 0 (31→32) taken 393 times.
✓ Branch 1 (31→34) taken 4246 times.
4639 if (is(TY_BOOL))
208 393 return llvm::Type::getInt1Ty(context);
209
210
3/4
✓ Branch 0 (34→35) taken 4246 times.
✗ Branch 1 (34→162) not taken.
✓ Branch 2 (35→36) taken 1516 times.
✓ Branch 3 (35→124) taken 2730 times.
4246 if (isOneOf({TY_STRUCT, TY_INTERFACE})) {
211
1/2
✓ Branch 0 (36→37) taken 1516 times.
✗ Branch 1 (36→194) not taken.
1516 const Scope *structBodyScope = getBodyScope();
212
2/4
✓ Branch 0 (38→39) taken 1516 times.
✗ Branch 1 (38→194) not taken.
✓ Branch 2 (39→40) taken 1516 times.
✗ Branch 3 (39→194) not taken.
1516 const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes());
213
1/2
✓ Branch 0 (40→41) taken 1516 times.
✗ Branch 1 (40→192) not taken.
1516 const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature);
214
1/2
✗ Branch 0 (43→44) not taken.
✓ Branch 1 (43→45) taken 1516 times.
1516 assert(structSymbol != nullptr);
215
216 // Collect concrete field types
217 llvm::StructType *structType;
218 1516 std::vector<llvm::Type *> fieldTypes;
219 1516 bool isPacked = false;
220
2/2
✓ Branch 0 (46→47) taken 1362 times.
✓ Branch 1 (46→108) taken 154 times.
1516 if (is(TY_STRUCT)) { // Struct
221
2/4
✓ Branch 0 (47→48) taken 1362 times.
✗ Branch 1 (47→183) not taken.
✓ Branch 2 (48→49) taken 1362 times.
✗ Branch 3 (48→183) not taken.
1362 const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode);
222
1/2
✗ Branch 0 (49→50) not taken.
✓ Branch 1 (49→51) taken 1362 times.
1362 assert(spiceStruct != nullptr);
223
1/2
✓ Branch 0 (51→52) taken 1362 times.
✗ Branch 1 (51→183) not taken.
1362 const std::string mangledName = NameMangling::mangleStruct(*spiceStruct);
224
1/2
✓ Branch 0 (53→54) taken 1362 times.
✗ Branch 1 (53→163) not taken.
1362 structType = llvm::StructType::create(context, mangledName);
225
226
1/2
✓ Branch 0 (54→55) taken 1362 times.
✗ Branch 1 (54→181) not taken.
1362 const size_t totalFieldCount = spiceStruct->scope->getFieldCount();
227
1/2
✓ Branch 0 (55→56) taken 1362 times.
✗ Branch 1 (55→181) not taken.
1362 fieldTypes.reserve(totalFieldCount);
228
229 // If the struct has no interface types, but a vtable was requested, add another ptr field type
230
2/4
✓ Branch 0 (56→57) taken 1362 times.
✗ Branch 1 (56→181) not taken.
✗ Branch 2 (57→58) not taken.
✓ Branch 3 (57→59) taken 1362 times.
1362 assert(structSymbol->declNode->isStructDef());
231
1/2
✓ Branch 0 (59→60) taken 1362 times.
✗ Branch 1 (59→61) not taken.
1362 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode);
232
4/4
✓ Branch 0 (66→67) taken 1102 times.
✓ Branch 1 (66→71) taken 260 times.
✓ Branch 2 (67→68) taken 38 times.
✓ Branch 3 (67→71) taken 1064 times.
1362 if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable)
233
2/4
✓ Branch 0 (68→69) taken 38 times.
✗ Branch 1 (68→164) not taken.
✓ Branch 2 (69→70) taken 38 times.
✗ Branch 3 (69→164) not taken.
38 fieldTypes.push_back(llvm::PointerType::get(context, 0));
234
235 // Collect all field types
236
2/2
✓ Branch 0 (84→72) taken 3543 times.
✓ Branch 1 (84→85) taken 1362 times.
4905 for (size_t i = 0; i < totalFieldCount; i++) {
237
1/2
✗ Branch 0 (72→73) not taken.
✓ Branch 1 (72→74) taken 3543 times.
3543 const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i);
238
1/2
✗ Branch 0 (77→78) not taken.
✓ Branch 1 (77→79) taken 3543 times.
3543 assert(fieldSymbol != nullptr);
239
3/6
✓ Branch 0 (79→80) taken 3543 times.
✗ Branch 1 (79→165) not taken.
✓ Branch 2 (81→82) taken 3543 times.
✗ Branch 3 (81→165) not taken.
✓ Branch 4 (82→83) taken 3543 times.
✗ Branch 5 (82→165) not taken.
3543 fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType()));
240 }
241
242 // Check if the struct is declared as packed
243
12/18
✓ Branch 0 (85→86) taken 39 times.
✓ Branch 1 (85→92) taken 1323 times.
✓ Branch 2 (88→89) taken 39 times.
✗ Branch 3 (88→166) not taken.
✓ Branch 4 (89→90) taken 39 times.
✗ Branch 5 (89→166) not taken.
✓ Branch 6 (90→91) taken 1 times.
✓ Branch 7 (90→92) taken 38 times.
✓ Branch 8 (93→94) taken 39 times.
✓ Branch 9 (93→95) taken 1323 times.
✓ Branch 10 (95→96) taken 39 times.
✓ Branch 11 (95→98) taken 1323 times.
✓ Branch 12 (98→99) taken 1 times.
✓ Branch 13 (98→106) taken 1361 times.
✗ Branch 14 (166→167) not taken.
✗ Branch 15 (166→168) not taken.
✗ Branch 16 (170→171) not taken.
✗ Branch 17 (170→173) not taken.
1440 if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED))
244
2/4
✓ Branch 0 (101→102) taken 1 times.
✗ Branch 1 (101→177) not taken.
✓ Branch 2 (102→103) taken 1 times.
✗ Branch 3 (102→175) not taken.
3 isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue;
245 1362 } else { // Interface
246
2/4
✓ Branch 0 (108→109) taken 154 times.
✗ Branch 1 (108→188) not taken.
✓ Branch 2 (109→110) taken 154 times.
✗ Branch 3 (109→188) not taken.
154 const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode);
247
1/2
✗ Branch 0 (110→111) not taken.
✓ Branch 1 (110→112) taken 154 times.
154 assert(spiceInterface != nullptr);
248
1/2
✓ Branch 0 (112→113) taken 154 times.
✗ Branch 1 (112→188) not taken.
154 const std::string mangledName = NameMangling::mangleInterface(*spiceInterface);
249
1/2
✓ Branch 0 (114→115) taken 154 times.
✗ Branch 1 (114→184) not taken.
154 structType = llvm::StructType::create(context, mangledName);
250
251
2/4
✓ Branch 0 (115→116) taken 154 times.
✗ Branch 1 (115→185) not taken.
✓ Branch 2 (116→117) taken 154 times.
✗ Branch 3 (116→185) not taken.
154 fieldTypes.push_back(llvm::PointerType::get(context, 0));
252 154 }
253
254 // Set field types to struct type
255
1/2
✓ Branch 0 (120→121) taken 1516 times.
✗ Branch 1 (120→189) not taken.
1516 structType->setBody(fieldTypes, isPacked);
256
257 1516 return structType;
258 1516 }
259
260
10/12
✓ Branch 0 (124→125) taken 2730 times.
✗ Branch 1 (124→195) not taken.
✓ Branch 2 (125→126) taken 127 times.
✓ Branch 3 (125→130) taken 2603 times.
✓ Branch 4 (127→128) taken 54 times.
✓ Branch 5 (127→131) taken 73 times.
✓ Branch 6 (128→129) taken 54 times.
✗ Branch 7 (128→195) not taken.
✓ Branch 8 (129→130) taken 20 times.
✓ Branch 9 (129→131) taken 34 times.
✓ Branch 10 (132→133) taken 2623 times.
✓ Branch 11 (132→135) taken 107 times.
2730 if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0))
261 2623 return llvm::PointerType::get(context, 0);
262
263
3/4
✓ Branch 0 (135→136) taken 107 times.
✗ Branch 1 (135→196) not taken.
✓ Branch 2 (136→137) taken 73 times.
✓ Branch 3 (136→142) taken 34 times.
107 if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
264 73 llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0);
265
1/2
✓ Branch 0 (139→140) taken 73 times.
✗ Branch 1 (139→197) not taken.
73 return llvm::StructType::get(context, {ptrTy, ptrTy});
266 }
267
268
1/2
✓ Branch 0 (143→144) taken 34 times.
✗ Branch 1 (143→152) not taken.
34 if (isArray()) {
269
1/2
✗ Branch 0 (145→146) not taken.
✓ Branch 1 (145→147) taken 34 times.
34 assert(getArraySize() > 0);
270 34 llvm::Type *containedType = sourceFile->getLLVMType(getContained());
271 34 return llvm::ArrayType::get(containedType, getArraySize());
272 }
273
274 throw CompilerError(UNHANDLED_BRANCH, "Cannot determine LLVM type of " + getName(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 550958 bool Type::isBase(SuperType superType) const {
284
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 550958 times.
550958 assert(!typeChain.empty());
285 550958 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 0 (2→3) taken 102925 times.
✗ Branch 1 (2→6) not taken.
102925 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 70027 bool Type::isExtendedPrimitive() const {
305
6/8
✓ Branch 0 (2→3) taken 70027 times.
✗ Branch 1 (2→11) not taken.
✓ Branch 2 (3→4) taken 21390 times.
✓ Branch 3 (3→6) taken 48637 times.
✓ Branch 4 (4→5) taken 21390 times.
✗ Branch 5 (4→11) not taken.
✓ Branch 6 (5→6) taken 19096 times.
✓ Branch 7 (5→7) taken 2294 times.
70027 return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE});
306 }
307
308 /**
309 * Check if the current type is a pointer type
310 *
311 * @return Pointer type or not
312 */
313 252608 bool Type::isPtr() const { return getSuperType() == TY_PTR; }
314
315 /**
316 * Check if the current type is a reference type
317 *
318 * @return Reference type or not
319 */
320 755935 bool Type::isRef() const { return getSuperType() == TY_REF; }
321
322 /**
323 * Check if the current type is an array type
324 *
325 * @return Array type or not
326 */
327 94679 bool Type::isArray() const { return getSuperType() == TY_ARRAY; }
328
329 /**
330 * Check if the current type is of the same container type like the other type.
331 * Only TY_PTR, TY_REF and TY_ARRAY are considered as container types.
332 *
333 * @param other Other symbol type
334 * @return Same container type or not
335 */
336 71992 bool Type::isSameContainerTypeAs(const Type *other) const {
337
4/4
✓ Branch 0 (3→4) taken 1675 times.
✓ Branch 1 (3→7) taken 70317 times.
✓ Branch 2 (5→6) taken 1525 times.
✓ Branch 3 (5→7) taken 150 times.
71992 const bool bothPtr = isPtr() && other->isPtr();
338
4/4
✓ Branch 0 (9→10) taken 3274 times.
✓ Branch 1 (9→13) taken 68718 times.
✓ Branch 2 (11→12) taken 3171 times.
✓ Branch 3 (11→13) taken 103 times.
71992 const bool bothRef = isRef() && other->isRef();
339
3/4
✓ Branch 0 (15→16) taken 50 times.
✓ Branch 1 (15→19) taken 71942 times.
✓ Branch 2 (17→18) taken 50 times.
✗ Branch 3 (17→19) not taken.
71992 const bool bothArray = isArray() && other->isArray();
340
6/6
✓ Branch 0 (20→21) taken 70467 times.
✓ Branch 1 (20→23) taken 1525 times.
✓ Branch 2 (21→22) taken 67296 times.
✓ Branch 3 (21→23) taken 3171 times.
✓ Branch 4 (22→23) taken 50 times.
✓ Branch 5 (22→24) taken 67246 times.
71992 return bothPtr || bothRef || bothArray;
341 }
342
343 /**
344 * Retrieve the base type of the current type
345 *
346 * @return Base type
347 */
348 884653 const Type *Type::getBase() const {
349
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 884653 times.
884653 assert(!typeChain.empty());
350
351 // Create new type chain
352
3/6
✓ Branch 0 (9→10) taken 884653 times.
✗ Branch 1 (9→19) not taken.
✓ Branch 2 (12→13) taken 884653 times.
✓ Branch 3 (12→14) taken 884653 times.
✗ Branch 4 (23→24) not taken.
✗ Branch 5 (23→25) not taken.
2653959 const TypeChain newTypeChain = {typeChain.front()};
353
354 // Register new type or return if already registered
355
1/2
✓ Branch 0 (14→15) taken 884653 times.
✗ Branch 1 (14→32) not taken.
1769306 return TypeRegistry::getOrInsert(newTypeChain);
356
1/6
✓ Branch 0 (6→7) taken 884653 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.
1769306 }
357
358 /**
359 * Retrieve the same type, but with lambda captures
360 *
361 * @return Type with lambda captures
362 */
363 45 const Type *Type::getWithLambdaCaptures(bool enabled) const {
364
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}));
365
366 // Create new type chain
367
1/2
✓ Branch 0 (6→7) taken 45 times.
✗ Branch 1 (6→16) not taken.
45 TypeChain newTypeChain = typeChain;
368 45 newTypeChain.front().data.hasCaptures = enabled;
369
370 // Register new type or return if already registered
371
1/2
✓ Branch 0 (8→9) taken 45 times.
✗ Branch 1 (8→14) not taken.
90 return TypeRegistry::getOrInsert(newTypeChain);
372 45 }
373
374 /**
375 * Retrieve the same type, but with the body scope removed
376 *
377 * @return Type with body scope removed
378 */
379 22436 const Type *Type::getWithBodyScope(Scope *bodyScope) const {
380
3/6
✓ Branch 0 (2→3) taken 22436 times.
✗ Branch 1 (2→16) not taken.
✓ Branch 2 (3→4) taken 22436 times.
✗ Branch 3 (3→13) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 22436 times.
22436 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
381
382 // Create new type chain
383
1/2
✓ Branch 0 (6→7) taken 22436 times.
✗ Branch 1 (6→16) not taken.
22436 TypeChain newTypeChain = typeChain;
384 22436 newTypeChain.front().data.bodyScope = bodyScope;
385
386 // Register new type or return if already registered
387
1/2
✓ Branch 0 (8→9) taken 22436 times.
✗ Branch 1 (8→14) not taken.
44872 return TypeRegistry::getOrInsert(newTypeChain);
388 22436 }
389
390 /**
391 * Retrieve the same type, but with the given template types
392 *
393 * @return Type with new template types
394 */
395 2974 const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const {
396
2/4
✓ Branch 0 (2→3) taken 2974 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 2974 times.
2974 assert(isOneOf({TY_STRUCT, TY_INTERFACE}));
397 2974 return getWithBaseTemplateTypes(templateTypes);
398 }
399
400 /**
401 * Retrieve the same type, but with the given base template types
402 *
403 * @return Type with new base template types
404 */
405 6616 const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const {
406
3/6
✓ Branch 0 (2→3) taken 6616 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 6616 times.
✗ Branch 3 (3→14) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 6616 times.
6616 assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE}));
407
408 // Create new type chain
409
1/2
✓ Branch 0 (6→7) taken 6616 times.
✗ Branch 1 (6→17) not taken.
6616 TypeChain newTypeChain = typeChain;
410
1/2
✓ Branch 0 (8→9) taken 6616 times.
✗ Branch 1 (8→15) not taken.
6616 newTypeChain.front().templateTypes = templateTypes;
411
412 // Register new type or return if already registered
413
1/2
✓ Branch 0 (9→10) taken 6616 times.
✗ Branch 1 (9→15) not taken.
13232 return TypeRegistry::getOrInsert(newTypeChain);
414 6616 }
415
416 /**
417 * Retrieve the same type, but with the param and return types removed
418 *
419 * @return Type with param and return types removed
420 */
421 10580 const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList &paramAndReturnTypes) const {
422
3/6
✓ Branch 0 (2→3) taken 10580 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 10580 times.
✗ Branch 3 (3→14) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 10580 times.
10580 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
423
424 // Create new type chain
425
1/2
✓ Branch 0 (6→7) taken 10580 times.
✗ Branch 1 (6→17) not taken.
10580 TypeChain newTypeChain = typeChain;
426
1/2
✓ Branch 0 (8→9) taken 10580 times.
✗ Branch 1 (8→15) not taken.
10580 newTypeChain.front().paramTypes = paramAndReturnTypes;
427
428 // Register new type or return if already registered
429
1/2
✓ Branch 0 (9→10) taken 10580 times.
✗ Branch 1 (9→15) not taken.
21160 return TypeRegistry::getOrInsert(newTypeChain);
430 10580 }
431
432 /**
433 * Checks if the base type is generic itself or has generic parts in its template types
434 *
435 * @return Contains generic parts or not
436 */
437 246419 bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion)
438
1/2
✓ Branch 0 (2→3) taken 246419 times.
✗ Branch 1 (2→34) not taken.
246419 const Type *baseType = getBase();
439
440 // Check if the type itself is generic
441
2/2
✓ Branch 0 (4→5) taken 42579 times.
✓ Branch 1 (4→6) taken 203840 times.
246419 if (baseType->is(TY_GENERIC))
442 42579 return true;
443
444 // Check if the type has generic template types
445
1/2
✓ Branch 0 (7→8) taken 203840 times.
✗ Branch 1 (7→34) not taken.
203840 const auto templateTypes = baseType->getTemplateTypes();
446
3/4
✓ Branch 0 (8→9) taken 203840 times.
✗ Branch 1 (8→32) not taken.
✓ Branch 2 (9→10) taken 16412 times.
✓ Branch 3 (9→11) taken 187428 times.
244356 if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
447 16412 return true;
448
449 // Check param and return types or functions/procedures
450
3/4
✓ Branch 0 (11→12) taken 187428 times.
✗ Branch 1 (11→28) not taken.
✓ Branch 2 (12→13) taken 504 times.
✓ Branch 3 (12→24) taken 186924 times.
187428 if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) {
451
2/4
✓ Branch 0 (13→14) taken 504 times.
✗ Branch 1 (13→31) not taken.
✓ Branch 2 (14→15) taken 504 times.
✗ Branch 3 (14→31) not taken.
504 const auto paramTypes = baseType->getFunctionParamAndReturnTypes();
452
3/4
✓ Branch 0 (15→16) taken 504 times.
✗ Branch 1 (15→29) not taken.
✓ Branch 2 (16→17) taken 144 times.
✓ Branch 3 (16→18) taken 360 times.
1326 if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); }))
453 144 return true;
454
2/2
✓ Branch 0 (20→21) taken 360 times.
✓ Branch 1 (20→23) taken 144 times.
504 }
455
456 187284 return false; // Does not have generic parts
457 203840 }
458
459 /**
460 * Retrieve template types of the current type
461 *
462 * @return Vector of template types
463 */
464 291027 const QualTypeList &Type::getTemplateTypes() const { return typeChain.back().templateTypes; }
465
466 /**
467 * Check if the current type is of a certain super type
468 *
469 * @return Applicable or not
470 */
471 5269957 bool Type::is(SuperType superType) const { return getSuperType() == superType; }
472
473 /**
474 * Check if the current type is one of a list of super types
475 *
476 * @return Applicable or not
477 */
478 1114781 bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const {
479 3626167 return std::ranges::any_of(superTypes, [this](SuperType superType) { return is(superType); });
480 }
481
482 /**
483 * Get the name of the symbol type as a string
484 *
485 * @param name Get name of type
486 * @param withSize Include the array size for sized types
487 * @return Symbol type name
488 */
489 325117 void Type::getName(std::stringstream &name, bool withSize) const { // NOLINT(misc-no-recursion)
490 // Loop through all chain elements
491
2/2
✓ Branch 0 (10→4) taken 407875 times.
✓ Branch 1 (10→11) taken 325117 times.
732992 for (const TypeChainElement &chainElement : typeChain)
492
2/4
✓ Branch 0 (5→6) taken 407875 times.
✗ Branch 1 (5→14) not taken.
✓ Branch 2 (6→7) taken 407875 times.
✗ Branch 3 (6→12) not taken.
407875 name << chainElement.getName(withSize);
493 325117 }
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 * @return Symbol type name
500 */
501 11971 std::string Type::getName(bool withSize) const {
502
1/2
✓ Branch 0 (2→3) taken 11971 times.
✗ Branch 1 (2→11) not taken.
11971 std::stringstream name;
503
1/2
✓ Branch 0 (3→4) taken 11971 times.
✗ Branch 1 (3→9) not taken.
11971 getName(name, withSize);
504
1/2
✓ Branch 0 (4→5) taken 11971 times.
✗ Branch 1 (4→9) not taken.
23942 return name.str();
505 11971 }
506
507 /**
508 * Get the return type of function type
509 *
510 * @return Function return type
511 */
512 39 const QualType &Type::getFunctionReturnType() const {
513
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 39 times.
39 assert(is(TY_FUNCTION));
514
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 39 times.
39 assert(!typeChain.back().paramTypes.empty());
515 39 return typeChain.back().paramTypes.front();
516 }
517
518 /**
519 * Get the param types of a function or procedure type
520 *
521 * @return Function param types
522 */
523 140 QualTypeList Type::getFunctionParamTypes() const {
524
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}));
525
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 140 times.
140 if (typeChain.back().paramTypes.empty())
526 return {};
527
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()};
528 }
529
530 /**
531 * Check if a function or procedure type has captures
532 *
533 * @return Has captures
534 */
535 176 bool Type::hasLambdaCaptures() const {
536
2/4
✓ Branch 0 (3→4) taken 176 times.
✗ Branch 1 (3→9) not taken.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 176 times.
176 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
537 176 return typeChain.front().data.hasCaptures;
538 }
539
540 /**
541 * Get the param and return types of a function or procedure base type
542 *
543 * @return Function param and return types (first is return type, rest are param types)
544 */
545 647 const QualTypeList &Type::getFunctionParamAndReturnTypes() const {
546
2/4
✓ Branch 0 (3→4) taken 647 times.
✗ Branch 1 (3→9) not taken.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 647 times.
647 assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE}));
547 647 return typeChain.front().paramTypes;
548 }
549
550 /**
551 * Check for the matching compatibility of two types.
552 * Useful for struct and function matching as well as assignment type validation and function arg matching.
553 *
554 * @param otherType Type to compare against
555 * @param ignoreArraySize Ignore array sizes
556 * @return Matching or not
557 */
558 92343 bool Type::matches(const Type *otherType, bool ignoreArraySize) const {
559 // If the size does not match, it is not equal
560
2/2
✓ Branch 0 (4→5) taken 11861 times.
✓ Branch 1 (4→6) taken 80482 times.
92343 if (typeChain.size() != otherType->typeChain.size())
561 11861 return false;
562
563 // Compare the elements
564
2/2
✓ Branch 0 (18→7) taken 86515 times.
✓ Branch 1 (18→19) taken 52940 times.
139455 for (size_t i = 0; i < typeChain.size(); i++) {
565 86515 const TypeChainElement &lhsElement = typeChain.at(i);
566 86515 const TypeChainElement &rhsElement = otherType->typeChain.at(i);
567
568 // Ignore differences in array size
569
5/6
✓ Branch 0 (9→10) taken 52595 times.
✓ Branch 1 (9→13) taken 33920 times.
✓ Branch 2 (10→11) taken 1 times.
✓ Branch 3 (10→13) taken 52594 times.
✓ Branch 4 (11→12) taken 1 times.
✗ Branch 5 (11→13) not taken.
86515 if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY)
570 1 continue;
571
572 // Not both types are arrays -> compare them as usual
573
2/2
✓ Branch 0 (14→15) taken 27542 times.
✓ Branch 1 (14→16) taken 58972 times.
86514 if (lhsElement != rhsElement)
574 27542 return false;
575 }
576
577 // Ignore or compare qualifiers
578 52940 return true;
579 }
580
581 /**
582 * Remove pointers / arrays / references if both types have them as far as possible.
583 * Furthermore, remove reference wrappers if possible.
584 *
585 * @param typeA Candidate type
586 * @param typeB Requested type
587 */
588 64651 void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) {
589 // Remove reference wrapper of front type if required
590
6/6
✓ Branch 0 (3→4) taken 30969 times.
✓ Branch 1 (3→7) taken 33682 times.
✓ Branch 2 (5→6) taken 27798 times.
✓ Branch 3 (5→7) taken 3171 times.
✓ Branch 4 (8→9) taken 27798 times.
✓ Branch 5 (8→11) taken 36853 times.
64651 if (typeA->isRef() && !typeB->isRef())
591 27798 typeA = typeA->removeReferenceWrapper();
592
593 // Remove reference wrapper of requested type if required
594
8/8
✓ Branch 0 (12→13) taken 61480 times.
✓ Branch 1 (12→19) taken 3171 times.
✓ Branch 2 (14→15) taken 2552 times.
✓ Branch 3 (14→19) taken 58928 times.
✓ Branch 4 (17→18) taken 2198 times.
✓ Branch 5 (17→19) taken 354 times.
✓ Branch 6 (20→21) taken 2198 times.
✓ Branch 7 (20→23) taken 62453 times.
64651 if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC))
595 2198 typeB = typeB->removeReferenceWrapper();
596
597 // Unwrap both types as far as possible
598
2/2
✓ Branch 0 (28→24) taken 4620 times.
✓ Branch 1 (28→29) taken 64651 times.
69271 while (typeA->isSameContainerTypeAs(typeB)) {
599 4620 typeB = typeB->getContained();
600 4620 typeA = typeA->getContained();
601 }
602 64651 }
603
604 /**
605 * Check if two types have the same type chain depth
606 *
607 * @param typeA First type
608 * @param typeB Second type
609 * @return Same depth or not
610 */
611 15960 bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) {
612 15960 return typeA->typeChain.size() == typeB->typeChain.size();
613 }
614
615 } // namespace spice::compiler
616