| 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 5 → 6 taken 4739632 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 4739632 times.
✓ Branch 7 → 9 taken 4739632 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 19 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
|
14218896 | Type::Type(SuperType superType) : typeChain({TypeChainElement{superType}}) {} |
| 23 | |||
| 24 |
4/12✓ Branch 4 → 5 taken 1705 times.
✗ Branch 4 → 19 not taken.
✓ Branch 6 → 7 taken 1705 times.
✗ Branch 6 → 13 not taken.
✓ Branch 8 → 9 taken 1705 times.
✓ Branch 8 → 10 taken 1705 times.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 24 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
|
5115 | Type::Type(SuperType superType, const std::string &subType) : typeChain({TypeChainElement{superType, subType}}) {} |
| 25 | |||
| 26 | 1123 | Type::Type(SuperType superType, const std::string &subType, uint64_t typeId, const TypeChainElementData &data, | |
| 27 | 1123 | const QualTypeList &templateTypes) | |
| 28 |
5/14✓ Branch 4 → 5 taken 1123 times.
✗ Branch 4 → 24 not taken.
✓ Branch 5 → 6 taken 1123 times.
✗ Branch 5 → 21 not taken.
✓ Branch 7 → 8 taken 1123 times.
✗ Branch 7 → 15 not taken.
✓ Branch 9 → 10 taken 1123 times.
✓ Branch 9 → 11 taken 1123 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 29 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 29 not taken.
|
3369 | : typeChain({TypeChainElement(superType, subType, typeId, data, templateTypes)}) {} |
| 29 | |||
| 30 | 1317262 | 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 | 8277020 | SuperType Type::getSuperType() const { | |
| 38 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 8277020 times.
|
8277020 | assert(!typeChain.empty()); |
| 39 | 8277020 | return typeChain.back().superType; | |
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Get the sub type of the current type | ||
| 44 | * | ||
| 45 | * @return Sub type | ||
| 46 | */ | ||
| 47 | 198002 | const std::string &Type::getSubType() const { | |
| 48 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 198002 times.
|
198002 | assert(!typeChain.empty()); |
| 49 |
2/4✓ Branch 5 → 6 taken 198002 times.
✗ Branch 5 → 11 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 198002 times.
|
198002 | assert(isOneOf({TY_STRUCT, TY_INTERFACE, TY_ENUM, TY_GENERIC})); |
| 50 | 198002 | 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 3 → 4 not taken.
✓ Branch 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 | 147926 | Scope *Type::getBodyScope() const { | |
| 69 |
2/4✓ Branch 2 → 3 taken 147926 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 147926 times.
|
147926 | assert(isOneOf({TY_STRUCT, TY_INTERFACE})); |
| 70 | 147926 | 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 | 15340 | const Type *Type::toPtr(const ASTNode *node) const { | |
| 80 | // Do not allow pointers of dyn | ||
| 81 |
2/2✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 12 taken 15338 times.
|
15340 | if (is(TY_DYN)) |
| 82 |
2/4✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 32 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 29 not taken.
|
6 | throw SemanticError(node, DYN_POINTERS_NOT_ALLOWED, "Just use the dyn type without '*' instead"); |
| 83 |
1/2✗ Branch 13 → 14 not taken.
✓ Branch 13 → 22 taken 15338 times.
|
15338 | 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 22 → 23 taken 15338 times.
✗ Branch 22 → 50 not taken.
|
15338 | TypeChain newTypeChain = typeChain; |
| 88 |
1/2✓ Branch 23 → 24 taken 15338 times.
✗ Branch 23 → 47 not taken.
|
15338 | newTypeChain.emplace_back(TY_PTR); |
| 89 | |||
| 90 | // Register new type or return if already registered | ||
| 91 |
1/2✓ Branch 24 → 25 taken 15338 times.
✗ Branch 24 → 48 not taken.
|
30676 | return TypeRegistry::getOrInsert(newTypeChain); |
| 92 | 15338 | } | |
| 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 | 11763 | const Type *Type::toRef(const ASTNode *node) const { | |
| 101 | // Do not allow references of dyn | ||
| 102 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 12 taken 11763 times.
|
11763 | 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 13 → 14 not taken.
✓ Branch 13 → 22 taken 11763 times.
|
11763 | 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 22 → 23 taken 11763 times.
✗ Branch 22 → 50 not taken.
|
11763 | TypeChain newTypeChain = typeChain; |
| 110 |
1/2✓ Branch 23 → 24 taken 11763 times.
✗ Branch 23 → 47 not taken.
|
11763 | newTypeChain.emplace_back(TY_REF); |
| 111 | |||
| 112 | // Register new type or return if already registered | ||
| 113 |
1/2✓ Branch 24 → 25 taken 11763 times.
✗ Branch 24 → 48 not taken.
|
23526 | return TypeRegistry::getOrInsert(newTypeChain); |
| 114 | 11763 | } | |
| 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 2 → 3 taken 146 times.
✓ Branch 2 → 6 taken 72 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 145 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 16 taken 217 times.
|
218 | if (!skipDynCheck && typeChain.back().superType == TY_DYN) |
| 127 |
2/4✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 26 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 23 not taken.
|
3 | throw SemanticError(node, DYN_ARRAYS_NOT_ALLOWED, "Just use the dyn type without '[]' instead"); |
| 128 | |||
| 129 | // Create new type chain | ||
| 130 |
1/2✓ Branch 16 → 17 taken 217 times.
✗ Branch 16 → 36 not taken.
|
217 | TypeChain newTypeChain = typeChain; |
| 131 |
1/2✓ Branch 17 → 18 taken 217 times.
✗ Branch 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 18 → 19 taken 217 times.
✗ Branch 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 | 103345 | const Type *Type::getContained() const { | |
| 143 |
2/2✓ Branch 3 → 4 taken 1406 times.
✓ Branch 3 → 6 taken 101939 times.
|
103345 | if (is(TY_STRING)) |
| 144 |
1/2✓ Branch 4 → 5 taken 1406 times.
✗ Branch 4 → 18 not taken.
|
1406 | return TypeRegistry::getOrInsert(TY_CHAR); |
| 145 | |||
| 146 | // Create new type chain | ||
| 147 |
1/2✓ Branch 6 → 7 taken 101939 times.
✗ Branch 6 → 18 not taken.
|
101939 | TypeChain newTypeChain = typeChain; |
| 148 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 101939 times.
|
101939 | assert(newTypeChain.size() > 1); |
| 149 | 101939 | newTypeChain.pop_back(); | |
| 150 | |||
| 151 | // Register new type or return if already registered | ||
| 152 |
1/2✓ Branch 11 → 12 taken 101939 times.
✗ Branch 11 → 16 not taken.
|
101939 | return TypeRegistry::getOrInsert(newTypeChain); |
| 153 | 101939 | } | |
| 154 | |||
| 155 | /** | ||
| 156 | * Replace the base type with another one | ||
| 157 | * | ||
| 158 | * @param newBaseType New base type | ||
| 159 | * @return The new type | ||
| 160 | */ | ||
| 161 | 16101 | const Type *Type::replaceBase(const Type *newBaseType) const { | |
| 162 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 16101 times.
|
16101 | assert(!typeChain.empty()); |
| 163 | |||
| 164 | // Create new type | ||
| 165 |
1/2✓ Branch 5 → 6 taken 16101 times.
✗ Branch 5 → 27 not taken.
|
16101 | TypeChain newTypeChain = newBaseType->typeChain; |
| 166 |
4/4✓ Branch 7 → 8 taken 971 times.
✓ Branch 7 → 11 taken 15130 times.
✓ Branch 9 → 10 taken 42 times.
✓ Branch 9 → 11 taken 929 times.
|
16101 | const bool doubleRef = newTypeChain.back().superType == TY_REF && typeChain.back().superType == TY_REF; |
| 167 |
2/2✓ Branch 19 → 13 taken 1720 times.
✓ Branch 19 → 20 taken 16101 times.
|
17821 | for (size_t i = 1; i < typeChain.size(); i++) |
| 168 |
3/4✓ Branch 13 → 14 taken 42 times.
✓ Branch 13 → 15 taken 1678 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 42 times.
|
1720 | if (!doubleRef || i > 1) |
| 169 |
2/4✓ Branch 15 → 16 taken 1678 times.
✗ Branch 15 → 25 not taken.
✓ Branch 16 → 17 taken 1678 times.
✗ Branch 16 → 25 not taken.
|
1678 | newTypeChain.push_back(typeChain.at(i)); |
| 170 | |||
| 171 | // Register new type or return if already registered | ||
| 172 |
1/2✓ Branch 20 → 21 taken 16101 times.
✗ Branch 20 → 25 not taken.
|
32202 | return TypeRegistry::getOrInsert(newTypeChain); |
| 173 | 16101 | } | |
| 174 | |||
| 175 | /** | ||
| 176 | * Remove reference wrapper from the current type | ||
| 177 | * | ||
| 178 | * @return Type without reference wrapper | ||
| 179 | */ | ||
| 180 |
1/2✓ Branch 3 → 4 taken 33812 times.
✗ Branch 3 → 6 not taken.
|
33812 | 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 | 7073 | llvm::Type *Type::toLLVMType(SourceFile *sourceFile) const { // NOLINT(misc-no-recursion) | |
| 189 |
2/4✓ Branch 3 → 4 taken 7073 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 7073 times.
✗ Branch 5 → 7 not taken.
|
7073 | assert(!typeChain.empty() && !is(TY_INVALID)); |
| 190 | 7073 | llvm::LLVMContext &context = sourceFile->llvmModule->getContext(); | |
| 191 | |||
| 192 |
10/12✓ Branch 10 → 11 taken 7073 times.
✗ Branch 10 → 163 not taken.
✓ Branch 11 → 12 taken 3919 times.
✓ Branch 11 → 16 taken 3154 times.
✓ Branch 13 → 14 taken 57 times.
✓ Branch 13 → 17 taken 3862 times.
✓ Branch 14 → 15 taken 57 times.
✗ Branch 14 → 163 not taken.
✓ Branch 15 → 16 taken 21 times.
✓ Branch 15 → 17 taken 36 times.
✓ Branch 18 → 19 taken 3175 times.
✓ Branch 18 → 21 taken 3898 times.
|
7073 | if (isOneOf({TY_PTR, TY_REF, TY_STRING}) || (isArray() && getArraySize() == 0)) |
| 193 | 3175 | return llvm::PointerType::get(context, 0); | |
| 194 | |||
| 195 |
2/2✓ Branch 22 → 23 taken 36 times.
✓ Branch 22 → 31 taken 3862 times.
|
3898 | if (isArray()) { |
| 196 |
1/2✗ Branch 24 → 25 not taken.
✓ Branch 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 32 → 33 not taken.
✓ Branch 32 → 34 taken 3862 times.
|
3862 | assert(!hasAnyGenericParts()); |
| 202 | |||
| 203 |
2/2✓ Branch 35 → 36 taken 75 times.
✓ Branch 35 → 38 taken 3787 times.
|
3862 | if (is(TY_DOUBLE)) |
| 204 | 75 | return llvm::Type::getDoubleTy(context); | |
| 205 | |||
| 206 |
3/4✓ Branch 38 → 39 taken 3787 times.
✗ Branch 38 → 164 not taken.
✓ Branch 39 → 40 taken 594 times.
✓ Branch 39 → 42 taken 3193 times.
|
3787 | if (isOneOf({TY_INT, TY_ENUM})) |
| 207 | 594 | return llvm::Type::getInt32Ty(context); | |
| 208 | |||
| 209 |
2/2✓ Branch 43 → 44 taken 66 times.
✓ Branch 43 → 46 taken 3127 times.
|
3193 | if (is(TY_SHORT)) |
| 210 | 66 | return llvm::Type::getInt16Ty(context); | |
| 211 | |||
| 212 |
2/2✓ Branch 47 → 48 taken 395 times.
✓ Branch 47 → 50 taken 2732 times.
|
3127 | if (is(TY_LONG)) |
| 213 | 395 | return llvm::Type::getInt64Ty(context); | |
| 214 | |||
| 215 |
3/4✓ Branch 50 → 51 taken 2732 times.
✗ Branch 50 → 165 not taken.
✓ Branch 51 → 52 taken 272 times.
✓ Branch 51 → 54 taken 2460 times.
|
2732 | if (isOneOf({TY_CHAR, TY_BYTE})) |
| 216 | 272 | return llvm::Type::getInt8Ty(context); | |
| 217 | |||
| 218 |
2/2✓ Branch 55 → 56 taken 459 times.
✓ Branch 55 → 58 taken 2001 times.
|
2460 | if (is(TY_BOOL)) |
| 219 | 459 | return llvm::Type::getInt1Ty(context); | |
| 220 | |||
| 221 |
3/4✓ Branch 58 → 59 taken 2001 times.
✗ Branch 58 → 166 not taken.
✓ Branch 59 → 60 taken 1924 times.
✓ Branch 59 → 148 taken 77 times.
|
2001 | if (isOneOf({TY_STRUCT, TY_INTERFACE})) { |
| 222 |
1/2✓ Branch 60 → 61 taken 1924 times.
✗ Branch 60 → 198 not taken.
|
1924 | const Scope *structBodyScope = getBodyScope(); |
| 223 |
2/4✓ Branch 62 → 63 taken 1924 times.
✗ Branch 62 → 198 not taken.
✓ Branch 63 → 64 taken 1924 times.
✗ Branch 63 → 198 not taken.
|
1924 | const std::string structSignature = Struct::getSignature(getSubType(), getTemplateTypes()); |
| 224 |
1/2✓ Branch 64 → 65 taken 1924 times.
✗ Branch 64 → 196 not taken.
|
1924 | const SymbolTableEntry *structSymbol = structBodyScope->parent->lookupStrict(structSignature); |
| 225 |
1/2✗ Branch 67 → 68 not taken.
✓ Branch 67 → 69 taken 1924 times.
|
1924 | assert(structSymbol != nullptr); |
| 226 | |||
| 227 | // Collect concrete field types | ||
| 228 | llvm::StructType *structType; | ||
| 229 | 1924 | std::vector<llvm::Type *> fieldTypes; | |
| 230 | 1924 | bool isPacked = false; | |
| 231 |
2/2✓ Branch 70 → 71 taken 1686 times.
✓ Branch 70 → 132 taken 238 times.
|
1924 | if (is(TY_STRUCT)) { // Struct |
| 232 |
2/4✓ Branch 71 → 72 taken 1686 times.
✗ Branch 71 → 187 not taken.
✓ Branch 72 → 73 taken 1686 times.
✗ Branch 72 → 187 not taken.
|
1686 | const Struct *spiceStruct = structSymbol->getQualType().getStruct(structSymbol->declNode); |
| 233 |
1/2✗ Branch 73 → 74 not taken.
✓ Branch 73 → 75 taken 1686 times.
|
1686 | assert(spiceStruct != nullptr); |
| 234 |
1/2✓ Branch 75 → 76 taken 1686 times.
✗ Branch 75 → 187 not taken.
|
1686 | const std::string mangledName = NameMangling::mangleStruct(*spiceStruct); |
| 235 |
1/2✓ Branch 77 → 78 taken 1686 times.
✗ Branch 77 → 167 not taken.
|
1686 | structType = llvm::StructType::create(context, mangledName); |
| 236 | |||
| 237 |
1/2✓ Branch 78 → 79 taken 1686 times.
✗ Branch 78 → 185 not taken.
|
1686 | const size_t totalFieldCount = spiceStruct->scope->getFieldCount(); |
| 238 |
1/2✓ Branch 79 → 80 taken 1686 times.
✗ Branch 79 → 185 not taken.
|
1686 | 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 80 → 81 taken 1686 times.
✗ Branch 80 → 185 not taken.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 1686 times.
|
1686 | assert(structSymbol->declNode->isStructDef()); |
| 242 |
1/2✓ Branch 83 → 84 taken 1686 times.
✗ Branch 83 → 85 not taken.
|
1686 | const auto structDeclNode = spice_pointer_cast<StructDefNode *>(structSymbol->declNode); |
| 243 |
4/4✓ Branch 90 → 91 taken 1346 times.
✓ Branch 90 → 95 taken 340 times.
✓ Branch 91 → 92 taken 43 times.
✓ Branch 91 → 95 taken 1303 times.
|
1686 | if (!structDeclNode->hasInterfaces && structDeclNode->emitVTable) |
| 244 |
2/4✓ Branch 92 → 93 taken 43 times.
✗ Branch 92 → 168 not taken.
✓ Branch 93 → 94 taken 43 times.
✗ Branch 93 → 168 not taken.
|
43 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
| 245 | |||
| 246 | // Collect all field types | ||
| 247 |
2/2✓ Branch 108 → 96 taken 4345 times.
✓ Branch 108 → 109 taken 1686 times.
|
6031 | for (size_t i = 0; i < totalFieldCount; i++) { |
| 248 |
1/2✗ Branch 96 → 97 not taken.
✓ Branch 96 → 98 taken 4345 times.
|
4345 | const SymbolTableEntry *fieldSymbol = spiceStruct->scope->lookupField(i); |
| 249 |
1/2✗ Branch 101 → 102 not taken.
✓ Branch 101 → 103 taken 4345 times.
|
4345 | assert(fieldSymbol != nullptr); |
| 250 |
3/6✓ Branch 103 → 104 taken 4345 times.
✗ Branch 103 → 169 not taken.
✓ Branch 105 → 106 taken 4345 times.
✗ Branch 105 → 169 not taken.
✓ Branch 106 → 107 taken 4345 times.
✗ Branch 106 → 169 not taken.
|
4345 | fieldTypes.push_back(sourceFile->getLLVMType(fieldSymbol->getQualType().getType())); |
| 251 | } | ||
| 252 | |||
| 253 | // Check if the struct is declared as packed | ||
| 254 |
12/18✓ Branch 109 → 110 taken 44 times.
✓ Branch 109 → 116 taken 1642 times.
✓ Branch 112 → 113 taken 44 times.
✗ Branch 112 → 170 not taken.
✓ Branch 113 → 114 taken 44 times.
✗ Branch 113 → 170 not taken.
✓ Branch 114 → 115 taken 1 time.
✓ Branch 114 → 116 taken 43 times.
✓ Branch 117 → 118 taken 44 times.
✓ Branch 117 → 119 taken 1642 times.
✓ Branch 119 → 120 taken 44 times.
✓ Branch 119 → 122 taken 1642 times.
✓ Branch 122 → 123 taken 1 time.
✓ Branch 122 → 130 taken 1685 times.
✗ Branch 170 → 171 not taken.
✗ Branch 170 → 172 not taken.
✗ Branch 174 → 175 not taken.
✗ Branch 174 → 177 not taken.
|
1774 | if (structDeclNode->attrs && structDeclNode->attrs->attrLst->hasAttr(ATTR_CORE_COMPILER_PACKED)) |
| 255 |
2/4✓ Branch 125 → 126 taken 1 time.
✗ Branch 125 → 181 not taken.
✓ Branch 126 → 127 taken 1 time.
✗ Branch 126 → 179 not taken.
|
3 | isPacked = structDeclNode->attrs->attrLst->getAttrValueByName(ATTR_CORE_COMPILER_PACKED)->boolValue; |
| 256 | 1686 | } else { // Interface | |
| 257 |
2/4✓ Branch 132 → 133 taken 238 times.
✗ Branch 132 → 192 not taken.
✓ Branch 133 → 134 taken 238 times.
✗ Branch 133 → 192 not taken.
|
238 | const Interface *spiceInterface = structSymbol->getQualType().getInterface(structSymbol->declNode); |
| 258 |
1/2✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 238 times.
|
238 | assert(spiceInterface != nullptr); |
| 259 |
1/2✓ Branch 136 → 137 taken 238 times.
✗ Branch 136 → 192 not taken.
|
238 | const std::string mangledName = NameMangling::mangleInterface(*spiceInterface); |
| 260 |
1/2✓ Branch 138 → 139 taken 238 times.
✗ Branch 138 → 188 not taken.
|
238 | structType = llvm::StructType::create(context, mangledName); |
| 261 | |||
| 262 |
2/4✓ Branch 139 → 140 taken 238 times.
✗ Branch 139 → 189 not taken.
✓ Branch 140 → 141 taken 238 times.
✗ Branch 140 → 189 not taken.
|
238 | fieldTypes.push_back(llvm::PointerType::get(context, 0)); |
| 263 | 238 | } | |
| 264 | |||
| 265 | // Set field types to struct type | ||
| 266 |
1/2✓ Branch 144 → 145 taken 1924 times.
✗ Branch 144 → 193 not taken.
|
1924 | structType->setBody(fieldTypes, isPacked); |
| 267 | |||
| 268 | 1924 | return structType; | |
| 269 | 1924 | } | |
| 270 | |||
| 271 |
2/4✓ Branch 148 → 149 taken 77 times.
✗ Branch 148 → 199 not taken.
✓ Branch 149 → 150 taken 77 times.
✗ Branch 149 → 155 not taken.
|
77 | if (isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
| 272 | 77 | llvm::PointerType *ptrTy = llvm::PointerType::get(context, 0); | |
| 273 |
1/2✓ Branch 152 → 153 taken 77 times.
✗ Branch 152 → 200 not taken.
|
77 | 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 | 651633 | bool Type::isBase(SuperType superType) const { | |
| 286 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 651633 times.
|
651633 | assert(!typeChain.empty()); |
| 287 | 651633 | 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 2 → 3 taken 101904 times.
✗ Branch 2 → 6 not taken.
|
101904 | 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 2 → 3 taken 80105 times.
✗ Branch 2 → 11 not taken.
✓ Branch 3 → 4 taken 24179 times.
✓ Branch 3 → 6 taken 55926 times.
✓ Branch 4 → 5 taken 24179 times.
✗ Branch 4 → 11 not taken.
✓ Branch 5 → 6 taken 21417 times.
✓ Branch 5 → 7 taken 2762 times.
|
80105 | 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 | 254446 | 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 | 889938 | 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 | 131817 | 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 | 90254 | bool Type::isSameContainerTypeAs(const Type *other) const { | |
| 337 |
4/4✓ Branch 3 → 4 taken 1987 times.
✓ Branch 3 → 7 taken 88267 times.
✓ Branch 5 → 6 taken 1812 times.
✓ Branch 5 → 7 taken 175 times.
|
90254 | const bool bothPtr = isPtr() && other->isPtr(); |
| 338 |
4/4✓ Branch 9 → 10 taken 3703 times.
✓ Branch 9 → 13 taken 86551 times.
✓ Branch 11 → 12 taken 3592 times.
✓ Branch 11 → 13 taken 111 times.
|
90254 | const bool bothRef = isRef() && other->isRef(); |
| 339 |
3/4✓ Branch 15 → 16 taken 52 times.
✓ Branch 15 → 19 taken 90202 times.
✓ Branch 17 → 18 taken 52 times.
✗ Branch 17 → 19 not taken.
|
90254 | const bool bothArray = isArray() && other->isArray(); |
| 340 |
6/6✓ Branch 20 → 21 taken 88442 times.
✓ Branch 20 → 23 taken 1812 times.
✓ Branch 21 → 22 taken 84850 times.
✓ Branch 21 → 23 taken 3592 times.
✓ Branch 22 → 23 taken 52 times.
✓ Branch 22 → 24 taken 84798 times.
|
90254 | return bothPtr || bothRef || bothArray; |
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Retrieve the base type of the current type | ||
| 345 | * | ||
| 346 | * @return Base type | ||
| 347 | */ | ||
| 348 | 1127471 | const Type *Type::getBase() const { | |
| 349 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1127471 times.
|
1127471 | assert(!typeChain.empty()); |
| 350 | |||
| 351 | // Create new type chain | ||
| 352 |
3/6✓ Branch 9 → 10 taken 1127471 times.
✗ Branch 9 → 19 not taken.
✓ Branch 12 → 13 taken 1127471 times.
✓ Branch 12 → 14 taken 1127471 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
|
3382413 | const TypeChain newTypeChain = {typeChain.front()}; |
| 353 | |||
| 354 | // Register new type or return if already registered | ||
| 355 |
1/2✓ Branch 14 → 15 taken 1127471 times.
✗ Branch 14 → 32 not taken.
|
2254942 | return TypeRegistry::getOrInsert(newTypeChain); |
| 356 |
1/6✓ Branch 6 → 7 taken 1127471 times.
✗ Branch 6 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 30 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
|
2254942 | } |
| 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 2 → 3 taken 45 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 45 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 45 times.
|
45 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 365 | |||
| 366 | // Create new type chain | ||
| 367 |
1/2✓ Branch 6 → 7 taken 45 times.
✗ Branch 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 8 → 9 taken 45 times.
✗ Branch 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 | 22798 | const Type *Type::getWithBodyScope(Scope *bodyScope) const { | |
| 380 |
3/6✓ Branch 2 → 3 taken 22798 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 22798 times.
✗ Branch 3 → 13 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 22798 times.
|
22798 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE})); |
| 381 | |||
| 382 | // Create new type chain | ||
| 383 |
1/2✓ Branch 6 → 7 taken 22798 times.
✗ Branch 6 → 16 not taken.
|
22798 | TypeChain newTypeChain = typeChain; |
| 384 | 22798 | newTypeChain.front().data.bodyScope = bodyScope; | |
| 385 | |||
| 386 | // Register new type or return if already registered | ||
| 387 |
1/2✓ Branch 8 → 9 taken 22798 times.
✗ Branch 8 → 14 not taken.
|
45596 | return TypeRegistry::getOrInsert(newTypeChain); |
| 388 | 22798 | } | |
| 389 | |||
| 390 | /** | ||
| 391 | * Retrieve the same type, but with the given template types | ||
| 392 | * | ||
| 393 | * @return Type with new template types | ||
| 394 | */ | ||
| 395 | 3838 | const Type *Type::getWithTemplateTypes(const QualTypeList &templateTypes) const { | |
| 396 |
2/4✓ Branch 2 → 3 taken 3838 times.
✗ Branch 2 → 8 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3838 times.
|
3838 | assert(isOneOf({TY_STRUCT, TY_INTERFACE})); |
| 397 | 3838 | 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 | 8556 | const Type *Type::getWithBaseTemplateTypes(const QualTypeList &templateTypes) const { | |
| 406 |
3/6✓ Branch 2 → 3 taken 8556 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 8556 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 8556 times.
|
8556 | assert(getBase()->isOneOf({TY_STRUCT, TY_INTERFACE})); |
| 407 | |||
| 408 | // Create new type chain | ||
| 409 |
1/2✓ Branch 6 → 7 taken 8556 times.
✗ Branch 6 → 17 not taken.
|
8556 | TypeChain newTypeChain = typeChain; |
| 410 |
1/2✓ Branch 8 → 9 taken 8556 times.
✗ Branch 8 → 15 not taken.
|
8556 | newTypeChain.front().templateTypes = templateTypes; |
| 411 | |||
| 412 | // Register new type or return if already registered | ||
| 413 |
1/2✓ Branch 9 → 10 taken 8556 times.
✗ Branch 9 → 15 not taken.
|
17112 | return TypeRegistry::getOrInsert(newTypeChain); |
| 414 | 8556 | } | |
| 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 | 13034 | const Type *Type::getWithFunctionParamAndReturnTypes(const QualTypeList ¶mAndReturnTypes) const { | |
| 422 |
3/6✓ Branch 2 → 3 taken 13034 times.
✗ Branch 2 → 17 not taken.
✓ Branch 3 → 4 taken 13034 times.
✗ Branch 3 → 14 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 13034 times.
|
13034 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 423 | |||
| 424 | // Create new type chain | ||
| 425 |
1/2✓ Branch 6 → 7 taken 13034 times.
✗ Branch 6 → 17 not taken.
|
13034 | TypeChain newTypeChain = typeChain; |
| 426 |
1/2✓ Branch 8 → 9 taken 13034 times.
✗ Branch 8 → 15 not taken.
|
13034 | newTypeChain.front().paramTypes = paramAndReturnTypes; |
| 427 | |||
| 428 | // Register new type or return if already registered | ||
| 429 |
1/2✓ Branch 9 → 10 taken 13034 times.
✗ Branch 9 → 15 not taken.
|
26068 | return TypeRegistry::getOrInsert(newTypeChain); |
| 430 | 13034 | } | |
| 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 | 325015 | bool Type::hasAnyGenericParts() const { // NOLINT(misc-no-recursion) | |
| 438 |
1/2✓ Branch 2 → 3 taken 325015 times.
✗ Branch 2 → 34 not taken.
|
325015 | const Type *baseType = getBase(); |
| 439 | |||
| 440 | // Check if the type itself is generic | ||
| 441 |
2/2✓ Branch 4 → 5 taken 54900 times.
✓ Branch 4 → 6 taken 270115 times.
|
325015 | if (baseType->is(TY_GENERIC)) |
| 442 | 54900 | return true; | |
| 443 | |||
| 444 | // Check if the type has generic template types | ||
| 445 |
1/2✓ Branch 7 → 8 taken 270115 times.
✗ Branch 7 → 34 not taken.
|
270115 | const auto templateTypes = baseType->getTemplateTypes(); |
| 446 |
3/4✓ Branch 8 → 9 taken 270115 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 20703 times.
✓ Branch 9 → 11 taken 249412 times.
|
332397 | if (std::ranges::any_of(templateTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
| 447 | 20703 | return true; | |
| 448 | |||
| 449 | // Check param and return types or functions/procedures | ||
| 450 |
3/4✓ Branch 11 → 12 taken 249412 times.
✗ Branch 11 → 28 not taken.
✓ Branch 12 → 13 taken 423 times.
✓ Branch 12 → 24 taken 248989 times.
|
249412 | if (baseType->isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
| 451 |
2/4✓ Branch 13 → 14 taken 423 times.
✗ Branch 13 → 31 not taken.
✓ Branch 14 → 15 taken 423 times.
✗ Branch 14 → 31 not taken.
|
423 | const auto paramTypes = baseType->getFunctionParamAndReturnTypes(); |
| 452 |
3/4✓ Branch 15 → 16 taken 423 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 45 times.
✓ Branch 16 → 18 taken 378 times.
|
1005 | if (std::ranges::any_of(paramTypes, [](const QualType &t) { return t.hasAnyGenericParts(); })) |
| 453 | 45 | return true; | |
| 454 |
2/2✓ Branch 20 → 21 taken 378 times.
✓ Branch 20 → 23 taken 45 times.
|
423 | } |
| 455 | |||
| 456 | 249367 | return false; // Does not have generic parts | |
| 457 | 270115 | } | |
| 458 | |||
| 459 | /** | ||
| 460 | * Retrieve template types of the current type | ||
| 461 | * | ||
| 462 | * @return Vector of template types | ||
| 463 | */ | ||
| 464 | 358753 | 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 | 6138153 | 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 | 1337769 | bool Type::isOneOf(const std::initializer_list<SuperType> &superTypes) const { | |
| 479 | 4221031 | 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 | 440962 | 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 10 → 4 taken 554752 times.
✓ Branch 10 → 11 taken 440962 times.
|
995714 | for (const TypeChainElement &chainElement : typeChain) |
| 493 |
2/4✓ Branch 5 → 6 taken 554752 times.
✗ Branch 5 → 14 not taken.
✓ Branch 6 → 7 taken 554752 times.
✗ Branch 6 → 12 not taken.
|
554752 | name << chainElement.getName(withSize, ignorePublic); |
| 494 | 440962 | } | |
| 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 | 15116 | std::string Type::getName(bool withSize, bool ignorePublic) const { | |
| 504 |
1/2✓ Branch 2 → 3 taken 15116 times.
✗ Branch 2 → 11 not taken.
|
15116 | std::stringstream name; |
| 505 |
1/2✓ Branch 3 → 4 taken 15116 times.
✗ Branch 3 → 9 not taken.
|
15116 | getName(name, withSize, ignorePublic); |
| 506 |
1/2✓ Branch 4 → 5 taken 15116 times.
✗ Branch 4 → 9 not taken.
|
30232 | return name.str(); |
| 507 | 15116 | } | |
| 508 | |||
| 509 | /** | ||
| 510 | * Get the return type of function type | ||
| 511 | * | ||
| 512 | * @return Function return type | ||
| 513 | */ | ||
| 514 | 39 | const QualType &Type::getFunctionReturnType() const { | |
| 515 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 39 times.
|
39 | assert(is(TY_FUNCTION)); |
| 516 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 39 times.
|
39 | assert(!typeChain.back().paramTypes.empty()); |
| 517 | 39 | return typeChain.back().paramTypes.front(); | |
| 518 | } | ||
| 519 | |||
| 520 | /** | ||
| 521 | * Get the param types of a function or procedure type | ||
| 522 | * | ||
| 523 | * @return Function param types | ||
| 524 | */ | ||
| 525 | 140 | QualTypeList Type::getFunctionParamTypes() const { | |
| 526 |
2/4✓ Branch 2 → 3 taken 140 times.
✗ Branch 2 → 20 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 140 times.
|
140 | assert(isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 527 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 140 times.
|
140 | if (typeChain.back().paramTypes.empty()) |
| 528 | ✗ | return {}; | |
| 529 |
1/2✓ Branch 16 → 17 taken 140 times.
✗ Branch 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 | 129 | bool Type::hasLambdaCaptures() const { | |
| 538 |
2/4✓ Branch 3 → 4 taken 129 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 129 times.
|
129 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 539 | 129 | 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 | 477 | const QualTypeList &Type::getFunctionParamAndReturnTypes() const { | |
| 548 |
2/4✓ Branch 3 → 4 taken 477 times.
✗ Branch 3 → 9 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 477 times.
|
477 | assert(getBase()->isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 549 | 477 | 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 | 110528 | bool Type::matches(const Type *otherType, bool ignoreArraySize) const { | |
| 561 | // If the size does not match, it is not equal | ||
| 562 |
2/2✓ Branch 4 → 5 taken 13409 times.
✓ Branch 4 → 6 taken 97119 times.
|
110528 | if (typeChain.size() != otherType->typeChain.size()) |
| 563 | 13409 | return false; | |
| 564 | |||
| 565 | // Compare the elements | ||
| 566 |
2/2✓ Branch 18 → 7 taken 104932 times.
✓ Branch 18 → 19 taken 64255 times.
|
169187 | for (size_t i = 0; i < typeChain.size(); i++) { |
| 567 | 104932 | const TypeChainElement &lhsElement = typeChain.at(i); | |
| 568 | 104932 | const TypeChainElement &rhsElement = otherType->typeChain.at(i); | |
| 569 | |||
| 570 | // Ignore differences in array size | ||
| 571 |
5/6✓ Branch 9 → 10 taken 66410 times.
✓ Branch 9 → 13 taken 38522 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 13 taken 66408 times.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 13 not taken.
|
104932 | if (ignoreArraySize && lhsElement.superType == TY_ARRAY && rhsElement.superType == TY_ARRAY) |
| 572 | 2 | continue; | |
| 573 | |||
| 574 | // Not both types are arrays -> compare them as usual | ||
| 575 |
2/2✓ Branch 14 → 15 taken 32864 times.
✓ Branch 14 → 16 taken 72066 times.
|
104930 | if (lhsElement != rhsElement) |
| 576 | 32864 | return false; | |
| 577 | } | ||
| 578 | |||
| 579 | 64255 | 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 | 82480 | void Type::unwrapBoth(const Type *&typeA, const Type *&typeB) { | |
| 590 | // Remove reference wrapper of front type if required | ||
| 591 |
6/6✓ Branch 3 → 4 taken 34820 times.
✓ Branch 3 → 7 taken 47660 times.
✓ Branch 5 → 6 taken 31234 times.
✓ Branch 5 → 7 taken 3586 times.
✓ Branch 8 → 9 taken 31234 times.
✓ Branch 8 → 11 taken 51246 times.
|
82480 | if (typeA->isRef() && !typeB->isRef()) |
| 592 | 31234 | typeA = typeA->removeReferenceWrapper(); | |
| 593 | |||
| 594 | // Remove reference wrapper of requested type if required | ||
| 595 |
8/8✓ Branch 12 → 13 taken 78894 times.
✓ Branch 12 → 19 taken 3586 times.
✓ Branch 14 → 15 taken 3106 times.
✓ Branch 14 → 19 taken 75788 times.
✓ Branch 17 → 18 taken 2578 times.
✓ Branch 17 → 19 taken 528 times.
✓ Branch 20 → 21 taken 2578 times.
✓ Branch 20 → 23 taken 79902 times.
|
82480 | if (!typeA->isRef() && typeB->isRef() && !typeA->getBase()->is(TY_GENERIC)) |
| 596 | 2578 | typeB = typeB->removeReferenceWrapper(); | |
| 597 | |||
| 598 | // Unwrap both types as far as possible | ||
| 599 |
2/2✓ Branch 28 → 24 taken 5319 times.
✓ Branch 28 → 29 taken 82480 times.
|
87799 | while (typeA->isSameContainerTypeAs(typeB)) { |
| 600 | 5319 | typeB = typeB->getContained(); | |
| 601 | 5319 | typeA = typeA->getContained(); | |
| 602 | } | ||
| 603 | 82480 | } | |
| 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 | 18372 | bool Type::hasSameTypeChainDepth(const Type *typeA, const Type *typeB) { | |
| 613 | 18372 | return typeA->typeChain.size() == typeB->typeChain.size(); | |
| 614 | } | ||
| 615 | |||
| 616 | } // namespace spice::compiler | ||
| 617 |