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 4545177 times.
✗ Branch 1 (5→11) not taken.
✓ Branch 2 (7→8) taken 4545177 times.
✓ Branch 3 (7→9) taken 4545177 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.
|
13635531 | Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {} |
23 | |||
24 |
4/12✓ Branch 0 (4→5) taken 1607 times.
✗ Branch 1 (4→19) not taken.
✓ Branch 2 (6→7) taken 1607 times.
✗ Branch 3 (6→13) not taken.
✓ Branch 4 (8→9) taken 1607 times.
✓ Branch 5 (8→10) taken 1607 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.
|
4821 | Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {} |
25 | |||
26 | 1063 | Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data, | |
27 | 1063 | const QualTypeList &templateTypes) | |
28 |
5/14✓ Branch 0 (4→5) taken 1063 times.
✗ Branch 1 (4→24) not taken.
✓ Branch 2 (5→6) taken 1063 times.
✗ Branch 3 (5→21) not taken.
✓ Branch 4 (7→8) taken 1063 times.
✗ Branch 5 (7→15) not taken.
✓ Branch 6 (9→10) taken 1063 times.
✓ Branch 7 (9→11) taken 1063 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.
|
3189 | : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {} |
29 | |||
30 | 1216190 | 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 | 7842553 | SuperType Type::getSuperType() const { | |
38 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 7842553 times.
|
7842553 | assert(!typeChain.empty()); |
39 | 7842553 | return typeChain.back().superType; | |
40 | } | ||
41 | |||
42 | /** | ||
43 | * Get the sub type of the current type | ||
44 | * | ||
45 | * @return Sub type | ||
46 | */ | ||
47 | 183081 | const std::string &Type::getSubType() const { | |
48 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 183081 times.
|
183081 | assert(!typeChain.empty()); |
49 |
2/4✓ Branch 0 (5→6) taken 183081 times.
✗ Branch 1 (5→11) not taken.
✗ Branch 2 (6→7) not taken.
✓ Branch 3 (6→8) taken 183081 times.
|
183081 | assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC})); |
50 | 183081 | return typeChain.back().subType; | |
51 | } | ||
52 | |||
53 | /** | ||
54 | * Get the array size of the current type | ||
55 | * | ||
56 | * @return Array size | ||
57 | */ | ||
58 | 560 | unsigned int Type::getArraySize() const { | |
59 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 560 times.
|
560 | assert(isArray()); |
60 | 560 | return typeChain.back().data.arraySize; | |
61 | } | ||
62 | |||
63 | /** | ||
64 | * Get the body scope of the current type | ||
65 | * | ||
66 | * @return Body scope | ||
67 | */ | ||
68 | 134440 | Scope *Type::getBodyScope() const { | |
69 |
2/4✓ Branch 0 (2→3) taken 134440 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 134440 times.
|
134440 | assert(isOneOf({TY_STRUCT, TY_INTERFACE})); |
70 | 134440 | 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 | 14477 | 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 14475 times.
|
14477 | 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 14475 times.
|
14475 | 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 14475 times.
✗ Branch 1 (22→50) not taken.
|
14475 | TypeChain newTypeChain = typeChain; |
88 |
1/2✓ Branch 0 (23→24) taken 14475 times.
✗ Branch 1 (23→47) not taken.
|
14475 | newTypeChain.emplace_back(TY_PTR); |
89 | |||
90 | // Register new type or return if already registered | ||
91 |
1/2✓ Branch 0 (24→25) taken 14475 times.
✗ Branch 1 (24→48) not taken.
|
28950 | return TypeRegistry::getOrInsert(newTypeChain); |
92 | 14475 | } | |
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 | 11104 | 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 11104 times.
|
11104 | 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 11104 times.
|
11104 | 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 11104 times.
✗ Branch 1 (22→50) not taken.
|
11104 | TypeChain newTypeChain = typeChain; |
110 |
1/2✓ Branch 0 (23→24) taken 11104 times.
✗ Branch 1 (23→47) not taken.
|
11104 | newTypeChain.emplace_back(TY_REF); |
111 | |||
112 | // Register new type or return if already registered | ||
113 |
1/2✓ Branch 0 (24→25) taken 11104 times.
✗ Branch 1 (24→48) not taken.
|
22208 | return TypeRegistry::getOrInsert(newTypeChain); |
114 | 11104 | } | |
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 | 218 | 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 146 times.
✓ Branch 1 (2→6) taken 72 times.
✓ Branch 2 (4→5) taken 1 times.
✓ Branch 3 (4→6) taken 145 times.
✓ Branch 4 (7→8) taken 1 times.
✓ Branch 5 (7→16) taken 217 times.
|
218 | 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 217 times.
✗ Branch 1 (16→36) not taken.
|
217 | TypeChain newTypeChain = typeChain; |
131 |
1/2✓ Branch 0 (17→18) taken 217 times.
✗ Branch 1 (17→32) not taken.
|
217 | 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 217 times.
✗ Branch 1 (18→34) not taken.
|
434 | return TypeRegistry::getOrInsert(newTypeChain); |
135 | 217 | } | |
136 | |||
137 | /** | ||
138 | * Retrieve the base type of an array or a pointer | ||
139 | * | ||
140 | * @return Base type | ||
141 | */ | ||
142 | 99272 | const Type *Type::getContained() const { | |
143 |
2/2✓ Branch 0 (3→4) taken 1374 times.
✓ Branch 1 (3→6) taken 97898 times.
|
99272 | if (is(TY_STRING)) |
144 |
1/2✓ Branch 0 (4→5) taken 1374 times.
✗ Branch 1 (4→18) not taken.
|
1374 | return TypeRegistry::getOrInsert(TY_CHAR); |
145 | |||
146 | // Create new type chain | ||
147 |
1/2✓ Branch 0 (6→7) taken 97898 times.
✗ Branch 1 (6→18) not taken.
|
97898 | TypeChain newTypeChain = typeChain; |
148 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 97898 times.
|
97898 | assert(newTypeChain.size() > 1); |
149 | 97898 | newTypeChain.pop_back(); | |
150 | |||
151 | // Register new type or return if already registered | ||
152 |
1/2✓ Branch 0 (11→12) taken 97898 times.
✗ Branch 1 (11→16) not taken.
|
97898 | return TypeRegistry::getOrInsert(newTypeChain); |
153 | 97898 | } | |
154 | |||
155 | /** | ||
156 | * Replace the base type with another one | ||
157 | * | ||
158 | * @param newBaseType New base type | ||
159 | * @return The new type | ||
160 | */ | ||
161 | 9506 | const Type *Type::replaceBase(const Type *newBaseType) const { | |
162 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 9506 times.
|
9506 | assert(!typeChain.empty()); |
163 | |||
164 | // Create new type | ||
165 |
1/2✓ Branch 0 (5→6) taken 9506 times.
✗ Branch 1 (5→27) not taken.
|
9506 | TypeChain newTypeChain = newBaseType->typeChain; |
166 |
4/4✓ Branch 0 (7→8) taken 508 times.
✓ Branch 1 (7→11) taken 8998 times.
✓ Branch 2 (9→10) taken 14 times.
✓ Branch 3 (9→11) taken 494 times.
|
9506 | const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF; |
167 |
2/2✓ Branch 0 (19→13) taken 1517 times.
✓ Branch 1 (19→20) taken 9506 times.
|
11023 | for (size_t i = 1; i < typeChain.size(); i++) |
168 |
3/4✓ Branch 0 (13→14) taken 14 times.
✓ Branch 1 (13→15) taken 1503 times.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→17) taken 14 times.
|
1517 | if (!doubleRef || i > 1) |
169 |
2/4✓ Branch 0 (15→16) taken 1503 times.
✗ Branch 1 (15→25) not taken.
✓ Branch 2 (16→17) taken 1503 times.
✗ Branch 3 (16→25) not taken.
|
1503 | newTypeChain.push_back(typeChain.at(i)); |
170 | |||
171 | // Register new type or return if already registered | ||
172 |
1/2✓ Branch 0 (20→21) taken 9506 times.
✗ Branch 1 (20→25) not taken.
|
19012 | return TypeRegistry::getOrInsert(newTypeChain); |
173 | 9506 | } | |
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 32563 times.
✗ Branch 1 (3→6) not taken.
|
32563 | 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 | 6636 | llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion) | |
189 |
2/4✓ Branch 0 (3→4) taken 6636 times.
✗ Branch 1 (3→7) not taken.
✓ Branch 2 (5→6) taken 6636 times.
✗ Branch 3 (5→7) not taken.
|
6636 | assert(!typeChain.empty() && !is(TY_INVALID)); |
190 | 6636 | llvm::LLVMContext &context = sourceFile->llvmModule->getContext(); | |
191 | |||
192 |
10/12✓ Branch 0 (10→11) taken 6636 times.
✗ Branch 1 (10→163) not taken.
✓ Branch 2 (11→12) taken 3674 times.
✓ Branch 3 (11→16) taken 2962 times.
✓ Branch 4 (13→14) taken 57 times.
✓ Branch 5 (13→17) taken 3617 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 2983 times.
✓ Branch 11 (18→21) taken 3653 times.
|
6636 | if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0)) |
193 | 2983 | return llvm::PointerType::get(context, 0); | |
194 | |||
195 |
2/2✓ Branch 0 (22→23) taken 36 times.
✓ Branch 1 (22→31) taken 3617 times.
|
3653 | 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 3617 times.
|
3617 | assert(!hasAnyGenericParts()); |
202 | |||
203 |
2/2✓ Branch 0 (35→36) taken 74 times.
✓ Branch 1 (35→38) taken 3543 times.
|
3617 | if (is(TY_DOUBLE)) |
204 | 74 | return llvm::Type::getDoubleTy(context); | |
205 | |||
206 |
3/4✓ Branch 0 (38→39) taken 3543 times.
✗ Branch 1 (38→164) not taken.
✓ Branch 2 (39→40) taken 567 times.
✓ Branch 3 (39→42) taken 2976 times.
|
3543 | if (isOneOf({TY_INT, TY_ENUM})) |
207 | 567 | return llvm::Type::getInt32Ty(context); | |
208 | |||
209 |
2/2✓ Branch 0 (43→44) taken 66 times.
✓ Branch 1 (43→46) taken 2910 times.
|
2976 | if (is(TY_SHORT)) |
210 | 66 | return llvm::Type::getInt16Ty(context); | |
211 | |||
212 |
2/2✓ Branch 0 (47→48) taken 375 times.
✓ Branch 1 (47→50) taken 2535 times.
|
2910 | if (is(TY_LONG)) |
213 | 375 | return llvm::Type::getInt64Ty(context); | |
214 | |||
215 |
3/4✓ Branch 0 (50→51) taken 2535 times.
✗ Branch 1 (50→165) not taken.
✓ Branch 2 (51→52) taken 267 times.
✓ Branch 3 (51→54) taken 2268 times.
|
2535 | if (isOneOf({TY_CHAR, TY_BYTE})) |
216 | 267 | return llvm::Type::getInt8Ty(context); | |
217 | |||
218 |
2/2✓ Branch 0 (55→56) taken 439 times.
✓ Branch 1 (55→58) taken 1829 times.
|
2268 | if (is(TY_BOOL)) |
219 | 439 | return llvm::Type::getInt1Ty(context); | |
220 | |||
221 |
3/4✓ Branch 0 (58→59) taken 1829 times.
✗ Branch 1 (58→166) not taken.
✓ Branch 2 (59→60) taken 1756 times.
✓ Branch 3 (59→148) taken 73 times.
|
1829 | if (isOneOf({TY_STRUCT, TY_INTERFACE})) { |
222 |
1/2✓ Branch 0 (60→61) taken 1756 times.
✗ Branch 1 (60→198) not taken.
|
1756 | const Scope *structBodyScope = getBodyScope(); |
223 |
2/4✓ Branch 0 (62→63) taken 1756 times.
✗ Branch 1 (62→198) not taken.
✓ Branch 2 (63→64) taken 1756 times.
✗ Branch 3 (63→198) not taken.
|
1756 | const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes()); |
224 |
1/2✓ Branch 0 (64→65) taken 1756 times.
✗ Branch 1 (64→196) not taken.
|
1756 | const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature); |
225 |
1/2✗ Branch 0 (67→68) not taken.
✓ Branch 1 (67→69) taken 1756 times.
|
1756 | assert(structSymbol != nullptr); |
226 | |||
227 | // Collect concrete field types | ||
228 | llvm::StructType *structType; | ||
229 | 1756 | std::vector<llvm::Type *> fieldTypes; | |
230 | 1756 | bool isPacked = false; | |
231 |
2/2✓ Branch 0 (70→71) taken 1558 times.
✓ Branch 1 (70→132) taken 198 times.
|
1756 | if (is(TY_STRUCT)) { // Struct |
232 |
2/4✓ Branch 0 (71→72) taken 1558 times.
✗ Branch 1 (71→187) not taken.
✓ Branch 2 (72→73) taken 1558 times.
✗ Branch 3 (72→187) not taken.
|
1558 | const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode); |
233 |
1/2✗ Branch 0 (73→74) not taken.
✓ Branch 1 (73→75) taken 1558 times.
|
1558 | assert(spiceStruct != nullptr); |
234 |
1/2✓ Branch 0 (75→76) taken 1558 times.
✗ Branch 1 (75→187) not taken.
|
1558 | const std::string mangledName = NameMangling::mangleStruct(*spiceStruct); |
235 |
1/2✓ Branch 0 (77→78) taken 1558 times.
✗ Branch 1 (77→167) not taken.
|
1558 | structType = llvm::StructType::create(context, mangledName); |
236 | |||
237 |
1/2✓ Branch 0 (78→79) taken 1558 times.
✗ Branch 1 (78→185) not taken.
|
1558 | const size_t totalFieldCount = spiceStruct->scope->getFieldCount(); |
238 |
1/2✓ Branch 0 (79→80) taken 1558 times.
✗ Branch 1 (79→185) not taken.
|
1558 | 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 1558 times.
✗ Branch 1 (80→185) not taken.
✗ Branch 2 (81→82) not taken.
✓ Branch 3 (81→83) taken 1558 times.
|
1558 | assert(structSymbol->declNode->isStructDef()); |
242 |
1/2✓ Branch 0 (83→84) taken 1558 times.
✗ Branch 1 (83→85) not taken.
|
1558 | const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode); |
243 |
4/4✓ Branch 0 (90→91) taken 1257 times.
✓ Branch 1 (90→95) taken 301 times.
✓ Branch 2 (91→92) taken 41 times.
✓ Branch 3 (91→95) taken 1216 times.
|
1558 | if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable) |
244 |
2/4✓ Branch 0 (92→93) taken 41 times.
✗ Branch 1 (92→168) not taken.
✓ Branch 2 (93→94) taken 41 times.
✗ Branch 3 (93→168) not taken.
|
41 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
245 | |||
246 | // Collect all field types | ||
247 |
2/2✓ Branch 0 (108→96) taken 4023 times.
✓ Branch 1 (108→109) taken 1558 times.
|
5581 | for (size_t i = 0; i < totalFieldCount; i++) { |
248 |
1/2✗ Branch 0 (96→97) not taken.
✓ Branch 1 (96→98) taken 4023 times.
|
4023 | const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i); |
249 |
1/2✗ Branch 0 (101→102) not taken.
✓ Branch 1 (101→103) taken 4023 times.
|
4023 | assert(fieldSymbol != nullptr); |
250 |
3/6✓ Branch 0 (103→104) taken 4023 times.
✗ Branch 1 (103→169) not taken.
✓ Branch 2 (105→106) taken 4023 times.
✗ Branch 3 (105→169) not taken.
✓ Branch 4 (106→107) taken 4023 times.
✗ Branch 5 (106→169) not taken.
|
4023 | 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 42 times.
✓ Branch 1 (109→116) taken 1516 times.
✓ Branch 2 (112→113) taken 42 times.
✗ Branch 3 (112→170) not taken.
✓ Branch 4 (113→114) taken 42 times.
✗ Branch 5 (113→170) not taken.
✓ Branch 6 (114→115) taken 1 times.
✓ Branch 7 (114→116) taken 41 times.
✓ Branch 8 (117→118) taken 42 times.
✓ Branch 9 (117→119) taken 1516 times.
✓ Branch 10 (119→120) taken 42 times.
✓ Branch 11 (119→122) taken 1516 times.
✓ Branch 12 (122→123) taken 1 times.
✓ Branch 13 (122→130) taken 1557 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.
|
1642 | 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 | 1558 | } else { // Interface | |
257 |
2/4✓ Branch 0 (132→133) taken 198 times.
✗ Branch 1 (132→192) not taken.
✓ Branch 2 (133→134) taken 198 times.
✗ Branch 3 (133→192) not taken.
|
198 | const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode); |
258 |
1/2✗ Branch 0 (134→135) not taken.
✓ Branch 1 (134→136) taken 198 times.
|
198 | assert(spiceInterface != nullptr); |
259 |
1/2✓ Branch 0 (136→137) taken 198 times.
✗ Branch 1 (136→192) not taken.
|
198 | const std::string mangledName = NameMangling::mangleInterface(*spiceInterface); |
260 |
1/2✓ Branch 0 (138→139) taken 198 times.
✗ Branch 1 (138→188) not taken.
|
198 | structType = llvm::StructType::create(context, mangledName); |
261 | |||
262 |
2/4✓ Branch 0 (139→140) taken 198 times.
✗ Branch 1 (139→189) not taken.
✓ Branch 2 (140→141) taken 198 times.
✗ Branch 3 (140→189) not taken.
|
198 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
263 | 198 | } | |
264 | |||
265 | // Set field types to struct type | ||
266 |
1/2✓ Branch 0 (144→145) taken 1756 times.
✗ Branch 1 (144→193) not taken.
|
1756 | structType->setBody(fieldTypes, isPacked); |
267 | |||
268 | 1756 | return structType; | |
269 | 1756 | } | |
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, 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 | 614086 | bool Type::isBase(SuperType superType) const { | |
286 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 614086 times.
|
614086 | assert(!typeChain.empty()); |
287 | 614086 | 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 98568 times.
✗ Branch 1 (2→6) not taken.
|
98568 | 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 |
6/8✓ Branch 0 (2→3) taken 77711 times.
✗ Branch 1 (2→11) not taken.
✓ Branch 2 (3→4) taken 23249 times.
✓ Branch 3 (3→6) taken 54462 times.
✓ Branch 4 (4→5) taken 23249 times.
✗ Branch 5 (4→11) not taken.
✓ Branch 6 (5→6) taken 20616 times.
✓ Branch 7 (5→7) taken 2633 times.
|
77711 | bool Type::isExtendedPrimitive() const { return isPrimitive() || isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}); } |
307 | |||
308 | /** | ||
309 | * Check if the current type is a pointer type | ||
310 | * | ||
311 | * @return Pointer type or not | ||
312 | */ | ||
313 | 245647 | 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 | 840219 | 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 | 126012 | 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 | 86576 | bool Type::isSameContainerTypeAs(const Type *other) const { | |
337 |
4/4✓ Branch 0 (3→4) taken 1921 times.
✓ Branch 1 (3→7) taken 84655 times.
✓ Branch 2 (5→6) taken 1756 times.
✓ Branch 3 (5→7) taken 165 times.
|
86576 | const bool bothPtr = isPtr() && other->isPtr(); |
338 |
4/4✓ Branch 0 (9→10) taken 3522 times.
✓ Branch 1 (9→13) taken 83054 times.
✓ Branch 2 (11→12) taken 3417 times.
✓ Branch 3 (11→13) taken 105 times.
|
86576 | const bool bothRef = isRef() && other->isRef(); |
339 |
3/4✓ Branch 0 (15→16) taken 52 times.
✓ Branch 1 (15→19) taken 86524 times.
✓ Branch 2 (17→18) taken 52 times.
✗ Branch 3 (17→19) not taken.
|
86576 | const bool bothArray = isArray() && other->isArray(); |
340 |
6/6✓ Branch 0 (20→21) taken 84820 times.
✓ Branch 1 (20→23) taken 1756 times.
✓ Branch 2 (21→22) taken 81403 times.
✓ Branch 3 (21→23) taken 3417 times.
✓ Branch 4 (22→23) taken 52 times.
✓ Branch 5 (22→24) taken 81351 times.
|
86576 | return bothPtr || bothRef || bothArray; |
341 | } | ||
342 | |||
343 | /** | ||
344 | * Retrieve the base type of the current type | ||
345 | * | ||
346 | * @return Base type | ||
347 | */ | ||
348 | 1041384 | const Type *Type::getBase() const { | |
349 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 1041384 times.
|
1041384 | assert(!typeChain.empty()); |
350 | |||
351 | // Create new type chain | ||
352 |
3/6✓ Branch 0 (9→10) taken 1041384 times.
✗ Branch 1 (9→19) not taken.
✓ Branch 2 (12→13) taken 1041384 times.
✓ Branch 3 (12→14) taken 1041384 times.
✗ Branch 4 (23→24) not taken.
✗ Branch 5 (23→25) not taken.
|
3124152 | const TypeChain newTypeChain = {typeChain.front()}; |
353 | |||
354 | // Register new type or return if already registered | ||
355 |
1/2✓ Branch 0 (14→15) taken 1041384 times.
✗ Branch 1 (14→32) not taken.
|
2082768 | return TypeRegistry::getOrInsert(newTypeChain); |
356 |
1/6✓ Branch 0 (6→7) taken 1041384 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.
|
2082768 | } |
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 | 21438 | const Type *Type::getWithBodyScope(Scope *bodyScope) const { | |
380 |
3/6✓ Branch 0 (2→3) taken 21438 times.
✗ Branch 1 (2→16) not taken.
✓ Branch 2 (3→4) taken 21438 times.
✗ Branch 3 (3→13) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 21438 times.
|
21438 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE})); |
381 | |||
382 | // Create new type chain | ||
383 |
1/2✓ Branch 0 (6→7) taken 21438 times.
✗ Branch 1 (6→16) not taken.
|
21438 | TypeChain newTypeChain = typeChain; |
384 | 21438 | newTypeChain.front().data.bodyScope = bodyScope; | |
385 | |||
386 | // Register new type or return if already registered | ||
387 |
1/2✓ Branch 0 (8→9) taken 21438 times.
✗ Branch 1 (8→14) not taken.
|
42876 | return TypeRegistry::getOrInsert(newTypeChain); |
388 | 21438 | } | |
389 | |||
390 | /** | ||
391 | * Retrieve the same type, but with the given template types | ||
392 | * | ||
393 | * @return Type with new template types | ||
394 | */ | ||
395 | 3437 | const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const { | |
396 |
2/4✓ Branch 0 (2→3) taken 3437 times.
✗ Branch 1 (2→8) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 3437 times.
|
3437 | assert(isOneOf({TY_STRUCT, TY_INTERFACE})); |
397 | 3437 | 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 | 7606 | const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const { | |
406 |
3/6✓ Branch 0 (2→3) taken 7606 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 7606 times.
✗ Branch 3 (3→14) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 7606 times.
|
7606 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE})); |
407 | |||
408 | // Create new type chain | ||
409 |
1/2✓ Branch 0 (6→7) taken 7606 times.
✗ Branch 1 (6→17) not taken.
|
7606 | TypeChain newTypeChain = typeChain; |
410 |
1/2✓ Branch 0 (8→9) taken 7606 times.
✗ Branch 1 (8→15) not taken.
|
7606 | newTypeChain.front().templateTypes = templateTypes; |
411 | |||
412 | // Register new type or return if already registered | ||
413 |
1/2✓ Branch 0 (9→10) taken 7606 times.
✗ Branch 1 (9→15) not taken.
|
15212 | return TypeRegistry::getOrInsert(newTypeChain); |
414 | 7606 | } | |
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 | 12517 | const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList ¶mAndReturnTypes) const { | |
422 |
3/6✓ Branch 0 (2→3) taken 12517 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 12517 times.
✗ Branch 3 (3→14) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→6) taken 12517 times.
|
12517 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
423 | |||
424 | // Create new type chain | ||
425 |
1/2✓ Branch 0 (6→7) taken 12517 times.
✗ Branch 1 (6→17) not taken.
|
12517 | TypeChain newTypeChain = typeChain; |
426 |
1/2✓ Branch 0 (8→9) taken 12517 times.
✗ Branch 1 (8→15) not taken.
|
12517 | newTypeChain.front().paramTypes = paramAndReturnTypes; |
427 | |||
428 | // Register new type or return if already registered | ||
429 |
1/2✓ Branch 0 (9→10) taken 12517 times.
✗ Branch 1 (9→15) not taken.
|
25034 | return TypeRegistry::getOrInsert(newTypeChain); |
430 | 12517 | } | |
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 | 303311 | bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion) | |
438 |
1/2✓ Branch 0 (2→3) taken 303311 times.
✗ Branch 1 (2→34) not taken.
|
303311 | const Type *baseType = getBase(); |
439 | |||
440 | // Check if the type itself is generic | ||
441 |
2/2✓ Branch 0 (4→5) taken 49353 times.
✓ Branch 1 (4→6) taken 253958 times.
|
303311 | if (baseType->is(TY_GENERIC)) |
442 | 49353 | return true; | |
443 | |||
444 | // Check if the type has generic template types | ||
445 |
1/2✓ Branch 0 (7→8) taken 253958 times.
✗ Branch 1 (7→34) not taken.
|
253958 | const auto templateTypes = baseType->getTemplateTypes(); |
446 |
3/4✓ Branch 0 (8→9) taken 253958 times.
✗ Branch 1 (8→32) not taken.
✓ Branch 2 (9→10) taken 18667 times.
✓ Branch 3 (9→11) taken 235291 times.
|
309308 | if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
447 | 18667 | return true; | |
448 | |||
449 | // Check param and return types or functions/procedures | ||
450 |
3/4✓ Branch 0 (11→12) taken 235291 times.
✗ Branch 1 (11→28) not taken.
✓ Branch 2 (12→13) taken 385 times.
✓ Branch 3 (12→24) taken 234906 times.
|
235291 | if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
451 |
2/4✓ Branch 0 (13→14) taken 385 times.
✗ Branch 1 (13→31) not taken.
✓ Branch 2 (14→15) taken 385 times.
✗ Branch 3 (14→31) not taken.
|
385 | const auto paramTypes = baseType->getFunctionParamAndReturnTypes(); |
452 |
3/4✓ Branch 0 (15→16) taken 385 times.
✗ Branch 1 (15→29) not taken.
✓ Branch 2 (16→17) taken 45 times.
✓ Branch 3 (16→18) taken 340 times.
|
929 | if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
453 | 45 | return true; | |
454 |
2/2✓ Branch 0 (20→21) taken 340 times.
✓ Branch 1 (20→23) taken 45 times.
|
385 | } |
455 | |||
456 | 235246 | return false; // Does not have generic parts | |
457 | 253958 | } | |
458 | |||
459 | /** | ||
460 | * Retrieve template types of the current type | ||
461 | * | ||
462 | * @return Vector of template types | ||
463 | */ | ||
464 | 337866 | 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 | 5819629 | 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 | 1266155 | bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const { | |
479 | 3997539 | 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 | * @param ignorePublic Ignore any potential public qualifier | ||
488 | * @return Symbol type name | ||
489 | */ | ||
490 | 400122 | void Type::getName(std::stringstream &name, bool withSize, bool ignorePublic) const { // NOLINT(misc-no-recursion) | |
491 | // Loop through all chain elements | ||
492 |
2/2✓ Branch 0 (10→4) taken 501767 times.
✓ Branch 1 (10→11) taken 400122 times.
|
901889 | for (const TypeChainElement &chainElement : typeChain) |
493 |
2/4✓ Branch 0 (5→6) taken 501767 times.
✗ Branch 1 (5→14) not taken.
✓ Branch 2 (6→7) taken 501767 times.
✗ Branch 3 (6→12) not taken.
|
501767 | name << chainElement.getName(withSize, ignorePublic); |
494 | 400122 | } | |
495 | |||
496 | /** | ||
497 | * Get the name of the symbol type as a string | ||
498 | * | ||
499 | * @param withSize Include the array size for sized types | ||
500 | * @param ignorePublic Ignore any potential public qualifier | ||
501 | * @return Symbol type name | ||
502 | */ | ||
503 | 14276 | std::string Type::getName(bool withSize, bool ignorePublic) const { | |
504 |
1/2✓ Branch 0 (2→3) taken 14276 times.
✗ Branch 1 (2→11) not taken.
|
14276 | std::stringstream name; |
505 |
1/2✓ Branch 0 (3→4) taken 14276 times.
✗ Branch 1 (3→9) not taken.
|
14276 | getName(name, withSize, ignorePublic); |
506 |
1/2✓ Branch 0 (4→5) taken 14276 times.
✗ Branch 1 (4→9) not taken.
|
28552 | return name.str(); |
507 | 14276 | } | |
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 | 435 | const QualTypeList &Type::getFunctionParamAndReturnTypes() const { | |
548 |
2/4✓ Branch 0 (3→4) taken 435 times.
✗ Branch 1 (3→9) not taken.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 435 times.
|
435 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
549 | 435 | 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 | 101417 | 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 12949 times.
✓ Branch 1 (4→6) taken 88468 times.
|
101417 | if (typeChain.size() != otherType->typeChain.size()) |
563 | 12949 | return false; | |
564 | |||
565 | // Compare the elements | ||
566 |
2/2✓ Branch 0 (18→7) taken 95463 times.
✓ Branch 1 (18→19) taken 56613 times.
|
152076 | for (size_t i = 0; i < typeChain.size(); i++) { |
567 | 95463 | const TypeChainElement &lhsElement = typeChain.at(i); | |
568 | 95463 | const TypeChainElement &rhsElement = otherType->typeChain.at(i); | |
569 | |||
570 | // Ignore differences in array size | ||
571 |
3/6✓ Branch 0 (9→10) taken 58376 times.
✓ Branch 1 (9→13) taken 37087 times.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (10→13) taken 58376 times.
✗ Branch 4 (11→12) not taken.
✗ Branch 5 (11→13) not taken.
|
95463 | 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 31855 times.
✓ Branch 1 (14→16) taken 63608 times.
|
95463 | if (lhsElement != rhsElement) |
576 | 31855 | return false; | |
577 | } | ||
578 | |||
579 | 56613 | 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 | 79075 | 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 33508 times.
✓ Branch 1 (3→7) taken 45567 times.
✓ Branch 2 (5→6) taken 30097 times.
✓ Branch 3 (5→7) taken 3411 times.
✓ Branch 4 (8→9) taken 30097 times.
✓ Branch 5 (8→11) taken 48978 times.
|
79075 | if (typeA->isRef() && !typeB->isRef()) |
592 | 30097 | typeA = typeA->removeReferenceWrapper(); | |
593 | |||
594 | // Remove reference wrapper of requested type if required | ||
595 |
8/8✓ Branch 0 (12→13) taken 75664 times.
✓ Branch 1 (12→19) taken 3411 times.
✓ Branch 2 (14→15) taken 2892 times.
✓ Branch 3 (14→19) taken 72772 times.
✓ Branch 4 (17→18) taken 2466 times.
✓ Branch 5 (17→19) taken 426 times.
✓ Branch 6 (20→21) taken 2466 times.
✓ Branch 7 (20→23) taken 76609 times.
|
79075 | if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC)) |
596 | 2466 | typeB = typeB->removeReferenceWrapper(); | |
597 | |||
598 | // Unwrap both types as far as possible | ||
599 |
2/2✓ Branch 0 (28→24) taken 5094 times.
✓ Branch 1 (28→29) taken 79075 times.
|
84169 | while (typeA->isSameContainerTypeAs(typeB)) { |
600 | 5094 | typeB = typeB->getContained(); | |
601 | 5094 | typeA = typeA->getContained(); | |
602 | } | ||
603 | 79075 | } | |
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 | 17926 | bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) { | |
613 | 17926 | return typeA->typeChain.size() == typeB->typeChain.size(); | |
614 | } | ||
615 | |||
616 | } // namespace spice::compiler | ||
617 |