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 ¶mAndReturnTypes) 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 |