src/typechecker/TypeCheckerValues.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "TypeChecker.h" | ||
| 4 | |||
| 5 | #include <SourceFile.h> | ||
| 6 | #include <ast/ASTNodes.h> | ||
| 7 | #include <ast/Attributes.h> | ||
| 8 | #include <global/GlobalResourceManager.h> | ||
| 9 | #include <model/GenericType.h> | ||
| 10 | #include <symboltablebuilder/Scope.h> | ||
| 11 | #include <symboltablebuilder/ScopeHandle.h> | ||
| 12 | #include <symboltablebuilder/SymbolTableBuilder.h> | ||
| 13 | #include <typechecker/BuiltinFunctions.h> | ||
| 14 | #include <typechecker/FunctionManager.h> | ||
| 15 | #include <typechecker/MacroDefs.h> | ||
| 16 | #include <typechecker/TypeMatcher.h> | ||
| 17 | |||
| 18 | namespace spice::compiler { | ||
| 19 | |||
| 20 | 172203 | std::any TypeChecker::visitValue(ValueNode *node) { | |
| 21 | // Function call | ||
| 22 |
2/2✓ Branch 2 → 3 taken 148897 times.
✓ Branch 2 → 4 taken 23306 times.
|
172203 | if (node->fctCall) |
| 23 | 148897 | return visit(node->fctCall); | |
| 24 | |||
| 25 | // Array initialization | ||
| 26 |
2/2✓ Branch 4 → 5 taken 670 times.
✓ Branch 4 → 6 taken 22636 times.
|
23306 | if (node->arrayInitialization) |
| 27 | 670 | return visit(node->arrayInitialization); | |
| 28 | |||
| 29 | // Struct instantiation | ||
| 30 |
2/2✓ Branch 6 → 7 taken 3555 times.
✓ Branch 6 → 8 taken 19081 times.
|
22636 | if (node->structInstantiation) |
| 31 | 3555 | return visit(node->structInstantiation); | |
| 32 | |||
| 33 | // Lambda function | ||
| 34 |
2/2✓ Branch 8 → 9 taken 109 times.
✓ Branch 8 → 10 taken 18972 times.
|
19081 | if (node->lambdaFunc) |
| 35 | 109 | return visit(node->lambdaFunc); | |
| 36 | |||
| 37 | // Lambda procedure | ||
| 38 |
2/2✓ Branch 10 → 11 taken 92 times.
✓ Branch 10 → 12 taken 18880 times.
|
18972 | if (node->lambdaProc) |
| 39 | 92 | return visit(node->lambdaProc); | |
| 40 | |||
| 41 | // Lambda expression | ||
| 42 |
2/2✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 14 taken 18878 times.
|
18880 | if (node->lambdaExpr) |
| 43 | 2 | return visit(node->lambdaExpr); | |
| 44 | |||
| 45 | // Typed nil | ||
| 46 |
1/2✓ Branch 14 → 15 taken 18878 times.
✗ Branch 14 → 41 not taken.
|
18878 | if (node->isNil) { |
| 47 |
2/4✓ Branch 15 → 16 taken 18878 times.
✗ Branch 15 → 52 not taken.
✓ Branch 16 → 17 taken 18878 times.
✗ Branch 16 → 50 not taken.
|
18878 | const auto nilType = std::any_cast<QualType>(visit(node->nilType)); |
| 48 |
2/8✓ Branch 18 → 19 taken 18878 times.
✗ Branch 18 → 62 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 24 taken 18878 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 53 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 53 not taken.
|
18878 | HANDLE_UNRESOLVED_TYPE_ER(nilType) |
| 49 |
2/4✓ Branch 24 → 25 taken 18878 times.
✗ Branch 24 → 62 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 36 taken 18878 times.
|
18878 | if (nilType.is(TY_DYN)) |
| 50 | ✗ | SOFT_ERROR_ER(node->nilType, UNEXPECTED_DYN_TYPE, "Nil must have an explicit type") | |
| 51 |
2/4✓ Branch 36 → 37 taken 18878 times.
✗ Branch 36 → 61 not taken.
✓ Branch 37 → 38 taken 18878 times.
✗ Branch 37 → 61 not taken.
|
37756 | return ExprResult{node->setEvaluatedSymbolType(nilType, manIdx)}; |
| 52 | } | ||
| 53 | |||
| 54 | − | throw CompilerError(UNHANDLED_BRANCH, "Value fall-through"); // GCOV_EXCL_LINE | |
| 55 | } | ||
| 56 | |||
| 57 | 164284 | std::any TypeChecker::visitConstant(ConstantNode *node) { | |
| 58 | SuperType superType; | ||
| 59 |
7/8✓ Branch 2 → 3 taken 3918 times.
✓ Branch 2 → 4 taken 22646 times.
✓ Branch 2 → 5 taken 2526 times.
✓ Branch 2 → 6 taken 67586 times.
✓ Branch 2 → 7 taken 13207 times.
✓ Branch 2 → 8 taken 35060 times.
✓ Branch 2 → 9 taken 19341 times.
✗ Branch 2 → 10 not taken.
|
164284 | switch (node->type) { |
| 60 | 3918 | case ConstantNode::PrimitiveValueType::TYPE_DOUBLE: | |
| 61 | 3918 | superType = TY_DOUBLE; | |
| 62 | 3918 | break; | |
| 63 | 22646 | case ConstantNode::PrimitiveValueType::TYPE_INT: | |
| 64 | 22646 | superType = TY_INT; | |
| 65 | 22646 | break; | |
| 66 | 2526 | case ConstantNode::PrimitiveValueType::TYPE_SHORT: | |
| 67 | 2526 | superType = TY_SHORT; | |
| 68 | 2526 | break; | |
| 69 | 67586 | case ConstantNode::PrimitiveValueType::TYPE_LONG: | |
| 70 | 67586 | superType = TY_LONG; | |
| 71 | 67586 | break; | |
| 72 | 13207 | case ConstantNode::PrimitiveValueType::TYPE_CHAR: | |
| 73 | 13207 | superType = TY_CHAR; | |
| 74 | 13207 | break; | |
| 75 | 35060 | case ConstantNode::PrimitiveValueType::TYPE_STRING: | |
| 76 | 35060 | superType = TY_STRING; | |
| 77 | 35060 | break; | |
| 78 | 19341 | case ConstantNode::PrimitiveValueType::TYPE_BOOL: | |
| 79 | 19341 | superType = TY_BOOL; | |
| 80 | 19341 | break; | |
| 81 | − | default: // GCOV_EXCL_LINE | |
| 82 | − | throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE | |
| 83 | } | ||
| 84 |
3/6✓ Branch 18 → 19 taken 164284 times.
✗ Branch 18 → 33 not taken.
✓ Branch 19 → 20 taken 164284 times.
✗ Branch 19 → 33 not taken.
✓ Branch 20 → 21 taken 164284 times.
✗ Branch 20 → 33 not taken.
|
328568 | return ExprResult{node->setEvaluatedSymbolType(QualType(superType), manIdx)}; |
| 85 | } | ||
| 86 | |||
| 87 | 148897 | std::any TypeChecker::visitFctCall(FctCallNode *node) { | |
| 88 |
1/2✓ Branch 2 → 3 taken 148897 times.
✗ Branch 2 → 561 not taken.
|
148897 | FctCallNode::FctCallData &data = node->data.at(manIdx); |
| 89 | 148897 | auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = data; | |
| 90 | |||
| 91 | // Retrieve arg types | ||
| 92 | 148897 | args.clear(); | |
| 93 |
2/2✓ Branch 4 → 5 taken 107633 times.
✓ Branch 4 → 36 taken 41264 times.
|
148897 | if (node->hasArgs) { |
| 94 |
1/2✓ Branch 6 → 7 taken 107633 times.
✗ Branch 6 → 561 not taken.
|
107633 | args.reserve(node->argLst->args.size()); |
| 95 |
2/2✓ Branch 34 → 9 taken 173885 times.
✓ Branch 34 → 35 taken 107599 times.
|
389117 | for (ExprNode *arg : node->argLst->args) { |
| 96 | // Visit argument | ||
| 97 |
3/4✓ Branch 11 → 12 taken 173883 times.
✓ Branch 11 → 440 taken 2 times.
✓ Branch 12 → 13 taken 173883 times.
✗ Branch 12 → 438 not taken.
|
173885 | const auto argResult = std::any_cast<ExprResult>(visit(arg)); |
| 98 |
5/8✓ Branch 14 → 15 taken 173883 times.
✗ Branch 14 → 443 not taken.
✓ Branch 15 → 16 taken 32 times.
✓ Branch 15 → 20 taken 173851 times.
✓ Branch 16 → 17 taken 32 times.
✗ Branch 16 → 441 not taken.
✓ Branch 17 → 18 taken 32 times.
✗ Branch 17 → 441 not taken.
|
173915 | HANDLE_UNRESOLVED_TYPE_ER(argResult.type) |
| 99 |
2/4✓ Branch 20 → 21 taken 173851 times.
✗ Branch 20 → 443 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 173851 times.
|
173851 | assert(!argResult.type.hasAnyGenericParts()); |
| 100 | // Save arg type to arg types list | ||
| 101 |
1/2✓ Branch 24 → 25 taken 173851 times.
✗ Branch 24 → 442 not taken.
|
173851 | args.emplace_back(argResult.type, argResult.isTemporary()); |
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | // Retrieve template types | ||
| 106 | 148863 | templateTypes.clear(); | |
| 107 |
2/2✓ Branch 37 → 38 taken 12486 times.
✓ Branch 37 → 81 taken 136377 times.
|
148863 | if (node->hasTemplateTypes) { |
| 108 |
2/2✓ Branch 79 → 40 taken 14975 times.
✓ Branch 79 → 80 taken 12486 times.
|
39947 | for (DataTypeNode *templateTypeNode : node->templateTypeLst->dataTypes) { |
| 109 |
2/4✓ Branch 42 → 43 taken 14975 times.
✗ Branch 42 → 447 not taken.
✓ Branch 43 → 44 taken 14975 times.
✗ Branch 43 → 445 not taken.
|
14975 | auto templateType = std::any_cast<QualType>(visit(templateTypeNode)); |
| 110 |
2/4✓ Branch 45 → 46 taken 14975 times.
✗ Branch 45 → 456 not taken.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 14975 times.
|
14975 | assert(!templateType.is(TY_INVALID)); |
| 111 | |||
| 112 | // Abort if the type is unresolved | ||
| 113 |
2/4✓ Branch 48 → 49 taken 14975 times.
✗ Branch 48 → 456 not taken.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 56 taken 14975 times.
|
14975 | if (templateType.is(TY_UNRESOLVED)) |
| 114 | ✗ | HANDLE_UNRESOLVED_TYPE_ER(templateType) | |
| 115 | |||
| 116 | // Check if the given type is generic | ||
| 117 |
2/4✓ Branch 56 → 57 taken 14975 times.
✗ Branch 56 → 456 not taken.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 68 taken 14975 times.
|
14975 | if (templateType.is(TY_GENERIC)) |
| 118 | ✗ | SOFT_ERROR_ER(templateTypeNode, EXPECTED_NON_GENERIC_TYPE, "You must specify a concrete type here") | |
| 119 | |||
| 120 |
1/2✓ Branch 68 → 69 taken 14975 times.
✗ Branch 68 → 456 not taken.
|
14975 | templateTypes.push_back(templateType); |
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | // Check if this is a builtin call | ||
| 125 |
2/2✓ Branch 88 → 82 taken 3213472 times.
✓ Branch 88 → 89 taken 132694 times.
|
3346166 | for (const auto &[builtinFctName, _] : BUILTIN_FUNCTIONS) |
| 126 |
2/2✓ Branch 84 → 85 taken 16169 times.
✓ Branch 84 → 87 taken 3197303 times.
|
3213472 | if (node->fqFunctionName == builtinFctName) |
| 127 |
1/2✓ Branch 85 → 86 taken 16169 times.
✗ Branch 85 → 561 not taken.
|
16169 | return visitBuiltinCall(node); |
| 128 | |||
| 129 | // Retrieve entry of the first fragment | ||
| 130 | 132694 | const std::string &firstFrag = node->functionNameFragments.front(); | |
| 131 |
1/2✓ Branch 90 → 91 taken 132694 times.
✗ Branch 90 → 561 not taken.
|
132694 | SymbolTableEntry *firstFragEntry = currentScope->lookup(firstFrag); |
| 132 |
2/2✓ Branch 93 → 94 taken 90206 times.
✓ Branch 93 → 131 taken 42488 times.
|
132694 | if (firstFragEntry) { |
| 133 | // Check if we have seen a 'this.' prefix, because the generator needs that | ||
| 134 |
6/8✓ Branch 94 → 95 taken 2 times.
✓ Branch 94 → 98 taken 90204 times.
✓ Branch 95 → 96 taken 2 times.
✗ Branch 95 → 468 not taken.
✓ Branch 96 → 97 taken 2 times.
✗ Branch 96 → 98 not taken.
✓ Branch 99 → 100 taken 2 times.
✓ Branch 99 → 109 taken 90204 times.
|
90206 | if (firstFragEntry->scope->type == ScopeType::STRUCT && firstFrag != THIS_VARIABLE_NAME) |
| 135 |
5/10✓ Branch 100 → 101 taken 2 times.
✗ Branch 100 → 462 not taken.
✓ Branch 101 → 102 taken 2 times.
✗ Branch 101 → 460 not taken.
✓ Branch 102 → 103 taken 2 times.
✗ Branch 102 → 458 not taken.
✓ Branch 105 → 106 taken 2 times.
✗ Branch 105 → 464 not taken.
✓ Branch 106 → 107 taken 2 times.
✗ Branch 106 → 464 not taken.
|
4 | SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, |
| 136 | "The symbol '" + firstFrag + "' could not be found. Missing 'this.' prefix?") | ||
| 137 | |||
| 138 | 90204 | firstFragEntry->used = true; | |
| 139 | // Decide of which type the function call is | ||
| 140 |
2/4✓ Branch 109 → 110 taken 90204 times.
✗ Branch 109 → 468 not taken.
✓ Branch 110 → 111 taken 90204 times.
✗ Branch 110 → 468 not taken.
|
90204 | const QualType &baseType = firstFragEntry->getQualType().getBase(); |
| 141 |
5/8✓ Branch 111 → 112 taken 90204 times.
✗ Branch 111 → 468 not taken.
✓ Branch 112 → 113 taken 8 times.
✓ Branch 112 → 117 taken 90196 times.
✓ Branch 113 → 114 taken 8 times.
✗ Branch 113 → 465 not taken.
✓ Branch 114 → 115 taken 8 times.
✗ Branch 114 → 465 not taken.
|
90212 | HANDLE_UNRESOLVED_TYPE_ER(baseType) |
| 142 |
3/4✓ Branch 117 → 118 taken 90196 times.
✗ Branch 117 → 466 not taken.
✓ Branch 118 → 119 taken 70541 times.
✓ Branch 118 → 122 taken 19655 times.
|
90196 | if (baseType.isOneOf({TY_STRUCT, TY_INTERFACE})) { |
| 143 |
2/2✓ Branch 119 → 120 taken 7638 times.
✓ Branch 119 → 121 taken 62903 times.
|
70541 | if (firstFragEntry->scope->type == ScopeType::GLOBAL) |
| 144 | 7638 | callType = FctCallNode::FctCallType::TYPE_CTOR; | |
| 145 | else | ||
| 146 | 62903 | callType = FctCallNode::FctCallType::TYPE_METHOD; | |
| 147 |
7/8✓ Branch 122 → 123 taken 19655 times.
✗ Branch 122 → 467 not taken.
✓ Branch 123 → 124 taken 19275 times.
✓ Branch 123 → 126 taken 380 times.
✓ Branch 124 → 125 taken 235 times.
✓ Branch 124 → 126 taken 19040 times.
✓ Branch 127 → 128 taken 235 times.
✓ Branch 127 → 129 taken 19420 times.
|
19655 | } else if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && firstFragEntry->scope->type != ScopeType::GLOBAL) { |
| 148 | 235 | callType = FctCallNode::FctCallType::TYPE_FCT_PTR; | |
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | // Get struct name. Retrieve it from alias if required | ||
| 153 |
1/2✓ Branch 131 → 132 taken 132684 times.
✗ Branch 131 → 561 not taken.
|
132684 | const auto &[structEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqFunctionName); |
| 154 |
4/6✓ Branch 134 → 135 taken 50 times.
✓ Branch 134 → 138 taken 132634 times.
✓ Branch 135 → 136 taken 50 times.
✗ Branch 135 → 561 not taken.
✓ Branch 136 → 137 taken 50 times.
✗ Branch 136 → 561 not taken.
|
132684 | const std::string &fqFunctionName = isAlias ? structEntry->getQualType().getSubType() : node->fqFunctionName; |
| 155 | |||
| 156 | // Get the concrete template types | ||
| 157 |
2/2✓ Branch 139 → 140 taken 50 times.
✓ Branch 139 → 159 taken 132634 times.
|
132684 | if (isAlias) { |
| 158 | // Retrieve concrete template types from type alias | ||
| 159 |
3/6✓ Branch 140 → 141 taken 50 times.
✗ Branch 140 → 561 not taken.
✓ Branch 141 → 142 taken 50 times.
✗ Branch 141 → 561 not taken.
✓ Branch 142 → 143 taken 50 times.
✗ Branch 142 → 561 not taken.
|
50 | templateTypes = structEntry->getQualType().getTemplateTypes(); |
| 160 | // Check if the aliased type specified template types and the struct instantiation does | ||
| 161 |
3/6✓ Branch 144 → 145 taken 50 times.
✗ Branch 144 → 147 not taken.
✗ Branch 145 → 146 not taken.
✓ Branch 145 → 147 taken 50 times.
✗ Branch 148 → 149 not taken.
✓ Branch 148 → 159 taken 50 times.
|
50 | if (!templateTypes.empty() && node->hasTemplateTypes) |
| 162 | ✗ | SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list") | |
| 163 | } | ||
| 164 | |||
| 165 | // Check if this is a method call or a normal function call | ||
| 166 |
2/2✓ Branch 160 → 161 taken 62903 times.
✓ Branch 160 → 175 taken 69781 times.
|
132684 | if (data.isMethodCall()) { |
| 167 | // This is a method call | ||
| 168 |
1/2✓ Branch 161 → 162 taken 62903 times.
✗ Branch 161 → 561 not taken.
|
62903 | thisType = firstFragEntry->getQualType(); |
| 169 |
2/4✓ Branch 162 → 163 taken 62903 times.
✗ Branch 162 → 476 not taken.
✓ Branch 163 → 164 taken 62903 times.
✗ Branch 163 → 476 not taken.
|
62903 | Scope *structBodyScope = thisType.getBase().getBodyScope(); |
| 170 |
1/2✗ Branch 164 → 165 not taken.
✓ Branch 164 → 166 taken 62903 times.
|
62903 | assert(structBodyScope != nullptr); |
| 171 |
3/4✓ Branch 166 → 167 taken 62903 times.
✗ Branch 166 → 561 not taken.
✓ Branch 167 → 168 taken 4 times.
✓ Branch 167 → 173 taken 62899 times.
|
62903 | if (!visitMethodCall(node, structBodyScope)) // Check if soft errors occurred |
| 172 |
3/6✓ Branch 168 → 169 taken 4 times.
✗ Branch 168 → 477 not taken.
✓ Branch 169 → 170 taken 4 times.
✗ Branch 169 → 477 not taken.
✓ Branch 170 → 171 taken 4 times.
✗ Branch 170 → 477 not taken.
|
8 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)}; |
| 173 |
1/2✗ Branch 173 → 174 not taken.
✓ Branch 173 → 211 taken 62899 times.
|
62899 | assert(calleeParentScope != nullptr); |
| 174 |
2/2✓ Branch 176 → 177 taken 235 times.
✓ Branch 176 → 190 taken 69546 times.
|
69781 | } else if (data.isFctPtrCall()) { |
| 175 | // This is a function pointer call | ||
| 176 |
2/4✓ Branch 177 → 178 taken 235 times.
✗ Branch 177 → 482 not taken.
✓ Branch 178 → 179 taken 235 times.
✗ Branch 178 → 482 not taken.
|
235 | const QualType &functionType = firstFragEntry->getQualType().getBase(); |
| 177 |
2/4✓ Branch 179 → 180 taken 235 times.
✗ Branch 179 → 479 not taken.
✗ Branch 180 → 181 not taken.
✓ Branch 180 → 182 taken 235 times.
|
235 | assert(functionType.isOneOf({TY_FUNCTION, TY_PROCEDURE})); |
| 178 |
2/4✓ Branch 182 → 183 taken 235 times.
✗ Branch 182 → 482 not taken.
✗ Branch 183 → 184 not taken.
✓ Branch 183 → 189 taken 235 times.
|
235 | if (!visitFctPtrCall(node, functionType)) // Check if soft errors occurred |
| 179 | ✗ | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)}; | |
| 180 | } else { | ||
| 181 | // This is an ordinary function call | ||
| 182 |
3/4✓ Branch 191 → 192 taken 7712 times.
✓ Branch 191 → 195 taken 61834 times.
✗ Branch 193 → 194 not taken.
✓ Branch 193 → 195 taken 7712 times.
|
69546 | assert(data.isOrdinaryCall() || data.isCtorCall()); |
| 183 |
5/6✓ Branch 195 → 196 taken 69546 times.
✗ Branch 195 → 485 not taken.
✓ Branch 196 → 197 taken 69544 times.
✓ Branch 196 → 483 taken 2 times.
✓ Branch 198 → 199 taken 8 times.
✓ Branch 198 → 204 taken 69536 times.
|
69548 | if (!visitOrdinaryFctCall(node, fqFunctionName)) // Check if soft errors occurred |
| 184 |
3/6✓ Branch 199 → 200 taken 8 times.
✗ Branch 199 → 486 not taken.
✓ Branch 200 → 201 taken 8 times.
✗ Branch 200 → 486 not taken.
✓ Branch 201 → 202 taken 8 times.
✗ Branch 201 → 486 not taken.
|
16 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)}; |
| 185 |
1/2✗ Branch 204 → 205 not taken.
✓ Branch 204 → 206 taken 69536 times.
|
69536 | assert(calleeParentScope != nullptr); |
| 186 | |||
| 187 | // If the call is no ordinary call, it must be a constructor, which takes a struct as this type. | ||
| 188 |
4/6✓ Branch 207 → 208 taken 19809 times.
✓ Branch 207 → 211 taken 49727 times.
✓ Branch 208 → 209 taken 19809 times.
✗ Branch 208 → 561 not taken.
✗ Branch 209 → 210 not taken.
✓ Branch 209 → 211 taken 19809 times.
|
69536 | assert(data.isOrdinaryCall() || data.thisType.is(TY_STRUCT)); |
| 189 | } | ||
| 190 | |||
| 191 |
2/2✓ Branch 212 → 213 taken 132435 times.
✓ Branch 212 → 296 taken 235 times.
|
132670 | if (!data.isFctPtrCall()) { |
| 192 | // Check if we were able to find a function | ||
| 193 |
2/2✓ Branch 213 → 214 taken 24 times.
✓ Branch 213 → 251 taken 132411 times.
|
132435 | if (!callee) { |
| 194 | // Build error message | ||
| 195 |
6/10✓ Branch 215 → 216 taken 4 times.
✓ Branch 215 → 219 taken 20 times.
✓ Branch 218 → 221 taken 4 times.
✗ Branch 218 → 488 not taken.
✓ Branch 220 → 221 taken 20 times.
✗ Branch 220 → 488 not taken.
✓ Branch 221 → 222 taken 4 times.
✓ Branch 221 → 224 taken 20 times.
✗ Branch 488 → 489 not taken.
✗ Branch 488 → 491 not taken.
|
28 | const std::string functionName = data.isCtorCall() ? CTOR_FUNCTION_NAME : node->functionNameFragments.back(); |
| 196 | 24 | ParamList errArgTypes; | |
| 197 |
1/2✓ Branch 225 → 226 taken 24 times.
✗ Branch 225 → 508 not taken.
|
24 | errArgTypes.reserve(args.size()); |
| 198 |
5/8✓ Branch 226 → 227 taken 24 times.
✗ Branch 226 → 494 not taken.
✓ Branch 227 → 228 taken 24 times.
✗ Branch 227 → 494 not taken.
✓ Branch 228 → 229 taken 24 times.
✗ Branch 228 → 494 not taken.
✓ Branch 234 → 230 taken 14 times.
✓ Branch 234 → 235 taken 24 times.
|
38 | for (const auto &type : args | std::views::keys) |
| 199 |
1/2✓ Branch 231 → 232 taken 14 times.
✗ Branch 231 → 493 not taken.
|
14 | errArgTypes.push_back({type, false}); |
| 200 |
2/4✓ Branch 236 → 237 taken 24 times.
✗ Branch 236 → 495 not taken.
✓ Branch 237 → 238 taken 24 times.
✗ Branch 237 → 495 not taken.
|
24 | const std::string signature = Function::getSignature(functionName, thisType, QualType(TY_DYN), errArgTypes, {}, false); |
| 201 | // Throw error | ||
| 202 |
5/10✓ Branch 239 → 240 taken 24 times.
✗ Branch 239 → 503 not taken.
✓ Branch 240 → 241 taken 24 times.
✗ Branch 240 → 501 not taken.
✓ Branch 241 → 242 taken 24 times.
✗ Branch 241 → 499 not taken.
✓ Branch 244 → 245 taken 24 times.
✗ Branch 244 → 505 not taken.
✓ Branch 245 → 246 taken 24 times.
✗ Branch 245 → 505 not taken.
|
24 | SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_FUNCTION, "Function/procedure '" + signature + "' could not be found") |
| 203 | 24 | } | |
| 204 | |||
| 205 | // Check if we need to request a re-visit, because the function body was not type-checked yet | ||
| 206 |
1/2✓ Branch 251 → 252 taken 132411 times.
✗ Branch 251 → 561 not taken.
|
132411 | requestRevisitIfRequired(callee); |
| 207 | |||
| 208 | // Get function entry from function object | ||
| 209 | 132411 | SymbolTableEntry *functionEntry = callee->entry; | |
| 210 | |||
| 211 | // Check if the called function has sufficient visibility | ||
| 212 |
1/2✓ Branch 252 → 253 taken 132411 times.
✗ Branch 252 → 561 not taken.
|
132411 | isImported = calleeParentScope->isImportedBy(rootScope); |
| 213 |
8/10✓ Branch 253 → 254 taken 54074 times.
✓ Branch 253 → 258 taken 78337 times.
✓ Branch 254 → 255 taken 54074 times.
✗ Branch 254 → 561 not taken.
✓ Branch 255 → 256 taken 54074 times.
✗ Branch 255 → 561 not taken.
✓ Branch 256 → 257 taken 4 times.
✓ Branch 256 → 258 taken 54070 times.
✓ Branch 259 → 260 taken 4 times.
✓ Branch 259 → 284 taken 132407 times.
|
132411 | if (isImported && !functionEntry->getQualType().isPublic()) { |
| 214 |
1/2✓ Branch 260 → 261 taken 4 times.
✗ Branch 260 → 529 not taken.
|
4 | const QualType functionEntryType = functionEntry->getQualType(); |
| 215 |
1/2✓ Branch 261 → 262 taken 4 times.
✗ Branch 261 → 529 not taken.
|
4 | const std::string signature = callee->getSignature(); |
| 216 |
2/4✓ Branch 262 → 263 taken 4 times.
✗ Branch 262 → 527 not taken.
✓ Branch 263 → 264 taken 4 times.
✗ Branch 263 → 273 not taken.
|
4 | if (functionEntryType.is(TY_FUNCTION)) |
| 217 |
5/10✓ Branch 264 → 265 taken 4 times.
✗ Branch 264 → 517 not taken.
✓ Branch 265 → 266 taken 4 times.
✗ Branch 265 → 515 not taken.
✓ Branch 266 → 267 taken 4 times.
✗ Branch 266 → 513 not taken.
✓ Branch 269 → 270 taken 4 times.
✗ Branch 269 → 519 not taken.
✓ Branch 270 → 271 taken 4 times.
✗ Branch 270 → 519 not taken.
|
8 | SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Function '" + signature + "' has insufficient visibility") |
| 218 | else | ||
| 219 | ✗ | SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Procedure '" + signature + "' has insufficient visibility") | |
| 220 | 4 | } | |
| 221 | |||
| 222 | // Mark direct calls to err<T>(...) as an error-return-trace origin site when tracing is enabled for this file. | ||
| 223 | // err<T>'s own internal delegation to Result<T>'s error ctor is a distinct ctor call and is never matched here, | ||
| 224 | // so this only ever fires for the user's own call site, not for that nested one. | ||
| 225 |
8/10✓ Branch 284 → 285 taken 68 times.
✓ Branch 284 → 293 taken 132339 times.
✓ Branch 285 → 286 taken 68 times.
✗ Branch 285 → 293 not taken.
✓ Branch 286 → 287 taken 68 times.
✗ Branch 286 → 561 not taken.
✓ Branch 289 → 290 taken 38 times.
✓ Branch 289 → 293 taken 30 times.
✓ Branch 294 → 295 taken 10 times.
✓ Branch 294 → 296 taken 132397 times.
|
132513 | if (sourceFile->errorReturnTracing && callee->bodyScope != nullptr && callee->bodyScope->sourceFile->isResultRT() && |
| 226 |
3/4✓ Branch 290 → 291 taken 38 times.
✗ Branch 290 → 561 not taken.
✓ Branch 291 → 292 taken 10 times.
✓ Branch 291 → 293 taken 28 times.
|
38 | callee->name == "err") |
| 227 | 10 | node->isErrorTraceOrigin = true; | |
| 228 | } | ||
| 229 | |||
| 230 | // Generate arg infos | ||
| 231 |
2/2✓ Branch 296 → 297 taken 97234 times.
✓ Branch 296 → 339 taken 35408 times.
|
132642 | if (node->hasArgs) { |
| 232 | 97234 | QualTypeList paramTypes; | |
| 233 |
2/2✓ Branch 298 → 299 taken 183 times.
✓ Branch 298 → 305 taken 97051 times.
|
97234 | if (data.isFctPtrCall()) { |
| 234 |
2/4✓ Branch 299 → 300 taken 183 times.
✗ Branch 299 → 531 not taken.
✓ Branch 300 → 301 taken 183 times.
✗ Branch 300 → 531 not taken.
|
183 | const QualType &functionType = firstFragEntry->getQualType().getBase(); |
| 235 |
1/2✓ Branch 301 → 302 taken 183 times.
✗ Branch 301 → 530 not taken.
|
183 | paramTypes = functionType.getFunctionParamTypes(); |
| 236 | } else { | ||
| 237 |
1/2✗ Branch 305 → 306 not taken.
✓ Branch 305 → 307 taken 97051 times.
|
97051 | assert(callee != nullptr); |
| 238 |
1/2✓ Branch 307 → 308 taken 97051 times.
✗ Branch 307 → 532 not taken.
|
97051 | paramTypes = callee->getParamTypes(); |
| 239 | } | ||
| 240 | |||
| 241 | 97234 | node->argLst->argInfos.clear(); | |
| 242 |
2/2✓ Branch 332 → 313 taken 159885 times.
✓ Branch 332 → 333 taken 97234 times.
|
257119 | for (size_t argIdx = 0; argIdx < args.size(); argIdx++) { |
| 243 |
1/2✓ Branch 313 → 314 taken 159885 times.
✗ Branch 313 → 534 not taken.
|
159885 | const QualType &expectedType = paramTypes.at(argIdx); |
| 244 |
1/2✓ Branch 314 → 315 taken 159885 times.
✗ Branch 314 → 534 not taken.
|
159885 | const auto &[actualType, _] = args.at(argIdx); |
| 245 | |||
| 246 | 159885 | Function *copyCtor = nullptr; | |
| 247 |
11/14✓ Branch 317 → 318 taken 159885 times.
✗ Branch 317 → 534 not taken.
✓ Branch 318 → 319 taken 2502 times.
✓ Branch 318 → 324 taken 157383 times.
✓ Branch 319 → 320 taken 2502 times.
✗ Branch 319 → 534 not taken.
✓ Branch 320 → 321 taken 2494 times.
✓ Branch 320 → 324 taken 8 times.
✓ Branch 321 → 322 taken 2494 times.
✗ Branch 321 → 534 not taken.
✓ Branch 322 → 323 taken 32 times.
✓ Branch 322 → 324 taken 2462 times.
✓ Branch 325 → 326 taken 32 times.
✓ Branch 325 → 329 taken 159853 times.
|
159885 | if (expectedType.is(TY_STRUCT) && actualType.is(TY_STRUCT) && !actualType.isTriviallyCopyable(node)) { |
| 248 |
1/2✓ Branch 326 → 327 taken 32 times.
✗ Branch 326 → 534 not taken.
|
32 | copyCtor = matchCopyCtor(actualType, node); |
| 249 | // Insert anonymous symbol to track the dtor call of the copy | ||
| 250 |
1/2✓ Branch 327 → 328 taken 32 times.
✗ Branch 327 → 534 not taken.
|
32 | ExprNode *argNode = node->argLst->args.at(argIdx); |
| 251 |
1/2✓ Branch 328 → 329 taken 32 times.
✗ Branch 328 → 534 not taken.
|
32 | currentScope->symbolTable.insertAnonymous(actualType, argNode, SIZE_MAX); |
| 252 | } | ||
| 253 | |||
| 254 |
1/2✓ Branch 329 → 330 taken 159885 times.
✗ Branch 329 → 533 not taken.
|
159885 | node->argLst->argInfos.push_back(ArgLstNode::ArgInfo{copyCtor}); |
| 255 | } | ||
| 256 |
1/2✗ Branch 335 → 336 not taken.
✓ Branch 335 → 337 taken 97234 times.
|
97234 | assert(node->argLst->argInfos.size() == node->argLst->args.size()); |
| 257 | 97234 | } | |
| 258 | |||
| 259 | // Retrieve return type | ||
| 260 |
6/10✓ Branch 340 → 341 taken 235 times.
✓ Branch 340 → 345 taken 132407 times.
✓ Branch 341 → 342 taken 235 times.
✗ Branch 341 → 537 not taken.
✓ Branch 342 → 343 taken 235 times.
✗ Branch 342 → 537 not taken.
✓ Branch 343 → 344 taken 235 times.
✗ Branch 343 → 537 not taken.
✓ Branch 345 → 346 taken 132407 times.
✗ Branch 345 → 537 not taken.
|
265049 | const bool isFct = data.isFctPtrCall() ? firstFragEntry->getQualType().getBase().is(TY_FUNCTION) : callee->isFunction(); |
| 261 | 132642 | QualType returnType; | |
| 262 |
2/2✓ Branch 350 → 351 taken 235 times.
✓ Branch 350 → 358 taken 132407 times.
|
132642 | if (data.isFctPtrCall()) { |
| 263 |
6/10✓ Branch 351 → 352 taken 79 times.
✓ Branch 351 → 356 taken 156 times.
✓ Branch 352 → 353 taken 79 times.
✗ Branch 352 → 538 not taken.
✓ Branch 353 → 354 taken 79 times.
✗ Branch 353 → 538 not taken.
✓ Branch 354 → 355 taken 79 times.
✗ Branch 354 → 538 not taken.
✓ Branch 356 → 357 taken 156 times.
✗ Branch 356 → 538 not taken.
|
235 | returnType = isFct ? firstFragEntry->getQualType().getBase().getFunctionReturnType() : QualType(TY_BOOL); |
| 264 |
2/2✓ Branch 359 → 360 taken 19805 times.
✓ Branch 359 → 361 taken 112602 times.
|
132407 | } else if (data.isCtorCall()) { |
| 265 | 19805 | returnType = thisType; | |
| 266 |
3/4✓ Branch 361 → 362 taken 112602 times.
✗ Branch 361 → 561 not taken.
✓ Branch 364 → 365 taken 30815 times.
✓ Branch 364 → 367 taken 81787 times.
|
225204 | } else if (callee->isProcedure()) { |
| 267 |
1/2✓ Branch 365 → 366 taken 30815 times.
✗ Branch 365 → 540 not taken.
|
30815 | returnType = QualType(TY_DYN); |
| 268 | } else { | ||
| 269 | 81787 | returnType = callee->returnType; | |
| 270 | } | ||
| 271 | |||
| 272 |
1/2✓ Branch 368 → 369 taken 132642 times.
✗ Branch 368 → 561 not taken.
|
132642 | const QualType returnBaseType = returnType.getBase(); |
| 273 | |||
| 274 | // Make sure this source file knows about the return type | ||
| 275 |
3/4✓ Branch 369 → 370 taken 132642 times.
✗ Branch 369 → 561 not taken.
✓ Branch 370 → 371 taken 40352 times.
✓ Branch 370 → 374 taken 92290 times.
|
132642 | if (returnBaseType.is(TY_STRUCT)) |
| 276 |
2/4✓ Branch 371 → 372 taken 40352 times.
✗ Branch 371 → 541 not taken.
✓ Branch 372 → 373 taken 40352 times.
✗ Branch 372 → 541 not taken.
|
40352 | returnType = mapImportedScopeTypeToLocalType(returnBaseType.getBodyScope(), returnType); |
| 277 | |||
| 278 | // Add anonymous symbol to keep track of dtor call, if non-trivially destructible | ||
| 279 | 132642 | SymbolTableEntry *anonymousSymbol = nullptr; | |
| 280 |
8/10✓ Branch 374 → 375 taken 132642 times.
✗ Branch 374 → 561 not taken.
✓ Branch 375 → 376 taken 31731 times.
✓ Branch 375 → 379 taken 100911 times.
✓ Branch 376 → 377 taken 31731 times.
✗ Branch 376 → 561 not taken.
✓ Branch 377 → 378 taken 19851 times.
✓ Branch 377 → 379 taken 11880 times.
✓ Branch 380 → 381 taken 19851 times.
✓ Branch 380 → 383 taken 112791 times.
|
132642 | if (returnType.is(TY_STRUCT) && !returnType.isTriviallyDestructible(node)) |
| 281 |
1/2✓ Branch 381 → 382 taken 19851 times.
✗ Branch 381 → 561 not taken.
|
19851 | anonymousSymbol = currentScope->symbolTable.insertAnonymous(returnType, node); |
| 282 | |||
| 283 | // Remove public qualifier to not have public local variables | ||
| 284 | 132642 | returnType.getQualifiers().isPublic = false; | |
| 285 | |||
| 286 | // Check if the return value gets discarded | ||
| 287 |
7/8✓ Branch 384 → 385 taken 81866 times.
✓ Branch 384 → 388 taken 50776 times.
✓ Branch 385 → 386 taken 81866 times.
✗ Branch 385 → 561 not taken.
✓ Branch 386 → 387 taken 9178 times.
✓ Branch 386 → 388 taken 72688 times.
✓ Branch 389 → 390 taken 9178 times.
✓ Branch 389 → 432 taken 123464 times.
|
132642 | if (isFct && !node->hasReturnValueReceiver()) { |
| 288 | // Discarding a Result<T> is always a hard error when explicit error handling is enabled for this module, | ||
| 289 | // regardless of ignoreUnusedReturnValue (which only ever weakens the generic warning below). | ||
| 290 |
8/10✓ Branch 390 → 391 taken 6 times.
✓ Branch 390 → 395 taken 9172 times.
✓ Branch 391 → 392 taken 6 times.
✗ Branch 391 → 542 not taken.
✓ Branch 392 → 393 taken 6 times.
✗ Branch 392 → 542 not taken.
✓ Branch 393 → 394 taken 4 times.
✓ Branch 393 → 395 taken 2 times.
✓ Branch 396 → 397 taken 4 times.
✓ Branch 396 → 407 taken 9174 times.
|
9178 | if (sourceFile->explicitErrorHandling && returnType.removeReferenceWrapper().isResultObj()) |
| 291 |
4/8✓ Branch 399 → 400 taken 4 times.
✗ Branch 399 → 545 not taken.
✓ Branch 400 → 401 taken 4 times.
✗ Branch 400 → 543 not taken.
✓ Branch 403 → 404 taken 4 times.
✗ Branch 403 → 549 not taken.
✓ Branch 404 → 405 taken 4 times.
✗ Branch 404 → 549 not taken.
|
16 | SOFT_ERROR_ER(node, DISCARDED_RESULT_VALUE, |
| 292 | "A Result<T> returned from a call must be handled: bind it to a variable, propagate it with the " | ||
| 293 | "'!' operator, handle it with '.unwrapOr(...)'/'.unwrapOrElse(...)', or explicitly discard it by " | ||
| 294 | "binding it to a variable with a name starting with '_'") | ||
| 295 | |||
| 296 | // Check if we want to ignore the discarded return value | ||
| 297 | 9174 | bool ignoreUnusedReturnValue = false; | |
| 298 |
2/2✓ Branch 408 → 409 taken 9166 times.
✓ Branch 408 → 429 taken 8 times.
|
9174 | if (!data.isFctPtrCall()) { |
| 299 |
1/2✗ Branch 409 → 410 not taken.
✓ Branch 409 → 411 taken 9166 times.
|
9166 | assert(callee != nullptr); |
| 300 |
1/2✓ Branch 411 → 412 taken 9166 times.
✗ Branch 411 → 413 not taken.
|
9166 | auto fctDef = dynamic_cast<const FctDefNode *>(callee->declNode); |
| 301 |
12/18✓ Branch 414 → 415 taken 2503 times.
✓ Branch 414 → 422 taken 6663 times.
✓ Branch 415 → 416 taken 554 times.
✓ Branch 415 → 422 taken 1949 times.
✓ Branch 418 → 419 taken 554 times.
✗ Branch 418 → 550 not taken.
✓ Branch 419 → 420 taken 554 times.
✗ Branch 419 → 550 not taken.
✓ Branch 420 → 421 taken 516 times.
✓ Branch 420 → 422 taken 38 times.
✓ Branch 423 → 424 taken 554 times.
✓ Branch 423 → 425 taken 8612 times.
✓ Branch 425 → 426 taken 554 times.
✓ Branch 425 → 428 taken 8612 times.
✗ Branch 550 → 551 not taken.
✗ Branch 550 → 552 not taken.
✗ Branch 554 → 555 not taken.
✗ Branch 554 → 557 not taken.
|
10274 | ignoreUnusedReturnValue = fctDef && fctDef->attrs && fctDef->attrs->attrLst->hasAttr(ATTR_IGNORE_UNUSED_RETURN_VALUE); |
| 302 | } | ||
| 303 | |||
| 304 |
2/2✓ Branch 429 → 430 taken 8658 times.
✓ Branch 429 → 432 taken 516 times.
|
9174 | if (!ignoreUnusedReturnValue) |
| 305 |
1/2✓ Branch 430 → 431 taken 8658 times.
✗ Branch 430 → 559 not taken.
|
8658 | warnings.emplace_back(node->codeLoc, UNUSED_RETURN_VALUE, "The return value of the function call is unused"); |
| 306 | } | ||
| 307 | |||
| 308 |
2/4✓ Branch 432 → 433 taken 132638 times.
✗ Branch 432 → 560 not taken.
✓ Branch 433 → 434 taken 132638 times.
✗ Branch 433 → 560 not taken.
|
265276 | return ExprResult{node->setEvaluatedSymbolType(returnType, manIdx), anonymousSymbol}; |
| 309 | } | ||
| 310 | |||
| 311 | 69546 | bool TypeChecker::visitOrdinaryFctCall(FctCallNode *node, std::string fqFunctionName) const { | |
| 312 |
1/2✓ Branch 2 → 3 taken 69546 times.
✗ Branch 2 → 112 not taken.
|
69546 | FctCallNode::FctCallData &data = node->data.at(manIdx); |
| 313 | 69546 | auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = data; | |
| 314 | |||
| 315 | // Check if this is a well-known ctor/fct call | ||
| 316 |
2/2✓ Branch 4 → 5 taken 69226 times.
✓ Branch 4 → 7 taken 320 times.
|
69546 | if (node->functionNameFragments.size() == 1) { |
| 317 |
1/2✓ Branch 5 → 6 taken 69226 times.
✗ Branch 5 → 112 not taken.
|
69226 | ensureLoadedRuntimeForTypeName(fqFunctionName); |
| 318 |
1/2✓ Branch 6 → 7 taken 69226 times.
✗ Branch 6 → 112 not taken.
|
69226 | ensureLoadedRuntimeForFunctionName(fqFunctionName); |
| 319 | } | ||
| 320 | |||
| 321 | // Check if the type is generic (possible in case of ctor call) | ||
| 322 |
1/2✓ Branch 7 → 8 taken 69546 times.
✗ Branch 7 → 112 not taken.
|
69546 | const QualType *genericType = rootScope->lookupGenericTypeStrict(fqFunctionName); |
| 323 |
6/8✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 12 taken 69544 times.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 112 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 19 taken 69544 times.
|
69546 | if (genericType && typeMapping.contains(fqFunctionName)) { |
| 324 |
1/2✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 112 not taken.
|
2 | const QualType &replacementType = typeMapping.at(fqFunctionName); |
| 325 |
2/4✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 112 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 19 not taken.
|
2 | if (replacementType.is(TY_STRUCT)) |
| 326 |
2/4✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 112 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 112 not taken.
|
2 | fqFunctionName = replacementType.getSubType(); |
| 327 | } | ||
| 328 | |||
| 329 | // Check if the exported name registry contains that function name | ||
| 330 |
1/2✓ Branch 19 → 20 taken 69546 times.
✗ Branch 19 → 112 not taken.
|
69546 | const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName); |
| 331 |
2/2✓ Branch 20 → 21 taken 6 times.
✓ Branch 20 → 28 taken 69540 times.
|
69546 | if (!functionRegistryEntry) { |
| 332 |
2/4✓ Branch 22 → 23 taken 6 times.
✗ Branch 22 → 92 not taken.
✓ Branch 23 → 24 taken 6 times.
✗ Branch 23 → 90 not taken.
|
6 | const std::string msg = "Function/procedure/struct '" + node->functionNameFragments.back() + "' could not be found"; |
| 333 |
1/2✓ Branch 25 → 26 taken 6 times.
✗ Branch 25 → 93 not taken.
|
6 | SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, msg) |
| 334 | 6 | } | |
| 335 | 69540 | const SymbolTableEntry *functionEntry = functionRegistryEntry->targetEntry; | |
| 336 | 69540 | calleeParentScope = functionRegistryEntry->targetScope; | |
| 337 | |||
| 338 | // Check if the target symbol is a struct -> this must be a constructor call | ||
| 339 |
1/2✓ Branch 29 → 30 taken 69540 times.
✗ Branch 29 → 112 not taken.
|
69540 | std::string functionName = node->functionNameFragments.back(); |
| 340 |
7/10✓ Branch 30 → 31 taken 69540 times.
✗ Branch 30 → 35 not taken.
✓ Branch 31 → 32 taken 69540 times.
✗ Branch 31 → 110 not taken.
✓ Branch 32 → 33 taken 69540 times.
✗ Branch 32 → 110 not taken.
✓ Branch 33 → 34 taken 19811 times.
✓ Branch 33 → 35 taken 49729 times.
✓ Branch 36 → 37 taken 19811 times.
✓ Branch 36 → 52 taken 49729 times.
|
69540 | if (functionEntry != nullptr && functionEntry->getQualType().is(TY_STRUCT)) { |
| 341 | 19811 | callType = FctCallNode::FctCallType::TYPE_CTOR; | |
| 342 |
1/2✓ Branch 37 → 38 taken 19811 times.
✗ Branch 37 → 110 not taken.
|
19811 | functionName = CTOR_FUNCTION_NAME; |
| 343 | |||
| 344 | 19811 | const NameRegistryEntry *structRegistryEntry = functionRegistryEntry; | |
| 345 | 19811 | const SymbolTableEntry *structEntry = functionEntry; | |
| 346 | |||
| 347 | // Substantiate potentially generic this struct | ||
| 348 |
2/4✓ Branch 38 → 39 taken 19811 times.
✗ Branch 38 → 110 not taken.
✓ Branch 39 → 40 taken 19811 times.
✗ Branch 39 → 110 not taken.
|
19811 | const Struct *thisStruct = structEntry->getQualType().getStruct(node, templateTypes); |
| 349 |
2/2✓ Branch 40 → 41 taken 2 times.
✓ Branch 40 → 49 taken 19809 times.
|
19811 | if (!thisStruct) { |
| 350 |
1/2✓ Branch 41 → 42 taken 2 times.
✗ Branch 41 → 103 not taken.
|
2 | const std::string signature = Struct::getSignature(structRegistryEntry->targetEntry->name, templateTypes); |
| 351 |
2/4✓ Branch 42 → 43 taken 2 times.
✗ Branch 42 → 98 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 96 not taken.
|
2 | const std::string errorMsg = "Could not find struct candidate for struct '" + signature + "'. Do the template types match?"; |
| 352 |
1/2✓ Branch 45 → 46 taken 2 times.
✗ Branch 45 → 99 not taken.
|
2 | SOFT_ERROR_BOOL(node, UNKNOWN_DATATYPE, errorMsg) |
| 353 | 2 | } | |
| 354 | |||
| 355 | // Set the 'this' type of the function to the struct type | ||
| 356 |
2/4✓ Branch 49 → 50 taken 19809 times.
✗ Branch 49 → 104 not taken.
✓ Branch 50 → 51 taken 19809 times.
✗ Branch 50 → 104 not taken.
|
19809 | thisType = structEntry->getQualType().getWithBodyScope(thisStruct->scope); |
| 357 | 19809 | calleeParentScope = thisStruct->scope; | |
| 358 | } | ||
| 359 | |||
| 360 | // Attach the concrete template types to the 'this' type | ||
| 361 |
7/8✓ Branch 52 → 53 taken 69538 times.
✗ Branch 52 → 110 not taken.
✓ Branch 53 → 54 taken 19809 times.
✓ Branch 53 → 57 taken 49729 times.
✓ Branch 55 → 56 taken 4252 times.
✓ Branch 55 → 57 taken 15557 times.
✓ Branch 58 → 59 taken 4252 times.
✓ Branch 58 → 61 taken 65286 times.
|
69538 | if (!thisType.is(TY_DYN) && !templateTypes.empty()) |
| 362 |
1/2✓ Branch 59 → 60 taken 4252 times.
✗ Branch 59 → 105 not taken.
|
4252 | thisType = thisType.getWithTemplateTypes(templateTypes); |
| 363 | |||
| 364 | // Map local arg types to imported types | ||
| 365 |
5/8✓ Branch 61 → 62 taken 69538 times.
✗ Branch 61 → 107 not taken.
✓ Branch 62 → 63 taken 69538 times.
✗ Branch 62 → 107 not taken.
✓ Branch 63 → 64 taken 69538 times.
✗ Branch 63 → 107 not taken.
✓ Branch 69 → 65 taken 117813 times.
✓ Branch 69 → 70 taken 69538 times.
|
187351 | for (QualType &argType : args | std::views::keys) |
| 366 |
1/2✓ Branch 66 → 67 taken 117813 times.
✗ Branch 66 → 106 not taken.
|
117813 | argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType); |
| 367 | |||
| 368 | // Map local template types to imported types | ||
| 369 |
2/2✓ Branch 84 → 72 taken 9296 times.
✓ Branch 84 → 85 taken 69538 times.
|
148372 | for (QualType &templateType : templateTypes) |
| 370 |
1/2✓ Branch 74 → 75 taken 9296 times.
✗ Branch 74 → 108 not taken.
|
9296 | templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType); |
| 371 | |||
| 372 | // Retrieve function object | ||
| 373 | 69538 | Scope *matchScope = calleeParentScope; | |
| 374 |
2/2✓ Branch 85 → 86 taken 69536 times.
✓ Branch 85 → 110 taken 2 times.
|
69538 | callee = FunctionManager::match(matchScope, functionName, data.thisType, data.args, templateTypes, false, node); |
| 375 | |||
| 376 | 69536 | return true; | |
| 377 | 69540 | } | |
| 378 | |||
| 379 | 235 | bool TypeChecker::visitFctPtrCall(const FctCallNode *node, const QualType &functionType) const { | |
| 380 |
1/2✓ Branch 2 → 3 taken 235 times.
✗ Branch 2 → 75 not taken.
|
235 | const FctCallNode::FctCallData &data = node->data.at(manIdx); |
| 381 | 235 | const auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = | |
| 382 | data; | ||
| 383 | |||
| 384 | // Check if the given argument types match the type | ||
| 385 |
1/2✓ Branch 3 → 4 taken 235 times.
✗ Branch 3 → 75 not taken.
|
235 | const QualTypeList expectedArgTypes = functionType.getFunctionParamTypes(); |
| 386 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 14 taken 235 times.
|
235 | if (args.size() != expectedArgTypes.size()) |
| 387 | ✗ | SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, "Expected and actual number of arguments do not match") | |
| 388 | |||
| 389 | // Create resolver function, that always returns a nullptr | ||
| 390 | 235 | TypeMatcher::ResolverFct resolverFct = [](const std::string &) { return nullptr; }; | |
| 391 | |||
| 392 |
2/2✓ Branch 41 → 16 taken 237 times.
✓ Branch 41 → 42 taken 235 times.
|
472 | for (size_t i = 0; i < args.size(); i++) { |
| 393 |
1/2✓ Branch 16 → 17 taken 237 times.
✗ Branch 16 → 71 not taken.
|
237 | const QualType &actualType = args.at(i).first; |
| 394 |
1/2✓ Branch 17 → 18 taken 237 times.
✗ Branch 17 → 71 not taken.
|
237 | const QualType &expectedType = expectedArgTypes.at(i); |
| 395 |
2/4✓ Branch 19 → 20 taken 237 times.
✗ Branch 19 → 68 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 34 taken 237 times.
|
237 | if (TypeMapping tm; !TypeMatcher::matchRequestedToCandidateType(expectedType, actualType, tm, resolverFct, false)) |
| 396 |
1/16✗ Branch 21 → 22 not taken.
✗ Branch 21 → 66 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 61 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 59 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 57 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 55 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 53 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 53 not taken.
✓ Branch 36 → 37 taken 237 times.
✗ Branch 36 → 39 not taken.
|
237 | SOFT_ERROR_BOOL(node->argLst->args.at(i), REFERENCED_UNDEFINED_FUNCTION, |
| 397 | "Expected " + expectedType.getName(false) + " but got " + actualType.getName(false)) | ||
| 398 | } | ||
| 399 | 235 | return true; | |
| 400 | 235 | } | |
| 401 | |||
| 402 | 62903 | bool TypeChecker::visitMethodCall(FctCallNode *node, Scope *structScope) const { | |
| 403 | 62903 | FctCallNode::FctCallData &data = node->data.at(manIdx); | |
| 404 | 62903 | auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = data; | |
| 405 | |||
| 406 | // Traverse through structs - the first fragment is already looked up and the last one is the method name | ||
| 407 |
2/2✓ Branch 43 → 4 taken 14182 times.
✓ Branch 43 → 44 taken 62899 times.
|
77081 | for (size_t i = 1; i < node->functionNameFragments.size() - 1; i++) { |
| 408 |
1/2✓ Branch 4 → 5 taken 14182 times.
✗ Branch 4 → 104 not taken.
|
14182 | const std::string &identifier = node->functionNameFragments.at(i); |
| 409 | |||
| 410 | // Retrieve field entry, also looking through composed fields | ||
| 411 | 14182 | std::vector<size_t> indexPath; | |
| 412 |
1/2✓ Branch 5 → 6 taken 14182 times.
✗ Branch 5 → 102 not taken.
|
14182 | SymbolTableEntry *fieldEntry = structScope->symbolTable.lookupInComposedFields(identifier, indexPath); |
| 413 |
2/2✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 21 taken 14180 times.
|
14182 | if (!fieldEntry) { |
| 414 |
1/2✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 92 not taken.
|
2 | std::stringstream errorMsg; |
| 415 |
1/2✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 90 not taken.
|
2 | errorMsg << "The type '"; |
| 416 |
3/6✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 85 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 85 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 83 not taken.
|
2 | errorMsg << thisType.getBase().getName(false, true); |
| 417 |
3/6✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 90 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 90 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 90 not taken.
|
2 | errorMsg << "' does not have a member with the name '" << identifier << "'"; |
| 418 |
2/4✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 89 not taken.
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 87 not taken.
|
2 | SOFT_ERROR_BOOL(node, ACCESS_TO_NON_EXISTING_MEMBER, errorMsg.str()) |
| 419 | 2 | } | |
| 420 |
5/8✓ Branch 21 → 22 taken 14180 times.
✗ Branch 21 → 94 not taken.
✓ Branch 22 → 23 taken 14180 times.
✗ Branch 22 → 94 not taken.
✓ Branch 23 → 24 taken 14180 times.
✗ Branch 23 → 93 not taken.
✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 31 taken 14178 times.
|
14180 | if (!fieldEntry->getQualType().getBase().isOneOf({TY_STRUCT, TY_INTERFACE})) |
| 421 |
3/6✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 99 not taken.
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 97 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 95 not taken.
|
2 | SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS, |
| 422 | "Cannot call a method on '" + identifier + "', since it is no struct or interface") | ||
| 423 | 14178 | fieldEntry->used = true; | |
| 424 | |||
| 425 | // Get struct type and scope | ||
| 426 |
1/2✓ Branch 31 → 32 taken 14178 times.
✗ Branch 31 → 102 not taken.
|
14178 | thisType = fieldEntry->getQualType(); |
| 427 |
2/4✓ Branch 32 → 33 taken 14178 times.
✗ Branch 32 → 101 not taken.
✓ Branch 33 → 34 taken 14178 times.
✗ Branch 33 → 101 not taken.
|
14178 | structScope = thisType.getBase().getBodyScope(); |
| 428 |
1/2✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 14178 times.
|
14178 | assert(structScope != nullptr); |
| 429 |
2/2✓ Branch 38 → 39 taken 14178 times.
✓ Branch 38 → 41 taken 4 times.
|
14182 | } |
| 430 | |||
| 431 |
1/2✗ Branch 45 → 46 not taken.
✓ Branch 45 → 53 taken 62899 times.
|
62899 | if (thisType.is(TY_INTERFACE)) |
| 432 | ✗ | SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS, "Cannot call a method on an interface") | |
| 433 | |||
| 434 | // Map local arg types to imported types | ||
| 435 | 62899 | Scope *matchScope = calleeParentScope = structScope; | |
| 436 |
5/8✓ Branch 53 → 54 taken 62899 times.
✗ Branch 53 → 112 not taken.
✓ Branch 54 → 55 taken 62899 times.
✗ Branch 54 → 112 not taken.
✓ Branch 55 → 56 taken 62899 times.
✗ Branch 55 → 112 not taken.
✓ Branch 61 → 57 taken 41851 times.
✓ Branch 61 → 62 taken 62899 times.
|
104750 | for (QualType &argType : args | std::views::keys) |
| 437 |
1/2✓ Branch 58 → 59 taken 41851 times.
✗ Branch 58 → 111 not taken.
|
41851 | argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType); |
| 438 | |||
| 439 | // Map local template types to imported types | ||
| 440 |
2/2✓ Branch 76 → 64 taken 700 times.
✓ Branch 76 → 77 taken 62899 times.
|
126498 | for (QualType &templateType : templateTypes) |
| 441 |
1/2✓ Branch 66 → 67 taken 700 times.
✗ Branch 66 → 113 not taken.
|
700 | templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType); |
| 442 | |||
| 443 | // 'this' type | ||
| 444 |
1/2✓ Branch 77 → 78 taken 62899 times.
✗ Branch 77 → 115 not taken.
|
62899 | thisType = thisType.autoDeReference(); |
| 445 |
1/2✓ Branch 78 → 79 taken 62899 times.
✗ Branch 78 → 116 not taken.
|
62899 | thisType = mapLocalTypeToImportedScopeType(calleeParentScope, thisType); |
| 446 | |||
| 447 | // Retrieve function object | ||
| 448 | 62899 | const std::string &functionName = node->functionNameFragments.back(); | |
| 449 | 62899 | callee = FunctionManager::match(matchScope, functionName, thisType, args, templateTypes, false, node); | |
| 450 | |||
| 451 | 62899 | return true; | |
| 452 | } | ||
| 453 | |||
| 454 | 670 | std::any TypeChecker::visitArrayInitialization(ArrayInitializationNode *node) { | |
| 455 |
5/6✓ Branch 2 → 3 taken 668 times.
✓ Branch 2 → 5 taken 2 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 668 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 18 taken 668 times.
|
670 | if (!node->itemLst || node->itemLst->args.empty()) |
| 456 |
4/8✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 76 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 74 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 80 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 80 not taken.
|
8 | SOFT_ERROR_ER(node, ARRAY_SIZE_INVALID, "Array initializers must at least contain one value"); |
| 457 | 668 | node->actualSize = node->itemLst->args.size(); | |
| 458 | |||
| 459 |
1/2✓ Branch 19 → 20 taken 668 times.
✗ Branch 19 → 105 not taken.
|
668 | QualType actualItemType(TY_DYN); |
| 460 | // Check if all values have the same type | ||
| 461 |
2/2✓ Branch 63 → 22 taken 3630 times.
✓ Branch 63 → 64 taken 666 times.
|
4964 | for (ExprNode *arg : node->itemLst->args) { |
| 462 |
2/4✓ Branch 24 → 25 taken 3630 times.
✗ Branch 24 → 83 not taken.
✓ Branch 25 → 26 taken 3630 times.
✗ Branch 25 → 81 not taken.
|
3630 | const QualType itemType = std::any_cast<ExprResult>(visit(arg)).type; |
| 463 |
2/8✓ Branch 27 → 28 taken 3630 times.
✗ Branch 27 → 102 not taken.
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 33 taken 3630 times.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 85 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 85 not taken.
|
3630 | HANDLE_UNRESOLVED_TYPE_ER(itemType) |
| 464 |
3/4✓ Branch 33 → 34 taken 3630 times.
✗ Branch 33 → 102 not taken.
✓ Branch 34 → 35 taken 668 times.
✓ Branch 34 → 36 taken 2962 times.
|
3630 | if (actualItemType.is(TY_DYN)) // Perform type inference |
| 465 | 668 | actualItemType = itemType; | |
| 466 |
3/4✓ Branch 36 → 37 taken 2962 times.
✗ Branch 36 → 102 not taken.
✓ Branch 37 → 38 taken 2 times.
✓ Branch 37 → 53 taken 2960 times.
|
2962 | else if (itemType != actualItemType) // Check if types are matching |
| 467 |
8/16✓ Branch 38 → 39 taken 2 times.
✗ Branch 38 → 99 not taken.
✓ Branch 39 → 40 taken 2 times.
✗ Branch 39 → 94 not taken.
✓ Branch 40 → 41 taken 2 times.
✗ Branch 40 → 92 not taken.
✓ Branch 41 → 42 taken 2 times.
✗ Branch 41 → 90 not taken.
✓ Branch 42 → 43 taken 2 times.
✗ Branch 42 → 88 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 86 not taken.
✓ Branch 49 → 50 taken 2 times.
✗ Branch 49 → 101 not taken.
✓ Branch 50 → 51 taken 2 times.
✗ Branch 50 → 101 not taken.
|
4 | SOFT_ERROR_ER(arg, ARRAY_ITEM_TYPE_NOT_MATCHING, |
| 468 | "All provided values have to be of the same data type. You provided " + actualItemType.getName(false) + | ||
| 469 | " and " + itemType.getName(false)) | ||
| 470 | } | ||
| 471 |
2/4✓ Branch 64 → 65 taken 666 times.
✗ Branch 64 → 105 not taken.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 666 times.
|
666 | assert(!actualItemType.is(TY_DYN)); |
| 472 | |||
| 473 |
1/2✓ Branch 67 → 68 taken 666 times.
✗ Branch 67 → 105 not taken.
|
666 | const QualType arrayType = actualItemType.toArr(node, node->actualSize, true); |
| 474 |
2/4✓ Branch 68 → 69 taken 666 times.
✗ Branch 68 → 104 not taken.
✓ Branch 69 → 70 taken 666 times.
✗ Branch 69 → 104 not taken.
|
1332 | return ExprResult{node->setEvaluatedSymbolType(arrayType, manIdx)}; |
| 475 | } | ||
| 476 | |||
| 477 | 3555 | std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) { | |
| 478 | // Retrieve struct name | ||
| 479 |
1/2✓ Branch 2 → 3 taken 3555 times.
✗ Branch 2 → 307 not taken.
|
3555 | const auto [aliasedEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqStructName); |
| 480 |
5/8✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 9 taken 3553 times.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 307 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 307 not taken.
✓ Branch 10 → 11 taken 3555 times.
✗ Branch 10 → 307 not taken.
|
3555 | std::string structName = isAlias ? aliasedEntry->getQualType().getSubType() : node->fqStructName; |
| 481 | |||
| 482 | // Check if the struct type is generic | ||
| 483 |
1/2✓ Branch 11 → 12 taken 3555 times.
✗ Branch 11 → 305 not taken.
|
3555 | const QualType *genericType = rootScope->lookupGenericTypeStrict(structName); |
| 484 |
6/8✓ Branch 12 → 13 taken 4 times.
✓ Branch 12 → 16 taken 3551 times.
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 305 not taken.
✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 4 times.
✓ Branch 17 → 23 taken 3551 times.
|
3555 | if (genericType && typeMapping.contains(structName)) { |
| 485 |
1/2✓ Branch 18 → 19 taken 4 times.
✗ Branch 18 → 305 not taken.
|
4 | const QualType &replacementType = typeMapping.at(structName); |
| 486 |
2/4✓ Branch 19 → 20 taken 4 times.
✗ Branch 19 → 305 not taken.
✓ Branch 20 → 21 taken 4 times.
✗ Branch 20 → 23 not taken.
|
4 | if (replacementType.is(TY_STRUCT)) |
| 487 |
2/4✓ Branch 21 → 22 taken 4 times.
✗ Branch 21 → 305 not taken.
✓ Branch 22 → 23 taken 4 times.
✗ Branch 22 → 305 not taken.
|
4 | structName = replacementType.getSubType(); |
| 488 | } | ||
| 489 | |||
| 490 | // Retrieve struct | ||
| 491 |
1/2✓ Branch 23 → 24 taken 3555 times.
✗ Branch 23 → 305 not taken.
|
3555 | const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(structName); |
| 492 |
2/2✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 34 taken 3553 times.
|
3555 | if (!registryEntry) |
| 493 |
5/10✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 234 not taken.
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 232 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 230 not taken.
✓ Branch 30 → 31 taken 2 times.
✗ Branch 30 → 236 not taken.
✓ Branch 31 → 32 taken 2 times.
✗ Branch 31 → 236 not taken.
|
4 | SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Cannot find struct '" + structName + "'") |
| 494 |
2/4✓ Branch 34 → 35 taken 3553 times.
✗ Branch 34 → 37 not taken.
✓ Branch 35 → 36 taken 3553 times.
✗ Branch 35 → 37 not taken.
|
3553 | assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr); |
| 495 | 3553 | SymbolTableEntry *structEntry = registryEntry->targetEntry; | |
| 496 | |||
| 497 | // Check visibility | ||
| 498 |
9/12✓ Branch 38 → 39 taken 3553 times.
✗ Branch 38 → 305 not taken.
✓ Branch 39 → 40 taken 3553 times.
✗ Branch 39 → 305 not taken.
✓ Branch 40 → 41 taken 1087 times.
✓ Branch 40 → 44 taken 2466 times.
✓ Branch 41 → 42 taken 1087 times.
✗ Branch 41 → 305 not taken.
✓ Branch 42 → 43 taken 2 times.
✓ Branch 42 → 44 taken 1085 times.
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 55 taken 3551 times.
|
3553 | if (!structEntry->getQualType().isPublic() && structEntry->scope->isImportedBy(currentScope)) |
| 499 |
5/10✓ Branch 46 → 47 taken 2 times.
✗ Branch 46 → 241 not taken.
✓ Branch 47 → 48 taken 2 times.
✗ Branch 47 → 239 not taken.
✓ Branch 48 → 49 taken 2 times.
✗ Branch 48 → 237 not taken.
✓ Branch 51 → 52 taken 2 times.
✗ Branch 51 → 243 not taken.
✓ Branch 52 → 53 taken 2 times.
✗ Branch 52 → 243 not taken.
|
4 | SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Struct '" + structName + "' has insufficient visibility") |
| 500 | |||
| 501 | // Get struct type | ||
| 502 |
1/2✓ Branch 55 → 56 taken 3551 times.
✗ Branch 55 → 305 not taken.
|
3551 | QualType structType = structEntry->getQualType(); |
| 503 | |||
| 504 | // Get the concrete template types | ||
| 505 | 3551 | QualTypeList concreteTemplateTypes; | |
| 506 |
2/2✓ Branch 56 → 57 taken 2 times.
✓ Branch 56 → 76 taken 3549 times.
|
3551 | if (isAlias) { |
| 507 | // Retrieve concrete template types from type alias | ||
| 508 |
3/6✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 303 not taken.
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 303 not taken.
✓ Branch 59 → 60 taken 2 times.
✗ Branch 59 → 303 not taken.
|
2 | concreteTemplateTypes = aliasedEntry->getQualType().getTemplateTypes(); |
| 509 | // Check if the aliased type specified template types and the struct instantiation does | ||
| 510 |
3/6✓ Branch 61 → 62 taken 2 times.
✗ Branch 61 → 64 not taken.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 64 taken 2 times.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 76 taken 2 times.
|
2 | if (!concreteTemplateTypes.empty() && node->templateTypeLst) |
| 511 | ✗ | SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list") | |
| 512 | } | ||
| 513 | |||
| 514 |
2/2✓ Branch 76 → 77 taken 26 times.
✓ Branch 76 → 117 taken 3525 times.
|
3551 | if (node->templateTypeLst) { |
| 515 |
1/2✓ Branch 78 → 79 taken 26 times.
✗ Branch 78 → 303 not taken.
|
26 | concreteTemplateTypes.reserve(node->templateTypeLst->dataTypes.size()); |
| 516 |
2/2✓ Branch 115 → 81 taken 34 times.
✓ Branch 115 → 116 taken 26 times.
|
86 | for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) { |
| 517 |
2/4✓ Branch 83 → 84 taken 34 times.
✗ Branch 83 → 253 not taken.
✓ Branch 84 → 85 taken 34 times.
✗ Branch 84 → 251 not taken.
|
34 | auto concreteType = std::any_cast<QualType>(visit(dataType)); |
| 518 |
2/8✓ Branch 86 → 87 taken 34 times.
✗ Branch 86 → 262 not taken.
✗ Branch 87 → 88 not taken.
✓ Branch 87 → 92 taken 34 times.
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 254 not taken.
✗ Branch 89 → 90 not taken.
✗ Branch 89 → 254 not taken.
|
34 | HANDLE_UNRESOLVED_TYPE_ER(concreteType) |
| 519 | // Check if generic type | ||
| 520 |
2/4✓ Branch 92 → 93 taken 34 times.
✗ Branch 92 → 262 not taken.
✗ Branch 93 → 94 not taken.
✓ Branch 93 → 104 taken 34 times.
|
34 | if (concreteType.is(TY_GENERIC)) |
| 521 | ✗ | SOFT_ERROR_ER(dataType, EXPECTED_NON_GENERIC_TYPE, "Struct instantiations may only take concrete template types") | |
| 522 |
1/2✓ Branch 104 → 105 taken 34 times.
✗ Branch 104 → 262 not taken.
|
34 | concreteTemplateTypes.push_back(concreteType); |
| 523 | } | ||
| 524 | } | ||
| 525 | |||
| 526 | // Get the struct instance | ||
| 527 |
2/4✓ Branch 117 → 118 taken 3551 times.
✗ Branch 117 → 303 not taken.
✓ Branch 118 → 119 taken 3551 times.
✗ Branch 118 → 303 not taken.
|
3551 | Struct *spiceStruct = node->instantiatedStructs.at(manIdx) = structType.getStructAndAdjustType(node, concreteTemplateTypes); |
| 528 |
2/2✓ Branch 119 → 120 taken 2 times.
✓ Branch 119 → 131 taken 3549 times.
|
3551 | if (!spiceStruct) |
| 529 |
6/12✓ Branch 120 → 121 taken 2 times.
✗ Branch 120 → 270 not taken.
✓ Branch 121 → 122 taken 2 times.
✗ Branch 121 → 268 not taken.
✓ Branch 122 → 123 taken 2 times.
✗ Branch 122 → 266 not taken.
✓ Branch 123 → 124 taken 2 times.
✗ Branch 123 → 264 not taken.
✓ Branch 127 → 128 taken 2 times.
✗ Branch 127 → 273 not taken.
✓ Branch 128 → 129 taken 2 times.
✗ Branch 128 → 273 not taken.
|
4 | SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, |
| 530 | "Struct '" + Struct::getSignature(structName, concreteTemplateTypes) + "' could not be found") | ||
| 531 | |||
| 532 | // Struct instantiation for an inheriting struct is forbidden, because the vtable needs to be initialized and this is done in | ||
| 533 | // the ctor of the struct, which is never called in case of struct instantiation | ||
| 534 |
2/2✓ Branch 132 → 133 taken 2 times.
✓ Branch 132 → 143 taken 3547 times.
|
3549 | if (!spiceStruct->interfaceTypes.empty()) |
| 535 |
4/8✓ Branch 135 → 136 taken 2 times.
✗ Branch 135 → 276 not taken.
✓ Branch 136 → 137 taken 2 times.
✗ Branch 136 → 274 not taken.
✓ Branch 139 → 140 taken 2 times.
✗ Branch 139 → 280 not taken.
✓ Branch 140 → 141 taken 2 times.
✗ Branch 140 → 280 not taken.
|
8 | SOFT_ERROR_ER(node, INVALID_STRUCT_INSTANTIATION, "Struct instantiations for inheriting structs are forbidden") |
| 536 | |||
| 537 | // Check if the number of fields matches | ||
| 538 |
2/2✓ Branch 143 → 144 taken 3495 times.
✓ Branch 143 → 204 taken 52 times.
|
3547 | if (node->fieldLst) { // Check if any fields are passed. Empty braces are also allowed |
| 539 |
2/2✓ Branch 146 → 147 taken 2 times.
✓ Branch 146 → 157 taken 3493 times.
|
3495 | if (spiceStruct->fieldTypes.size() != node->fieldLst->args.size()) |
| 540 |
4/8✓ Branch 149 → 150 taken 2 times.
✗ Branch 149 → 283 not taken.
✓ Branch 150 → 151 taken 2 times.
✗ Branch 150 → 281 not taken.
✓ Branch 153 → 154 taken 2 times.
✗ Branch 153 → 287 not taken.
✓ Branch 154 → 155 taken 2 times.
✗ Branch 154 → 287 not taken.
|
8 | SOFT_ERROR_ER(node->fieldLst, NUMBER_OF_FIELDS_NOT_MATCHING, |
| 541 | "You've passed too less/many field values. Pass either none or all of them") | ||
| 542 | |||
| 543 | // Check if the field types are matching | ||
| 544 | 3493 | const size_t fieldCount = spiceStruct->fieldTypes.size(); | |
| 545 |
1/2✓ Branch 158 → 159 taken 3493 times.
✗ Branch 158 → 303 not taken.
|
3493 | const size_t explicitFieldsStartIdx = spiceStruct->scope->getFieldCount() - fieldCount; |
| 546 | // Per-manifestation: a struct literal inside a generic function is re-type-checked once per manifestation of | ||
| 547 | // that function, and the struct itself may resolve to a different concrete type each time (e.g. HashEntry<K, | ||
| 548 | // V> inside HashTable<K, V>.upsert()), so the copy-ctor set from one manifestation must not leak into another. | ||
| 549 |
1/2✓ Branch 159 → 160 taken 3493 times.
✗ Branch 159 → 303 not taken.
|
3493 | std::vector<Function *> &fieldCopyCtors = node->fieldCopyCtors.at(manIdx); |
| 550 | 3493 | fieldCopyCtors.clear(); | |
| 551 |
2/2✓ Branch 199 → 162 taken 7188 times.
✓ Branch 199 → 200 taken 3491 times.
|
10679 | for (size_t i = 0; i < node->fieldLst->args.size(); i++) { |
| 552 | // Get actual type | ||
| 553 |
1/2✓ Branch 162 → 163 taken 7188 times.
✗ Branch 162 → 294 not taken.
|
7188 | ExprNode *assignExpr = node->fieldLst->args.at(i); |
| 554 |
2/4✓ Branch 163 → 164 taken 7188 times.
✗ Branch 163 → 290 not taken.
✓ Branch 164 → 165 taken 7188 times.
✗ Branch 164 → 288 not taken.
|
7188 | auto fieldResult = std::any_cast<ExprResult>(visit(assignExpr)); |
| 555 |
2/8✓ Branch 166 → 167 taken 7188 times.
✗ Branch 166 → 294 not taken.
✗ Branch 167 → 168 not taken.
✓ Branch 167 → 172 taken 7188 times.
✗ Branch 168 → 169 not taken.
✗ Branch 168 → 291 not taken.
✗ Branch 169 → 170 not taken.
✗ Branch 169 → 291 not taken.
|
7188 | HANDLE_UNRESOLVED_TYPE_ER(fieldResult.type) |
| 556 | // Get expected type | ||
| 557 |
1/2✗ Branch 172 → 173 not taken.
✓ Branch 172 → 175 taken 7188 times.
|
7188 | SymbolTableEntry *expectedField = spiceStruct->scope->lookupField(explicitFieldsStartIdx + i); |
| 558 |
1/2✗ Branch 178 → 179 not taken.
✓ Branch 178 → 180 taken 7188 times.
|
7188 | assert(expectedField != nullptr); |
| 559 |
1/2✓ Branch 180 → 181 taken 7188 times.
✗ Branch 180 → 294 not taken.
|
7188 | const ExprResult expected = {expectedField->getQualType(), expectedField}; |
| 560 |
1/2✓ Branch 181 → 182 taken 7188 times.
✗ Branch 181 → 294 not taken.
|
7188 | const bool rhsIsImmediate = assignExpr->hasCompileTimeValue(manIdx); |
| 561 | |||
| 562 | // Capture anonymous info up front: getFieldAssignResultType may delete the anonymous entry (temp stealing | ||
| 563 | // in performStructAssign), turning fieldResult.entry into a dangling pointer. | ||
| 564 |
4/4✓ Branch 182 → 183 taken 4440 times.
✓ Branch 182 → 185 taken 2748 times.
✓ Branch 183 → 184 taken 14 times.
✓ Branch 183 → 185 taken 4426 times.
|
7188 | const bool rhsIsAnonymous = fieldResult.entry != nullptr && fieldResult.entry->anonymous; |
| 565 |
3/4✓ Branch 186 → 187 taken 14 times.
✓ Branch 186 → 188 taken 7174 times.
✓ Branch 187 → 189 taken 14 times.
✗ Branch 187 → 294 not taken.
|
7188 | const std::string rhsEntryName = rhsIsAnonymous ? fieldResult.entry->name : std::string(); |
| 566 | |||
| 567 | // Check if actual type matches expected type. A non-anonymous, non-trivially-copyable rhs (e.g. a plain | ||
| 568 | // local variable) needs its value deep-copied into the field: the struct instantiation does not | ||
| 569 | // consume/move it, so the caller keeps its own copy alive and destructs it independently. | ||
| 570 |
2/2✓ Branch 189 → 190 taken 7186 times.
✓ Branch 189 → 292 taken 2 times.
|
7188 | const auto [_, copyCtor] = opRuleManager.getFieldAssignResultType(assignExpr, expected, fieldResult, rhsIsImmediate, true); |
| 571 |
1/2✓ Branch 192 → 193 taken 7186 times.
✗ Branch 192 → 292 not taken.
|
7186 | fieldCopyCtors.push_back(copyCtor); |
| 572 | |||
| 573 | // If there is an anonymous entry attached (e.g. for struct instantiation), delete it. | ||
| 574 | // Safe to call even if performStructAssign already deleted it: map::erase by key is a no-op when absent. | ||
| 575 |
2/2✓ Branch 193 → 194 taken 14 times.
✓ Branch 193 → 196 taken 7172 times.
|
7186 | if (rhsIsAnonymous) { |
| 576 |
1/2✓ Branch 194 → 195 taken 14 times.
✗ Branch 194 → 292 not taken.
|
14 | currentScope->symbolTable.deleteAnonymous(rhsEntryName); |
| 577 | 14 | fieldResult.entry = nullptr; | |
| 578 | } | ||
| 579 | 7188 | } | |
| 580 |
1/2✗ Branch 202 → 203 not taken.
✓ Branch 202 → 216 taken 3491 times.
|
3491 | assert(fieldCopyCtors.size() == node->fieldLst->args.size()); |
| 581 | } else { | ||
| 582 |
2/4✓ Branch 204 → 205 taken 52 times.
✗ Branch 204 → 303 not taken.
✗ Branch 205 → 206 not taken.
✓ Branch 205 → 216 taken 52 times.
|
228 | if (std::ranges::any_of(spiceStruct->fieldTypes, [](const QualType &fieldType) { return fieldType.isRef(); })) |
| 583 | ✗ | SOFT_ERROR_ER(node, REFERENCE_WITHOUT_INITIALIZER, | |
| 584 | "The struct takes at least one reference field. You need to instantiate it with all fields.") | ||
| 585 | } | ||
| 586 | |||
| 587 | // Update type of struct entry | ||
| 588 |
1/2✓ Branch 216 → 217 taken 3543 times.
✗ Branch 216 → 303 not taken.
|
3543 | structEntry->updateType(structType, true); |
| 589 | |||
| 590 | // Add anonymous symbol to keep track of dtor call, if non-trivially destructible | ||
| 591 | 3543 | SymbolTableEntry *anonymousEntry = nullptr; | |
| 592 |
3/4✓ Branch 217 → 218 taken 3543 times.
✗ Branch 217 → 303 not taken.
✓ Branch 218 → 219 taken 175 times.
✓ Branch 218 → 221 taken 3368 times.
|
3543 | if (!structType.isTriviallyDestructible(node)) |
| 593 |
1/2✓ Branch 219 → 220 taken 175 times.
✗ Branch 219 → 303 not taken.
|
175 | anonymousEntry = currentScope->symbolTable.insertAnonymous(structType, node); |
| 594 | |||
| 595 | // Remove public qualifier to not have public local variables | ||
| 596 | 3543 | structType.getQualifiers().isPublic = false; | |
| 597 | |||
| 598 |
2/4✓ Branch 222 → 223 taken 3543 times.
✗ Branch 222 → 302 not taken.
✓ Branch 223 → 224 taken 3543 times.
✗ Branch 223 → 302 not taken.
|
7086 | return ExprResult{node->setEvaluatedSymbolType(structType, manIdx), anonymousEntry}; |
| 599 | 3557 | } | |
| 600 | |||
| 601 | 109 | std::any TypeChecker::visitLambdaFunc(LambdaFuncNode *node) { | |
| 602 | // Check if all control paths in the lambda body return | ||
| 603 | 109 | bool returnsOnAllControlPaths = true; | |
| 604 |
3/4✓ Branch 2 → 3 taken 109 times.
✗ Branch 2 → 194 not taken.
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 14 taken 107 times.
|
109 | if (!node->returnsOnAllControlPaths(&returnsOnAllControlPaths, manIdx)) |
| 605 |
4/8✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 120 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 118 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 124 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 124 not taken.
|
8 | SOFT_ERROR_ER(node, MISSING_RETURN_STMT, "Not all control paths of this lambda function have a return statement") |
| 606 | |||
| 607 | // Change to function scope | ||
| 608 |
2/4✓ Branch 14 → 15 taken 107 times.
✗ Branch 14 → 127 not taken.
✓ Branch 15 → 16 taken 107 times.
✗ Branch 15 → 125 not taken.
|
107 | Scope *bodyScope = currentScope->getChildScope(node->getScopeId()); |
| 609 |
1/2✓ Branch 17 → 18 taken 107 times.
✗ Branch 17 → 128 not taken.
|
107 | ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY); |
| 610 | |||
| 611 | // Visit return type | ||
| 612 |
2/4✓ Branch 18 → 19 taken 107 times.
✗ Branch 18 → 131 not taken.
✓ Branch 19 → 20 taken 107 times.
✗ Branch 19 → 129 not taken.
|
107 | const auto returnType = std::any_cast<QualType>(visit(node->returnType)); |
| 613 |
2/8✓ Branch 21 → 22 taken 107 times.
✗ Branch 21 → 192 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 27 taken 107 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 132 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 132 not taken.
|
107 | HANDLE_UNRESOLVED_TYPE_ER(returnType) |
| 614 |
3/4✓ Branch 27 → 28 taken 107 times.
✗ Branch 27 → 192 not taken.
✓ Branch 28 → 29 taken 2 times.
✓ Branch 28 → 39 taken 105 times.
|
107 | if (returnType.is(TY_DYN)) |
| 615 |
4/8✓ Branch 31 → 32 taken 2 times.
✗ Branch 31 → 135 not taken.
✓ Branch 32 → 33 taken 2 times.
✗ Branch 32 → 133 not taken.
✓ Branch 35 → 36 taken 2 times.
✗ Branch 35 → 139 not taken.
✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 139 not taken.
|
8 | SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed") |
| 616 | |||
| 617 | // Set the type of the result variable | ||
| 618 |
1/2✓ Branch 41 → 42 taken 105 times.
✗ Branch 41 → 142 not taken.
|
315 | SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME); |
| 619 |
1/2✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 105 times.
|
105 | assert(resultVarEntry != nullptr); |
| 620 |
1/2✓ Branch 49 → 50 taken 105 times.
✗ Branch 49 → 192 not taken.
|
105 | resultVarEntry->updateType(returnType, true); |
| 621 | 105 | resultVarEntry->used = true; | |
| 622 | |||
| 623 | // Visit parameters | ||
| 624 | 105 | QualTypeList paramTypes; | |
| 625 | 105 | ParamList paramList; | |
| 626 |
2/2✓ Branch 50 → 51 taken 95 times.
✓ Branch 50 → 80 taken 10 times.
|
105 | if (node->hasParams) { |
| 627 | // Visit param list to retrieve the param names | ||
| 628 |
2/4✓ Branch 51 → 52 taken 95 times.
✗ Branch 51 → 148 not taken.
✓ Branch 52 → 53 taken 95 times.
✗ Branch 52 → 146 not taken.
|
95 | auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst)); |
| 629 |
2/2✓ Branch 77 → 56 taken 125 times.
✓ Branch 77 → 78 taken 95 times.
|
315 | for (const auto &[name, qualType, isOptional] : namedParamList) { |
| 630 |
1/2✗ Branch 58 → 59 not taken.
✓ Branch 58 → 66 taken 125 times.
|
125 | if (isOptional) |
| 631 | ✗ | softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters"); | |
| 632 | |||
| 633 |
1/2✓ Branch 66 → 67 taken 125 times.
✗ Branch 66 → 156 not taken.
|
125 | paramTypes.push_back(qualType); |
| 634 |
1/2✓ Branch 67 → 68 taken 125 times.
✗ Branch 67 → 155 not taken.
|
125 | paramList.push_back({qualType, isOptional}); |
| 635 | } | ||
| 636 | 95 | } | |
| 637 | |||
| 638 | // Visit lambda body | ||
| 639 |
2/2✓ Branch 80 → 81 taken 103 times.
✓ Branch 80 → 160 taken 2 times.
|
105 | visit(node->body); |
| 640 | |||
| 641 | // Leave function body scope | ||
| 642 |
1/2✓ Branch 82 → 83 taken 103 times.
✗ Branch 82 → 188 not taken.
|
103 | scopeHandle.leaveScopeEarly(); |
| 643 | |||
| 644 | // Prepare type of function | ||
| 645 |
1/2✓ Branch 83 → 84 taken 103 times.
✗ Branch 83 → 161 not taken.
|
103 | const QualType functionType = QualType(TY_FUNCTION) |
| 646 |
1/2✓ Branch 84 → 85 taken 103 times.
✗ Branch 84 → 161 not taken.
|
103 | .getWithFunctionParamAndReturnTypes(returnType, paramTypes) |
| 647 |
1/2✓ Branch 86 → 87 taken 103 times.
✗ Branch 86 → 161 not taken.
|
103 | .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty()); |
| 648 | |||
| 649 | // Create function object | ||
| 650 |
2/4✓ Branch 87 → 88 taken 103 times.
✗ Branch 87 → 165 not taken.
✓ Branch 88 → 89 taken 103 times.
✗ Branch 88 → 163 not taken.
|
103 | const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn(); |
| 651 |
5/10✓ Branch 91 → 92 taken 103 times.
✗ Branch 91 → 174 not taken.
✓ Branch 92 → 93 taken 103 times.
✗ Branch 92 → 171 not taken.
✓ Branch 93 → 94 taken 103 times.
✗ Branch 93 → 170 not taken.
✓ Branch 94 → 95 taken 103 times.
✗ Branch 94 → 168 not taken.
✓ Branch 95 → 96 taken 103 times.
✗ Branch 95 → 166 not taken.
|
103 | node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node); |
| 652 |
1/2✓ Branch 101 → 102 taken 103 times.
✗ Branch 101 → 186 not taken.
|
103 | node->manifestations.at(manIdx).bodyScope = bodyScope; |
| 653 |
3/6✓ Branch 102 → 103 taken 103 times.
✗ Branch 102 → 183 not taken.
✓ Branch 103 → 104 taken 103 times.
✗ Branch 103 → 181 not taken.
✓ Branch 104 → 105 taken 103 times.
✗ Branch 104 → 179 not taken.
|
103 | node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx); |
| 654 | |||
| 655 | // Check special requirements if this is an async lambda | ||
| 656 |
1/2✓ Branch 108 → 109 taken 103 times.
✗ Branch 108 → 186 not taken.
|
103 | (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr); |
| 657 | |||
| 658 |
2/4✓ Branch 109 → 110 taken 103 times.
✗ Branch 109 → 185 not taken.
✓ Branch 110 → 111 taken 103 times.
✗ Branch 110 → 185 not taken.
|
103 | return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)}; |
| 659 | 111 | } | |
| 660 | |||
| 661 | 92 | std::any TypeChecker::visitLambdaProc(LambdaProcNode *node) { | |
| 662 | // Mark unreachable statements | ||
| 663 | 92 | bool doSetPredecessorsUnreachable = true; | |
| 664 |
1/2✓ Branch 2 → 3 taken 92 times.
✗ Branch 2 → 131 not taken.
|
92 | node->returnsOnAllControlPaths(&doSetPredecessorsUnreachable, manIdx); |
| 665 | |||
| 666 | // Change to function scope | ||
| 667 |
2/4✓ Branch 3 → 4 taken 92 times.
✗ Branch 3 → 79 not taken.
✓ Branch 4 → 5 taken 92 times.
✗ Branch 4 → 77 not taken.
|
92 | Scope *bodyScope = currentScope->getChildScope(node->getScopeId()); |
| 668 |
1/2✓ Branch 6 → 7 taken 92 times.
✗ Branch 6 → 80 not taken.
|
92 | ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY); |
| 669 | |||
| 670 | // Visit parameters | ||
| 671 | 92 | QualTypeList paramTypes; | |
| 672 | 92 | ParamList paramList; | |
| 673 |
2/2✓ Branch 7 → 8 taken 58 times.
✓ Branch 7 → 37 taken 34 times.
|
92 | if (node->hasParams) { |
| 674 | // Visit param list to retrieve the param names | ||
| 675 |
2/4✓ Branch 8 → 9 taken 58 times.
✗ Branch 8 → 83 not taken.
✓ Branch 9 → 10 taken 58 times.
✗ Branch 9 → 81 not taken.
|
58 | auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst)); |
| 676 |
2/2✓ Branch 34 → 13 taken 78 times.
✓ Branch 34 → 35 taken 58 times.
|
194 | for (const auto &[_, qualType, isOptional] : namedParamList) { |
| 677 |
2/2✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 23 taken 76 times.
|
78 | if (isOptional) |
| 678 |
2/4✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 86 not taken.
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 84 not taken.
|
4 | softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters"); |
| 679 | |||
| 680 |
1/2✓ Branch 23 → 24 taken 78 times.
✗ Branch 23 → 91 not taken.
|
78 | paramTypes.push_back(qualType); |
| 681 |
1/2✓ Branch 24 → 25 taken 78 times.
✗ Branch 24 → 90 not taken.
|
78 | paramList.push_back({qualType, isOptional}); |
| 682 | } | ||
| 683 | 58 | } | |
| 684 | |||
| 685 | // Visit lambda body | ||
| 686 |
1/2✓ Branch 37 → 38 taken 92 times.
✗ Branch 37 → 95 not taken.
|
92 | visit(node->body); |
| 687 | |||
| 688 | // Leave function body scope | ||
| 689 |
1/2✓ Branch 39 → 40 taken 92 times.
✗ Branch 39 → 125 not taken.
|
92 | scopeHandle.leaveScopeEarly(); |
| 690 | |||
| 691 | // Prepare type of function | ||
| 692 |
1/2✓ Branch 40 → 41 taken 92 times.
✗ Branch 40 → 97 not taken.
|
92 | const QualType functionType = QualType(TY_PROCEDURE) |
| 693 |
2/4✓ Branch 41 → 42 taken 92 times.
✗ Branch 41 → 96 not taken.
✓ Branch 42 → 43 taken 92 times.
✗ Branch 42 → 96 not taken.
|
92 | .getWithFunctionParamAndReturnTypes(QualType(TY_DYN), paramTypes) |
| 694 |
1/2✓ Branch 44 → 45 taken 92 times.
✗ Branch 44 → 96 not taken.
|
92 | .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty()); |
| 695 | |||
| 696 | // Create function object | ||
| 697 |
2/4✓ Branch 45 → 46 taken 92 times.
✗ Branch 45 → 101 not taken.
✓ Branch 46 → 47 taken 92 times.
✗ Branch 46 → 99 not taken.
|
92 | const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn(); |
| 698 |
6/12✓ Branch 49 → 50 taken 92 times.
✗ Branch 49 → 111 not taken.
✓ Branch 50 → 51 taken 92 times.
✗ Branch 50 → 108 not taken.
✓ Branch 51 → 52 taken 92 times.
✗ Branch 51 → 107 not taken.
✓ Branch 52 → 53 taken 92 times.
✗ Branch 52 → 106 not taken.
✓ Branch 53 → 54 taken 92 times.
✗ Branch 53 → 104 not taken.
✓ Branch 54 → 55 taken 92 times.
✗ Branch 54 → 102 not taken.
|
92 | node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), QualType(TY_DYN), paramList, {}, node); |
| 699 |
1/2✓ Branch 60 → 61 taken 92 times.
✗ Branch 60 → 123 not taken.
|
92 | node->manifestations.at(manIdx).bodyScope = bodyScope; |
| 700 |
3/6✓ Branch 61 → 62 taken 92 times.
✗ Branch 61 → 120 not taken.
✓ Branch 62 → 63 taken 92 times.
✗ Branch 62 → 118 not taken.
✓ Branch 63 → 64 taken 92 times.
✗ Branch 63 → 116 not taken.
|
92 | node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx); |
| 701 | |||
| 702 | // Check special requirements if this is an async lambda | ||
| 703 |
1/2✓ Branch 67 → 68 taken 92 times.
✗ Branch 67 → 123 not taken.
|
92 | (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr); |
| 704 | |||
| 705 |
2/4✓ Branch 68 → 69 taken 92 times.
✗ Branch 68 → 122 not taken.
✓ Branch 69 → 70 taken 92 times.
✗ Branch 69 → 122 not taken.
|
184 | return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)}; |
| 706 | 92 | } | |
| 707 | |||
| 708 | 2 | std::any TypeChecker::visitLambdaExpr(LambdaExprNode *node) { | |
| 709 | // Change to function scope | ||
| 710 |
2/4✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 98 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 96 not taken.
|
2 | Scope *bodyScope = currentScope->getChildScope(node->getScopeId()); |
| 711 |
1/2✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 99 not taken.
|
2 | ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY); |
| 712 | |||
| 713 | // Visit parameters | ||
| 714 | 2 | QualTypeList paramTypes; | |
| 715 | 2 | ParamList paramList; | |
| 716 |
1/2✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 36 not taken.
|
2 | if (node->hasParams) { |
| 717 | // Visit param list to retrieve the param names | ||
| 718 |
2/4✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 102 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 100 not taken.
|
2 | auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst)); |
| 719 |
2/2✓ Branch 33 → 12 taken 4 times.
✓ Branch 33 → 34 taken 2 times.
|
8 | for (const NamedParam ¶m : namedParamList) { |
| 720 |
1/2✗ Branch 14 → 15 not taken.
✓ Branch 14 → 22 taken 4 times.
|
4 | if (param.isOptional) |
| 721 | ✗ | softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters"); | |
| 722 | |||
| 723 |
1/2✓ Branch 22 → 23 taken 4 times.
✗ Branch 22 → 110 not taken.
|
4 | paramTypes.push_back(param.qualType); |
| 724 |
1/2✓ Branch 23 → 24 taken 4 times.
✗ Branch 23 → 109 not taken.
|
4 | paramList.push_back({param.qualType, param.isOptional}); |
| 725 | } | ||
| 726 | 2 | } | |
| 727 | |||
| 728 | // Visit lambda expression | ||
| 729 |
2/4✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 116 not taken.
✓ Branch 37 → 38 taken 2 times.
✗ Branch 37 → 114 not taken.
|
2 | const QualType returnType = std::any_cast<ExprResult>(visit(node->lambdaExpr)).type; |
| 730 |
2/8✓ Branch 39 → 40 taken 2 times.
✗ Branch 39 → 153 not taken.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 45 taken 2 times.
✗ Branch 41 → 42 not taken.
✗ Branch 41 → 118 not taken.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 118 not taken.
|
2 | HANDLE_UNRESOLVED_TYPE_ER(returnType) |
| 731 |
2/4✓ Branch 45 → 46 taken 2 times.
✗ Branch 45 → 153 not taken.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 57 taken 2 times.
|
2 | if (returnType.is(TY_DYN)) |
| 732 | ✗ | SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed") | |
| 733 | |||
| 734 | // Leave function body scope | ||
| 735 |
1/2✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 153 not taken.
|
2 | scopeHandle.leaveScopeEarly(); |
| 736 | |||
| 737 | // Prepare type of function | ||
| 738 |
2/4✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 153 not taken.
✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 2 times.
|
2 | const SuperType superType = returnType.is(TY_DYN) ? TY_PROCEDURE : TY_FUNCTION; |
| 739 |
1/2✓ Branch 62 → 63 taken 2 times.
✗ Branch 62 → 126 not taken.
|
2 | const QualType functionType = QualType(superType) |
| 740 |
1/2✓ Branch 63 → 64 taken 2 times.
✗ Branch 63 → 126 not taken.
|
2 | .getWithFunctionParamAndReturnTypes(returnType, paramTypes) |
| 741 |
1/2✓ Branch 65 → 66 taken 2 times.
✗ Branch 65 → 126 not taken.
|
2 | .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty()); |
| 742 | |||
| 743 | // Create function object | ||
| 744 |
2/4✓ Branch 66 → 67 taken 2 times.
✗ Branch 66 → 130 not taken.
✓ Branch 67 → 68 taken 2 times.
✗ Branch 67 → 128 not taken.
|
2 | const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn(); |
| 745 |
5/10✓ Branch 70 → 71 taken 2 times.
✗ Branch 70 → 139 not taken.
✓ Branch 71 → 72 taken 2 times.
✗ Branch 71 → 136 not taken.
✓ Branch 72 → 73 taken 2 times.
✗ Branch 72 → 135 not taken.
✓ Branch 73 → 74 taken 2 times.
✗ Branch 73 → 133 not taken.
✓ Branch 74 → 75 taken 2 times.
✗ Branch 74 → 131 not taken.
|
2 | node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node); |
| 746 |
1/2✓ Branch 80 → 81 taken 2 times.
✗ Branch 80 → 151 not taken.
|
2 | node->manifestations.at(manIdx).bodyScope = bodyScope; |
| 747 |
3/6✓ Branch 81 → 82 taken 2 times.
✗ Branch 81 → 148 not taken.
✓ Branch 82 → 83 taken 2 times.
✗ Branch 82 → 146 not taken.
✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 144 not taken.
|
2 | node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx); |
| 748 | |||
| 749 |
2/4✓ Branch 87 → 88 taken 2 times.
✗ Branch 87 → 150 not taken.
✓ Branch 88 → 89 taken 2 times.
✗ Branch 88 → 150 not taken.
|
2 | return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)}; |
| 750 | 2 | } | |
| 751 | |||
| 752 | } // namespace spice::compiler | ||
| 753 |