src/typechecker/TypeCheckerBuiltinFunctions.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 <driver/Driver.h> | ||
| 8 | #include <global/GlobalResourceManager.h> | ||
| 9 | #include <global/TypeRegistry.h> | ||
| 10 | #include <symboltablebuilder/QualType.h> | ||
| 11 | #include <symboltablebuilder/Scope.h> | ||
| 12 | #include <symboltablebuilder/SymbolTableBuilder.h> | ||
| 13 | #include <typechecker/Builtins.h> | ||
| 14 | #include <typechecker/FunctionManager.h> | ||
| 15 | #include <typechecker/MacroDefs.h> | ||
| 16 | |||
| 17 | #include <llvm/IR/DataLayout.h> | ||
| 18 | #include <llvm/IR/DerivedTypes.h> | ||
| 19 | |||
| 20 | namespace spice::compiler { | ||
| 21 | |||
| 22 | 5660 | std::any TypeChecker::visitBuiltinCall(FctCallNode *node) const { | |
| 23 |
2/4✓ Branch 3 → 4 taken 5660 times.
✗ Branch 3 → 69 not taken.
✓ Branch 4 → 5 taken 5660 times.
✗ Branch 4 → 6 not taken.
|
5660 | assert(BUILTIN_FUNCTIONS_MAP.contains(node->fqFunctionName) && "Builtin function not implemented!"); |
| 24 |
1/2✓ Branch 8 → 9 taken 5660 times.
✗ Branch 8 → 70 not taken.
|
5660 | const auto &info = BUILTIN_FUNCTIONS_MAP.find(node->fqFunctionName)->second; |
| 25 | |||
| 26 | 23 | const auto buildErrorMessage = [](unsigned int min, unsigned int max, unsigned int actual, const char *suffix) { | |
| 27 | 23 | std::string expectedStr; | |
| 28 |
2/2✓ Branch 3 → 4 taken 12 times.
✓ Branch 3 → 15 taken 11 times.
|
23 | if (min == max) |
| 29 |
5/8✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 8 taken 9 times.
✓ Branch 7 → 9 taken 3 times.
✗ Branch 7 → 46 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 14 taken 9 times.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 49 not taken.
|
18 | expectedStr = min == 0 ? "no" : std::to_string(min); |
| 30 | else | ||
| 31 |
5/10✓ Branch 17 → 18 taken 11 times.
✗ Branch 17 → 60 not taken.
✓ Branch 18 → 19 taken 11 times.
✗ Branch 18 → 58 not taken.
✓ Branch 19 → 20 taken 11 times.
✗ Branch 19 → 56 not taken.
✓ Branch 20 → 21 taken 11 times.
✗ Branch 20 → 54 not taken.
✓ Branch 21 → 22 taken 11 times.
✗ Branch 21 → 52 not taken.
|
11 | expectedStr = "between " + std::to_string(min) + " and " + std::to_string(max) + " " + suffix; |
| 32 |
5/10✓ Branch 32 → 33 taken 23 times.
✗ Branch 32 → 79 not taken.
✓ Branch 33 → 34 taken 23 times.
✗ Branch 33 → 77 not taken.
✓ Branch 34 → 35 taken 23 times.
✗ Branch 34 → 75 not taken.
✓ Branch 35 → 36 taken 23 times.
✗ Branch 35 → 73 not taken.
✓ Branch 36 → 37 taken 23 times.
✗ Branch 36 → 71 not taken.
|
69 | return "This builtin expects " + expectedStr + " " + suffix + ", but got " + std::to_string(actual); |
| 33 | 23 | }; | |
| 34 | |||
| 35 | // Do basic checks of template types and args, based on the builtin function info | ||
| 36 |
2/2✓ Branch 10 → 11 taken 1760 times.
✓ Branch 10 → 12 taken 3900 times.
|
5660 | const size_t numTemplateTypes = node->hasTemplateTypes ? node->templateTypeLst->dataTypes.size() : 0; |
| 37 |
4/4✓ Branch 13 → 14 taken 5657 times.
✓ Branch 13 → 15 taken 3 times.
✓ Branch 14 → 15 taken 7 times.
✓ Branch 14 → 22 taken 5650 times.
|
5660 | if (numTemplateTypes < info.minTemplateTypes || numTemplateTypes > info.maxTemplateTypes) { |
| 38 |
1/2✓ Branch 15 → 16 taken 10 times.
✗ Branch 15 → 75 not taken.
|
10 | const auto msg = buildErrorMessage(info.minTemplateTypes, info.maxTemplateTypes, numTemplateTypes, "template type(s)"); |
| 39 |
3/6✓ Branch 16 → 17 taken 10 times.
✗ Branch 16 → 73 not taken.
✓ Branch 17 → 18 taken 10 times.
✗ Branch 17 → 72 not taken.
✓ Branch 18 → 19 taken 10 times.
✗ Branch 18 → 72 not taken.
|
10 | SOFT_ERROR_ER(node, BUILTIN_TEMPLATE_TYPE_COUNT_MISMATCH, msg); |
| 40 | 10 | } | |
| 41 | |||
| 42 |
2/2✓ Branch 22 → 23 taken 4372 times.
✓ Branch 22 → 24 taken 1278 times.
|
5650 | const size_t numArgs = node->hasArgs ? node->argLst->args.size() : 0; |
| 43 |
4/4✓ Branch 25 → 26 taken 5646 times.
✓ Branch 25 → 27 taken 4 times.
✓ Branch 26 → 27 taken 9 times.
✓ Branch 26 → 34 taken 5637 times.
|
5650 | if (numArgs < info.minArgTypes || numArgs > info.maxArgTypes) { |
| 44 |
1/2✓ Branch 27 → 28 taken 13 times.
✗ Branch 27 → 79 not taken.
|
13 | const auto msg = buildErrorMessage(info.minArgTypes, info.maxArgTypes, numArgs, "argument(s)"); |
| 45 |
3/6✓ Branch 28 → 29 taken 13 times.
✗ Branch 28 → 77 not taken.
✓ Branch 29 → 30 taken 13 times.
✗ Branch 29 → 76 not taken.
✓ Branch 30 → 31 taken 13 times.
✗ Branch 30 → 76 not taken.
|
13 | SOFT_ERROR_ER(node, BUILTIN_ARG_COUNT_MISMATCH, msg); |
| 46 | 13 | } | |
| 47 | |||
| 48 |
2/2✓ Branch 34 → 35 taken 1235 times.
✓ Branch 34 → 59 taken 4402 times.
|
5637 | if (info.allTemplateTypesOrAllArgTypes) { |
| 49 |
4/4✓ Branch 35 → 36 taken 1177 times.
✓ Branch 35 → 47 taken 58 times.
✓ Branch 36 → 37 taken 4 times.
✓ Branch 36 → 47 taken 1173 times.
|
1235 | if (numTemplateTypes > 0 && numArgs > 0) |
| 50 |
4/8✓ Branch 39 → 40 taken 4 times.
✗ Branch 39 → 82 not taken.
✓ Branch 40 → 41 taken 4 times.
✗ Branch 40 → 80 not taken.
✓ Branch 43 → 44 taken 4 times.
✗ Branch 43 → 86 not taken.
✓ Branch 44 → 45 taken 4 times.
✗ Branch 44 → 86 not taken.
|
16 | SOFT_ERROR_ER(node, BUILTIN_SIGNATURE_MISMATCH, "This builtin expects either template types or arguments, but got both"); |
| 51 |
4/4✓ Branch 47 → 48 taken 58 times.
✓ Branch 47 → 59 taken 1173 times.
✓ Branch 48 → 49 taken 4 times.
✓ Branch 48 → 59 taken 54 times.
|
1231 | if (numTemplateTypes == 0 && numArgs == 0) |
| 52 |
4/8✓ Branch 51 → 52 taken 4 times.
✗ Branch 51 → 89 not taken.
✓ Branch 52 → 53 taken 4 times.
✗ Branch 52 → 87 not taken.
✓ Branch 55 → 56 taken 4 times.
✗ Branch 55 → 93 not taken.
✓ Branch 56 → 57 taken 4 times.
✗ Branch 56 → 93 not taken.
|
16 | SOFT_ERROR_ER(node, BUILTIN_SIGNATURE_MISMATCH, "This builtin expects either template types or arguments, but got none"); |
| 53 | } | ||
| 54 | |||
| 55 | // If specified, call to TypeChecker delegate to execute further checks | ||
| 56 |
3/8✓ Branch 59 → 60 taken 5629 times.
✗ Branch 59 → 64 not taken.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 5629 times.
✓ Branch 63 → 65 taken 5629 times.
✗ Branch 63 → 94 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 94 not taken.
|
11258 | return info.typeCheckerVisitMethod != nullptr ? (this->*info.typeCheckerVisitMethod)(node) : nullptr; |
| 57 | } | ||
| 58 | |||
| 59 | 1249 | std::any TypeChecker::visitBuiltinPrintfCall(FctCallNode *node) const { | |
| 60 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1249 times.
|
1249 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_PRINTF); |
| 61 | |||
| 62 | // Retrieve templated string | ||
| 63 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1249 times.
|
1249 | assert(node->hasArgs); |
| 64 | 1249 | const ExprNode *firstArg = node->argLst->args.front(); | |
| 65 |
5/10✓ Branch 9 → 10 taken 1249 times.
✗ Branch 9 → 285 not taken.
✓ Branch 10 → 11 taken 1249 times.
✗ Branch 10 → 285 not taken.
✓ Branch 11 → 12 taken 1249 times.
✗ Branch 11 → 15 not taken.
✓ Branch 12 → 13 taken 1249 times.
✗ Branch 12 → 285 not taken.
✓ Branch 13 → 14 taken 1249 times.
✗ Branch 13 → 15 not taken.
|
1249 | assert(firstArg->getEvaluatedSymbolType(manIdx).is(TY_STRING) && firstArg->hasCompileTimeValue(manIdx)); |
| 66 |
1/2✓ Branch 16 → 17 taken 1249 times.
✗ Branch 16 → 285 not taken.
|
1249 | const size_t stringOffset = firstArg->getCompileTimeValue(manIdx).stringValueOffset; |
| 67 |
2/4✓ Branch 17 → 18 taken 1249 times.
✗ Branch 17 → 285 not taken.
✓ Branch 18 → 19 taken 1249 times.
✗ Branch 18 → 285 not taken.
|
1249 | const std::string templatedString = resourceManager.compileTimeStringValues.at(stringOffset); |
| 68 | |||
| 69 | // Check if assignment types match placeholder types | ||
| 70 | 1249 | size_t placeholderCount = 0; | |
| 71 | 1249 | size_t index = templatedString.find_first_of('%'); | |
| 72 |
5/6✓ Branch 188 → 189 taken 994 times.
✓ Branch 188 → 192 taken 1241 times.
✓ Branch 190 → 191 taken 994 times.
✗ Branch 190 → 192 not taken.
✓ Branch 193 → 21 taken 994 times.
✓ Branch 193 → 194 taken 1241 times.
|
2235 | while (index != std::string::npos && index != templatedString.size() - 1) { |
| 73 | // Handle escaped percent signs (%%), which do not consume an argument | ||
| 74 |
2/4✓ Branch 21 → 22 taken 994 times.
✗ Branch 21 → 273 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 25 taken 994 times.
|
994 | if (templatedString.at(index + 1) == '%') { |
| 75 | ✗ | index = templatedString.find_first_of('%', index + 2); | |
| 76 | ✗ | continue; | |
| 77 | } | ||
| 78 | |||
| 79 | // Determine the position of the conversion specifier by skipping the optional | ||
| 80 | // flags, field width and precision (e.g. the "04" in "%04d"). These are forwarded | ||
| 81 | // verbatim to the underlying C printf, so we only need to skip over them here. | ||
| 82 | 994 | size_t specifierIndex = index + 1; | |
| 83 |
10/10✓ Branch 2 → 3 taken 1006 times.
✓ Branch 2 → 7 taken 1 time.
✓ Branch 3 → 4 taken 1005 times.
✓ Branch 3 → 7 taken 1 time.
✓ Branch 4 → 5 taken 1004 times.
✓ Branch 4 → 7 taken 1 time.
✓ Branch 5 → 6 taken 1003 times.
✓ Branch 5 → 7 taken 1 time.
✓ Branch 6 → 7 taken 9 times.
✓ Branch 6 → 8 taken 994 times.
|
1007 | auto isFlag = [](char c) { return c == '-' || c == '+' || c == ' ' || c == '#' || c == '0'; }; |
| 84 |
4/4✓ Branch 2 → 3 taken 1007 times.
✓ Branch 2 → 5 taken 2 times.
✓ Branch 3 → 4 taken 13 times.
✓ Branch 3 → 5 taken 994 times.
|
1009 | auto isDigit = [](char c) { return c >= '0' && c <= '9'; }; |
| 85 |
6/8✓ Branch 28 → 29 taken 1007 times.
✗ Branch 28 → 33 not taken.
✓ Branch 29 → 30 taken 1007 times.
✗ Branch 29 → 273 not taken.
✓ Branch 31 → 32 taken 13 times.
✓ Branch 31 → 33 taken 994 times.
✓ Branch 34 → 26 taken 13 times.
✓ Branch 34 → 35 taken 994 times.
|
1007 | while (specifierIndex < templatedString.size() && isFlag(templatedString.at(specifierIndex))) |
| 86 | 13 | specifierIndex++; // Skip flags | |
| 87 |
6/8✓ Branch 38 → 39 taken 1005 times.
✗ Branch 38 → 43 not taken.
✓ Branch 39 → 40 taken 1005 times.
✗ Branch 39 → 273 not taken.
✓ Branch 41 → 42 taken 11 times.
✓ Branch 41 → 43 taken 994 times.
✓ Branch 44 → 36 taken 11 times.
✓ Branch 44 → 45 taken 994 times.
|
1005 | while (specifierIndex < templatedString.size() && isDigit(templatedString.at(specifierIndex))) |
| 88 | 11 | specifierIndex++; // Skip field width | |
| 89 |
6/8✓ Branch 46 → 47 taken 994 times.
✗ Branch 46 → 50 not taken.
✓ Branch 47 → 48 taken 994 times.
✗ Branch 47 → 273 not taken.
✓ Branch 48 → 49 taken 2 times.
✓ Branch 48 → 50 taken 992 times.
✓ Branch 51 → 52 taken 2 times.
✓ Branch 51 → 62 taken 992 times.
|
994 | if (specifierIndex < templatedString.size() && templatedString.at(specifierIndex) == '.') { |
| 90 | 2 | specifierIndex++; // Skip precision dot | |
| 91 |
6/8✓ Branch 55 → 56 taken 4 times.
✗ Branch 55 → 60 not taken.
✓ Branch 56 → 57 taken 4 times.
✗ Branch 56 → 273 not taken.
✓ Branch 58 → 59 taken 2 times.
✓ Branch 58 → 60 taken 2 times.
✓ Branch 61 → 53 taken 2 times.
✓ Branch 61 → 62 taken 2 times.
|
4 | while (specifierIndex < templatedString.size() && isDigit(templatedString.at(specifierIndex))) |
| 92 | 2 | specifierIndex++; // Skip precision | |
| 93 | } | ||
| 94 |
1/2✗ Branch 63 → 64 not taken.
✓ Branch 63 → 74 taken 994 times.
|
994 | if (specifierIndex >= templatedString.size()) |
| 95 | ✗ | SOFT_ERROR_ER(node, PRINTF_TYPE_ERROR, "The placeholder string contains an invalid placeholder") | |
| 96 | |||
| 97 | // Check if there is another assignExpr | ||
| 98 |
2/2✓ Branch 75 → 76 taken 1 time.
✓ Branch 75 → 86 taken 993 times.
|
994 | if (node->argLst->args.size() - 1 <= placeholderCount) |
| 99 |
4/8✓ Branch 78 → 79 taken 1 time.
✗ Branch 78 → 223 not taken.
✓ Branch 79 → 80 taken 1 time.
✗ Branch 79 → 221 not taken.
✓ Branch 82 → 83 taken 1 time.
✗ Branch 82 → 227 not taken.
✓ Branch 83 → 84 taken 1 time.
✗ Branch 83 → 227 not taken.
|
4 | SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains more placeholders than arguments") |
| 100 | |||
| 101 | // Get next assignment | ||
| 102 |
1/2✓ Branch 86 → 87 taken 993 times.
✗ Branch 86 → 273 not taken.
|
993 | const ExprNode *assignment = node->argLst->args.at(placeholderCount + 1); |
| 103 | // Visit assignment | ||
| 104 |
1/2✓ Branch 87 → 88 taken 993 times.
✗ Branch 87 → 273 not taken.
|
993 | QualType argType = assignment->getEvaluatedSymbolType(manIdx); |
| 105 |
2/8✓ Branch 88 → 89 taken 993 times.
✗ Branch 88 → 273 not taken.
✗ Branch 89 → 90 not taken.
✓ Branch 89 → 94 taken 993 times.
✗ Branch 90 → 91 not taken.
✗ Branch 90 → 228 not taken.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 228 not taken.
|
993 | HANDLE_UNRESOLVED_TYPE_ER(argType) |
| 106 |
1/2✓ Branch 94 → 95 taken 993 times.
✗ Branch 94 → 229 not taken.
|
993 | argType = argType.removeReferenceWrapper(); |
| 107 | |||
| 108 |
7/8✓ Branch 95 → 96 taken 993 times.
✗ Branch 95 → 273 not taken.
✓ Branch 96 → 97 taken 33 times.
✓ Branch 96 → 109 taken 461 times.
✓ Branch 96 → 121 taken 103 times.
✓ Branch 96 → 133 taken 389 times.
✓ Branch 96 → 154 taken 6 times.
✓ Branch 96 → 173 taken 1 time.
|
993 | switch (templatedString.at(specifierIndex)) { |
| 109 | 33 | case 'c': { | |
| 110 |
3/4✓ Branch 97 → 98 taken 33 times.
✗ Branch 97 → 273 not taken.
✓ Branch 98 → 99 taken 1 time.
✓ Branch 98 → 108 taken 32 times.
|
33 | if (!argType.is(TY_CHAR)) |
| 111 |
5/10✓ Branch 99 → 100 taken 1 time.
✗ Branch 99 → 234 not taken.
✓ Branch 100 → 101 taken 1 time.
✗ Branch 100 → 232 not taken.
✓ Branch 101 → 102 taken 1 time.
✗ Branch 101 → 230 not taken.
✓ Branch 104 → 105 taken 1 time.
✗ Branch 104 → 236 not taken.
✓ Branch 105 → 106 taken 1 time.
✗ Branch 105 → 236 not taken.
|
2 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects char, but got " + argType.getName(false)) |
| 112 | 32 | placeholderCount++; | |
| 113 | 32 | break; | |
| 114 | } | ||
| 115 | 461 | case 'd': | |
| 116 | case 'i': | ||
| 117 | case 'l': | ||
| 118 | case 'o': | ||
| 119 | case 'u': | ||
| 120 | case 'x': | ||
| 121 | case 'X': { | ||
| 122 |
3/4✓ Branch 109 → 110 taken 461 times.
✗ Branch 109 → 237 not taken.
✓ Branch 110 → 111 taken 2 times.
✓ Branch 110 → 120 taken 459 times.
|
461 | if (!argType.isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_BOOL})) |
| 123 |
5/10✓ Branch 111 → 112 taken 2 times.
✗ Branch 111 → 242 not taken.
✓ Branch 112 → 113 taken 2 times.
✗ Branch 112 → 240 not taken.
✓ Branch 113 → 114 taken 2 times.
✗ Branch 113 → 238 not taken.
✓ Branch 116 → 117 taken 2 times.
✗ Branch 116 → 244 not taken.
✓ Branch 117 → 118 taken 2 times.
✗ Branch 117 → 244 not taken.
|
4 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, |
| 124 | "The placeholder string expects int, short, long, byte or bool, but got " + argType.getName(false)) | ||
| 125 | 459 | placeholderCount++; | |
| 126 | 459 | break; | |
| 127 | } | ||
| 128 | 103 | case 'a': | |
| 129 | case 'A': | ||
| 130 | case 'f': | ||
| 131 | case 'F': | ||
| 132 | case 'e': | ||
| 133 | case 'E': | ||
| 134 | case 'g': | ||
| 135 | case 'G': { | ||
| 136 |
3/4✓ Branch 121 → 122 taken 103 times.
✗ Branch 121 → 273 not taken.
✓ Branch 122 → 123 taken 1 time.
✓ Branch 122 → 132 taken 102 times.
|
103 | if (!argType.is(TY_DOUBLE)) |
| 137 |
5/10✓ Branch 123 → 124 taken 1 time.
✗ Branch 123 → 249 not taken.
✓ Branch 124 → 125 taken 1 time.
✗ Branch 124 → 247 not taken.
✓ Branch 125 → 126 taken 1 time.
✗ Branch 125 → 245 not taken.
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 251 not taken.
✓ Branch 129 → 130 taken 1 time.
✗ Branch 129 → 251 not taken.
|
2 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects double, but got " + argType.getName(false)) |
| 138 | 102 | placeholderCount++; | |
| 139 | 102 | break; | |
| 140 | } | ||
| 141 | 389 | case 's': { | |
| 142 |
13/18✓ Branch 133 → 134 taken 389 times.
✗ Branch 133 → 273 not taken.
✓ Branch 134 → 135 taken 83 times.
✓ Branch 134 → 142 taken 306 times.
✓ Branch 135 → 136 taken 83 times.
✗ Branch 135 → 273 not taken.
✓ Branch 136 → 137 taken 2 times.
✓ Branch 136 → 142 taken 81 times.
✓ Branch 137 → 138 taken 2 times.
✗ Branch 137 → 273 not taken.
✓ Branch 138 → 139 taken 1 time.
✓ Branch 138 → 142 taken 1 time.
✓ Branch 139 → 140 taken 1 time.
✗ Branch 139 → 273 not taken.
✓ Branch 140 → 141 taken 1 time.
✗ Branch 140 → 142 not taken.
✓ Branch 143 → 144 taken 1 time.
✓ Branch 143 → 153 taken 388 times.
|
389 | if (!argType.is(TY_STRING) && !argType.isStringObj() && !argType.isPtrTo(TY_CHAR) && !argType.isArrayOf(TY_CHAR)) |
| 143 |
5/10✓ Branch 144 → 145 taken 1 time.
✗ Branch 144 → 256 not taken.
✓ Branch 145 → 146 taken 1 time.
✗ Branch 145 → 254 not taken.
✓ Branch 146 → 147 taken 1 time.
✗ Branch 146 → 252 not taken.
✓ Branch 149 → 150 taken 1 time.
✗ Branch 149 → 258 not taken.
✓ Branch 150 → 151 taken 1 time.
✗ Branch 150 → 258 not taken.
|
2 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, |
| 144 | "The placeholder string expects string, String, char* or char[], but got " + argType.getName(false)) | ||
| 145 | 388 | placeholderCount++; | |
| 146 | 388 | break; | |
| 147 | } | ||
| 148 | 6 | case 'p': { | |
| 149 |
9/14✓ Branch 154 → 155 taken 6 times.
✗ Branch 154 → 273 not taken.
✓ Branch 155 → 156 taken 1 time.
✓ Branch 155 → 161 taken 5 times.
✓ Branch 156 → 157 taken 1 time.
✗ Branch 156 → 273 not taken.
✓ Branch 157 → 158 taken 1 time.
✗ Branch 157 → 161 not taken.
✓ Branch 158 → 159 taken 1 time.
✗ Branch 158 → 273 not taken.
✓ Branch 159 → 160 taken 1 time.
✗ Branch 159 → 161 not taken.
✓ Branch 162 → 163 taken 1 time.
✓ Branch 162 → 172 taken 5 times.
|
6 | if (!argType.isPtr() && !argType.isArray() && !argType.is(TY_STRING)) |
| 150 |
5/10✓ Branch 163 → 164 taken 1 time.
✗ Branch 163 → 263 not taken.
✓ Branch 164 → 165 taken 1 time.
✗ Branch 164 → 261 not taken.
✓ Branch 165 → 166 taken 1 time.
✗ Branch 165 → 259 not taken.
✓ Branch 168 → 169 taken 1 time.
✗ Branch 168 → 265 not taken.
✓ Branch 169 → 170 taken 1 time.
✗ Branch 169 → 265 not taken.
|
2 | SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, |
| 151 | "The placeholder string expects pointer, array or string, but got " + argType.getName(false)) | ||
| 152 | 5 | placeholderCount++; | |
| 153 | 5 | break; | |
| 154 | } | ||
| 155 | 1 | default: | |
| 156 |
4/8✓ Branch 175 → 176 taken 1 time.
✗ Branch 175 → 268 not taken.
✓ Branch 176 → 177 taken 1 time.
✗ Branch 176 → 266 not taken.
✓ Branch 179 → 180 taken 1 time.
✗ Branch 179 → 272 not taken.
✓ Branch 180 → 181 taken 1 time.
✗ Branch 180 → 272 not taken.
|
4 | SOFT_ERROR_ER(node, PRINTF_TYPE_ERROR, "The placeholder string contains an invalid placeholder") |
| 157 | } | ||
| 158 | 986 | index = templatedString.find_first_of('%', specifierIndex + 1); // We can also skip the conversion specifier | |
| 159 | } | ||
| 160 | |||
| 161 | // Check if the number of placeholders matches the number of args | ||
| 162 |
2/2✓ Branch 195 → 196 taken 1 time.
✓ Branch 195 → 206 taken 1240 times.
|
1241 | if (placeholderCount < node->argLst->args.size() - 1) |
| 163 |
4/8✓ Branch 198 → 199 taken 1 time.
✗ Branch 198 → 276 not taken.
✓ Branch 199 → 200 taken 1 time.
✗ Branch 199 → 274 not taken.
✓ Branch 202 → 203 taken 1 time.
✗ Branch 202 → 280 not taken.
✓ Branch 203 → 204 taken 1 time.
✗ Branch 203 → 280 not taken.
|
4 | SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains less placeholders than arguments") |
| 164 | |||
| 165 |
3/6✓ Branch 206 → 207 taken 1240 times.
✗ Branch 206 → 281 not taken.
✓ Branch 207 → 208 taken 1240 times.
✗ Branch 207 → 281 not taken.
✓ Branch 208 → 209 taken 1240 times.
✗ Branch 208 → 281 not taken.
|
2480 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_INT), manIdx)}; |
| 166 | 1249 | } | |
| 167 | |||
| 168 | 1106 | std::any TypeChecker::visitBuiltinSizeOfCall(FctCallNode *node) const { | |
| 169 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1106 times.
|
1106 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_SIZEOF); |
| 170 | |||
| 171 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 172 | 1106 | QualType qualType; | |
| 173 |
2/2✓ Branch 6 → 7 taken 1066 times.
✓ Branch 6 → 10 taken 40 times.
|
1106 | if (node->hasTemplateTypes) { // Align of type |
| 174 |
1/2✓ Branch 8 → 9 taken 1066 times.
✗ Branch 8 → 54 not taken.
|
1066 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 175 | } else { // Align of value | ||
| 176 |
1/2✓ Branch 11 → 12 taken 40 times.
✗ Branch 11 → 54 not taken.
|
40 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 177 | } | ||
| 178 | |||
| 179 |
3/4✓ Branch 13 → 14 taken 1106 times.
✗ Branch 13 → 40 not taken.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 25 taken 1104 times.
|
1106 | if (qualType.isOneOf({TY_UNRESOLVED, TY_DYN})) |
| 180 |
4/8✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 43 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 41 not taken.
✓ Branch 21 → 22 taken 2 times.
✗ Branch 21 → 47 not taken.
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 47 not taken.
|
8 | SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Cannot use sizeof on a dyn or unresolved type"); |
| 181 | |||
| 182 |
1/2✓ Branch 25 → 26 taken 1104 times.
✗ Branch 25 → 54 not taken.
|
1104 | llvm::Type *type = qualType.toLLVMType(sourceFile); |
| 183 |
3/6✓ Branch 27 → 28 taken 1104 times.
✗ Branch 27 → 50 not taken.
✓ Branch 28 → 29 taken 1104 times.
✗ Branch 28 → 48 not taken.
✓ Branch 29 → 30 taken 1104 times.
✗ Branch 29 → 48 not taken.
|
1104 | const int64_t typeSize = sourceFile->targetMachine->createDataLayout().getTypeAllocSize(type); |
| 184 |
1/2✓ Branch 31 → 32 taken 1104 times.
✗ Branch 31 → 54 not taken.
|
1104 | node->data.at(manIdx).setCompileTimeValue({.longValue = typeSize}); |
| 185 | |||
| 186 |
3/6✓ Branch 33 → 34 taken 1104 times.
✗ Branch 33 → 52 not taken.
✓ Branch 34 → 35 taken 1104 times.
✗ Branch 34 → 52 not taken.
✓ Branch 35 → 36 taken 1104 times.
✗ Branch 35 → 52 not taken.
|
2208 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 187 | } | ||
| 188 | |||
| 189 | 13 | std::any TypeChecker::visitBuiltinAlignOfCall(FctCallNode *node) const { | |
| 190 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 13 times.
|
13 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_ALIGNOF); |
| 191 | |||
| 192 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 193 | 13 | QualType qualType; | |
| 194 |
2/2✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 10 taken 11 times.
|
13 | if (node->hasTemplateTypes) { // Align of type |
| 195 |
1/2✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 54 not taken.
|
2 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 196 | } else { // Align of value | ||
| 197 |
1/2✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 54 not taken.
|
11 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 198 | } | ||
| 199 | |||
| 200 |
3/4✓ Branch 13 → 14 taken 13 times.
✗ Branch 13 → 40 not taken.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 25 taken 11 times.
|
13 | if (qualType.isOneOf({TY_UNRESOLVED, TY_DYN})) |
| 201 |
4/8✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 43 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 41 not taken.
✓ Branch 21 → 22 taken 2 times.
✗ Branch 21 → 47 not taken.
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 47 not taken.
|
8 | SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Cannot use alignof on a dyn or unresolved type"); |
| 202 | |||
| 203 |
1/2✓ Branch 25 → 26 taken 11 times.
✗ Branch 25 → 54 not taken.
|
11 | llvm::Type *type = qualType.toLLVMType(sourceFile); |
| 204 |
2/4✓ Branch 27 → 28 taken 11 times.
✗ Branch 27 → 50 not taken.
✓ Branch 28 → 29 taken 11 times.
✗ Branch 28 → 48 not taken.
|
11 | const int64_t typeAlignment = sourceFile->targetMachine->createDataLayout().getABITypeAlign(type).value(); |
| 205 |
1/2✓ Branch 31 → 32 taken 11 times.
✗ Branch 31 → 54 not taken.
|
11 | node->data.at(manIdx).setCompileTimeValue({.longValue = typeAlignment}); |
| 206 | |||
| 207 |
3/6✓ Branch 33 → 34 taken 11 times.
✗ Branch 33 → 52 not taken.
✓ Branch 34 → 35 taken 11 times.
✗ Branch 34 → 52 not taken.
✓ Branch 35 → 36 taken 11 times.
✗ Branch 35 → 52 not taken.
|
22 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 208 | } | ||
| 209 | |||
| 210 | 10 | std::any TypeChecker::visitBuiltinOffsetOfCall(FctCallNode *node) const { | |
| 211 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 10 times.
|
10 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_OFFSETOF); |
| 212 |
2/4✓ Branch 6 → 7 taken 10 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 10 times.
✗ Branch 8 → 10 not taken.
|
10 | assert(node->hasArgs && node->argLst->args.size() == 2); |
| 213 | |||
| 214 | // The first argument denotes the struct to compute the offset within | ||
| 215 |
1/2✓ Branch 11 → 12 taken 10 times.
✗ Branch 11 → 225 not taken.
|
10 | const ExprNode *structArg = node->argLst->args.at(0); |
| 216 |
3/6✓ Branch 12 → 13 taken 10 times.
✗ Branch 12 → 170 not taken.
✓ Branch 13 → 14 taken 10 times.
✗ Branch 13 → 170 not taken.
✓ Branch 14 → 15 taken 10 times.
✗ Branch 14 → 170 not taken.
|
10 | const QualType structType = structArg->getEvaluatedSymbolType(manIdx).removeReferenceWrapper().autoDeReference(); |
| 217 |
3/4✓ Branch 15 → 16 taken 10 times.
✗ Branch 15 → 225 not taken.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 27 taken 9 times.
|
10 | if (!structType.is(TY_STRUCT)) |
| 218 |
4/8✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 173 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 171 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 177 not taken.
✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 177 not taken.
|
4 | SOFT_ERROR_ER(structArg, EXPECTED_STRUCT_TYPE, "The offsetof builtin expects a struct as its first argument") |
| 219 | |||
| 220 | // The second argument must be a (possibly chained) member access, denoting the field to compute the offset of | ||
| 221 |
1/2✓ Branch 27 → 28 taken 9 times.
✗ Branch 27 → 225 not taken.
|
9 | const ExprNode *memberArg = node->argLst->args.at(1); |
| 222 | 9 | const PostfixUnaryExprNode *leafAccess = nullptr; | |
| 223 |
2/2✓ Branch 43 → 29 taken 9 times.
✓ Branch 43 → 44 taken 1 time.
|
10 | for (const ASTNode *cur = memberArg; cur != nullptr;) { |
| 224 |
3/4✓ Branch 29 → 30 taken 9 times.
✗ Branch 29 → 31 not taken.
✓ Branch 32 → 33 taken 8 times.
✓ Branch 32 → 34 taken 1 time.
|
9 | if (const auto *postfix = dynamic_cast<const PostfixUnaryExprNode *>(cur)) { |
| 225 | 8 | leafAccess = postfix; | |
| 226 | 8 | break; | |
| 227 | } | ||
| 228 |
1/2✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 178 not taken.
|
1 | const std::vector<ASTNode *> children = cur->getChildren(); |
| 229 |
1/2✗ Branch 36 → 37 not taken.
✓ Branch 36 → 39 taken 1 time.
|
1 | cur = children.size() == 1 ? children.front() : nullptr; |
| 230 | 1 | } | |
| 231 |
3/4✓ Branch 44 → 45 taken 8 times.
✓ Branch 44 → 46 taken 1 time.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 56 taken 8 times.
|
9 | if (leafAccess == nullptr || leafAccess->op != PostfixUnaryExprNode::PostfixUnaryOp::OP_MEMBER_ACCESS) |
| 232 |
4/8✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 181 not taken.
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 179 not taken.
✓ Branch 52 → 53 taken 1 time.
✗ Branch 52 → 185 not taken.
✓ Branch 53 → 54 taken 1 time.
✗ Branch 53 → 185 not taken.
|
4 | SOFT_ERROR_ER(memberArg, INVALID_MEMBER_ACCESS, "The offsetof builtin expects a struct member access as its second argument") |
| 233 | |||
| 234 | // Collect the chain of member accesses (from leaf to base). Only plain member accesses are supported. | ||
| 235 | 8 | std::vector<const PostfixUnaryExprNode *> accessChain; | |
| 236 |
2/2✓ Branch 73 → 57 taken 10 times.
✓ Branch 73 → 74 taken 8 times.
|
18 | for (const PostfixUnaryExprNode *access = leafAccess; access != nullptr;) { |
| 237 |
1/2✗ Branch 57 → 58 not taken.
✓ Branch 57 → 68 taken 10 times.
|
10 | if (access->op != PostfixUnaryExprNode::PostfixUnaryOp::OP_MEMBER_ACCESS) |
| 238 | ✗ | SOFT_ERROR_ER(memberArg, INVALID_MEMBER_ACCESS, "The offsetof builtin only supports plain member accesses") | |
| 239 |
1/2✓ Branch 68 → 69 taken 10 times.
✗ Branch 68 → 193 not taken.
|
10 | accessChain.push_back(access); |
| 240 |
1/2✓ Branch 69 → 70 taken 10 times.
✗ Branch 69 → 71 not taken.
|
10 | access = dynamic_cast<const PostfixUnaryExprNode *>(access->postfixUnaryExpr); |
| 241 | } | ||
| 242 | |||
| 243 | // Ensure the base of the member access chain is the struct that was passed as first argument | ||
| 244 | 8 | const QualType chainBaseType = | |
| 245 |
3/6✓ Branch 75 → 76 taken 8 times.
✗ Branch 75 → 194 not taken.
✓ Branch 76 → 77 taken 8 times.
✗ Branch 76 → 194 not taken.
✓ Branch 77 → 78 taken 8 times.
✗ Branch 77 → 194 not taken.
|
8 | accessChain.back()->postfixUnaryExpr->getEvaluatedSymbolType(manIdx).removeReferenceWrapper().autoDeReference(); |
| 246 |
2/4✓ Branch 78 → 79 taken 8 times.
✗ Branch 78 → 223 not taken.
✗ Branch 79 → 80 not taken.
✓ Branch 79 → 90 taken 8 times.
|
8 | if (!chainBaseType.matches(structType, false, true, false)) |
| 247 | ✗ | SOFT_ERROR_ER(memberArg, INVALID_MEMBER_ACCESS, "The member access must be rooted in the struct passed as first argument") | |
| 248 | |||
| 249 | // Accumulate the byte offset by walking each access in the chain through its struct layout | ||
| 250 |
1/2✓ Branch 91 → 92 taken 8 times.
✗ Branch 91 → 223 not taken.
|
8 | const llvm::DataLayout dataLayout = sourceFile->targetMachine->createDataLayout(); |
| 251 | 8 | int64_t offset = 0; | |
| 252 |
2/2✓ Branch 158 → 94 taken 10 times.
✓ Branch 158 → 159 taken 8 times.
|
26 | for (const PostfixUnaryExprNode *access : accessChain) { |
| 253 | 10 | const QualType baseType = | |
| 254 |
3/6✓ Branch 96 → 97 taken 10 times.
✗ Branch 96 → 202 not taken.
✓ Branch 97 → 98 taken 10 times.
✗ Branch 97 → 202 not taken.
✓ Branch 98 → 99 taken 10 times.
✗ Branch 98 → 202 not taken.
|
10 | access->postfixUnaryExpr->getEvaluatedSymbolType(manIdx).removeReferenceWrapper().autoDeReference(); |
| 255 |
2/4✓ Branch 99 → 100 taken 10 times.
✗ Branch 99 → 217 not taken.
✗ Branch 100 → 101 not taken.
✓ Branch 100 → 102 taken 10 times.
|
10 | assert(baseType.is(TY_STRUCT)); |
| 256 | |||
| 257 | // Resolve the struct body scope (substantiate the generic scope if required) | ||
| 258 |
1/2✓ Branch 102 → 103 taken 10 times.
✗ Branch 102 → 217 not taken.
|
10 | Scope *structScope = baseType.getBodyScope(); |
| 259 |
1/2✗ Branch 103 → 104 not taken.
✓ Branch 103 → 108 taken 10 times.
|
10 | if (structScope->isGenericScope) { |
| 260 | ✗ | const Struct *spiceStruct = baseType.getStruct(node); | |
| 261 | ✗ | assert(spiceStruct != nullptr); | |
| 262 | ✗ | structScope = spiceStruct->scope; | |
| 263 | } | ||
| 264 |
1/2✗ Branch 108 → 109 not taken.
✓ Branch 108 → 110 taken 10 times.
|
10 | assert(!structScope->isGenericScope); |
| 265 | |||
| 266 | // Look up the accessed field to retrieve its index path within the struct | ||
| 267 | 10 | std::vector<size_t> indexPath; | |
| 268 |
1/2✓ Branch 110 → 111 taken 10 times.
✗ Branch 110 → 215 not taken.
|
10 | const SymbolTableEntry *fieldEntry = structScope->symbolTable.lookupInComposedFields(access->identifier, indexPath); |
| 269 |
1/2✗ Branch 111 → 112 not taken.
✓ Branch 111 → 124 taken 10 times.
|
10 | if (fieldEntry == nullptr) |
| 270 | ✗ | SOFT_ERROR_ER(memberArg, REFERENCED_UNDEFINED_FIELD, | |
| 271 | "Field '" + access->identifier + "' not found in struct " + baseType.getSubType()) | ||
| 272 | |||
| 273 | // Walk the index path through the struct layout to accumulate the byte offset of the field | ||
| 274 |
1/2✓ Branch 124 → 125 taken 10 times.
✗ Branch 124 → 215 not taken.
|
10 | llvm::Type *currentType = baseType.toLLVMType(sourceFile); |
| 275 |
2/2✓ Branch 143 → 127 taken 10 times.
✓ Branch 143 → 144 taken 10 times.
|
30 | for (const size_t index : indexPath) { |
| 276 |
1/2✓ Branch 129 → 130 taken 10 times.
✗ Branch 129 → 214 not taken.
|
10 | auto *structLLVMType = llvm::cast<llvm::StructType>(currentType); |
| 277 |
3/6✓ Branch 130 → 131 taken 10 times.
✗ Branch 130 → 213 not taken.
✓ Branch 131 → 132 taken 10 times.
✗ Branch 131 → 213 not taken.
✓ Branch 132 → 133 taken 10 times.
✗ Branch 132 → 213 not taken.
|
10 | offset += static_cast<int64_t>(dataLayout.getStructLayout(structLLVMType)->getElementOffset(index)); |
| 278 | 10 | currentType = structLLVMType->getElementType(index); | |
| 279 | } | ||
| 280 |
1/2✓ Branch 146 → 147 taken 10 times.
✗ Branch 146 → 151 not taken.
|
10 | } |
| 281 |
1/2✓ Branch 159 → 160 taken 8 times.
✗ Branch 159 → 221 not taken.
|
8 | node->data.at(manIdx).setCompileTimeValue({.longValue = offset}); |
| 282 | |||
| 283 |
3/6✓ Branch 161 → 162 taken 8 times.
✗ Branch 161 → 219 not taken.
✓ Branch 162 → 163 taken 8 times.
✗ Branch 162 → 219 not taken.
✓ Branch 163 → 164 taken 8 times.
✗ Branch 163 → 219 not taken.
|
16 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 284 | 8 | } | |
| 285 | |||
| 286 | 27 | std::any TypeChecker::visitBuiltinTypeIdCall(FctCallNode *node) const { | |
| 287 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 27 times.
|
27 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_TYPEID); |
| 288 | |||
| 289 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 290 | 27 | QualType qualType; | |
| 291 |
2/2✓ Branch 6 → 7 taken 26 times.
✓ Branch 6 → 10 taken 1 time.
|
27 | if (node->hasTemplateTypes) { // typeid of type |
| 292 |
1/2✓ Branch 8 → 9 taken 26 times.
✗ Branch 8 → 26 not taken.
|
26 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 293 | } else { // typeid of value | ||
| 294 |
1/2✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 26 not taken.
|
1 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 295 | } | ||
| 296 |
1/2✓ Branch 14 → 15 taken 27 times.
✗ Branch 14 → 26 not taken.
|
27 | const uint64_t typeId = TypeRegistry::getTypeHash(*qualType.getType()); |
| 297 |
1/2✓ Branch 15 → 16 taken 27 times.
✗ Branch 15 → 26 not taken.
|
27 | node->data.at(manIdx).setCompileTimeValue({.longValue = std::bit_cast<int64_t>(typeId)}); |
| 298 | |||
| 299 |
3/6✓ Branch 18 → 19 taken 27 times.
✗ Branch 18 → 24 not taken.
✓ Branch 19 → 20 taken 27 times.
✗ Branch 19 → 24 not taken.
✓ Branch 20 → 21 taken 27 times.
✗ Branch 20 → 24 not taken.
|
54 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 300 | } | ||
| 301 | |||
| 302 | 81 | std::any TypeChecker::visitBuiltinTypeNameCall(FctCallNode *node) const { | |
| 303 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 81 times.
|
81 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_TYPENAME); |
| 304 | |||
| 305 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 306 | 81 | QualType qualType; | |
| 307 |
2/2✓ Branch 6 → 7 taken 79 times.
✓ Branch 6 → 10 taken 2 times.
|
81 | if (node->hasTemplateTypes) { // typename of type |
| 308 |
1/2✓ Branch 8 → 9 taken 79 times.
✗ Branch 8 → 30 not taken.
|
79 | qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 309 | } else { // typename of value | ||
| 310 |
1/2✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 30 not taken.
|
2 | qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 311 | } | ||
| 312 | 81 | const size_t stringValueOffset = resourceManager.compileTimeStringValues.size(); | |
| 313 |
2/4✓ Branch 14 → 15 taken 81 times.
✗ Branch 14 → 27 not taken.
✓ Branch 15 → 16 taken 81 times.
✗ Branch 15 → 25 not taken.
|
81 | resourceManager.compileTimeStringValues.push_back(qualType.getName()); |
| 314 |
1/2✓ Branch 17 → 18 taken 81 times.
✗ Branch 17 → 30 not taken.
|
81 | node->data.at(manIdx).setCompileTimeValue({.stringValueOffset = stringValueOffset}); |
| 315 | |||
| 316 |
3/6✓ Branch 19 → 20 taken 81 times.
✗ Branch 19 → 28 not taken.
✓ Branch 20 → 21 taken 81 times.
✗ Branch 20 → 28 not taken.
✓ Branch 21 → 22 taken 81 times.
✗ Branch 21 → 28 not taken.
|
162 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_STRING), manIdx)}; |
| 317 | } | ||
| 318 | |||
| 319 | 336 | std::any TypeChecker::visitBuiltinLenCall(FctCallNode *node) const { | |
| 320 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 336 times.
|
336 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_LEN); |
| 321 | |||
| 322 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 323 |
1/2✓ Branch 7 → 8 taken 336 times.
✗ Branch 7 → 56 not taken.
|
336 | QualType argType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx); |
| 324 |
1/2✓ Branch 8 → 9 taken 336 times.
✗ Branch 8 → 45 not taken.
|
336 | argType = argType.removeReferenceWrapper(); |
| 325 | |||
| 326 | // Check if arg is of type array | ||
| 327 |
8/10✓ Branch 9 → 10 taken 336 times.
✗ Branch 9 → 56 not taken.
✓ Branch 10 → 11 taken 77 times.
✓ Branch 10 → 14 taken 259 times.
✓ Branch 11 → 12 taken 77 times.
✗ Branch 11 → 56 not taken.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 76 times.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 27 taken 335 times.
|
336 | if (!argType.isArray() && !argType.is(TY_STRING)) |
| 328 |
4/8✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 48 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 46 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 52 not taken.
✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 52 not taken.
|
4 | SOFT_ERROR_ER(node->argLst->args.front(), EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays or strings") |
| 329 | |||
| 330 |
3/4✓ Branch 27 → 28 taken 335 times.
✗ Branch 27 → 56 not taken.
✓ Branch 28 → 29 taken 259 times.
✓ Branch 28 → 33 taken 76 times.
|
335 | if (argType.is(TY_ARRAY)) { |
| 331 |
2/4✓ Branch 29 → 30 taken 259 times.
✗ Branch 29 → 56 not taken.
✓ Branch 30 → 31 taken 259 times.
✗ Branch 30 → 53 not taken.
|
259 | node->data.at(manIdx).setCompileTimeValue({.longValue = static_cast<int64_t>(argType.getArraySize())}); |
| 332 | } else { | ||
| 333 | // If we want to use the len builtin on a string, we need to import the string runtime module | ||
| 334 |
3/4✓ Branch 33 → 34 taken 76 times.
✗ Branch 33 → 56 not taken.
✓ Branch 36 → 37 taken 75 times.
✓ Branch 36 → 38 taken 1 time.
|
152 | if (!sourceFile->isStringRT()) |
| 335 |
1/2✓ Branch 37 → 38 taken 75 times.
✗ Branch 37 → 56 not taken.
|
75 | sourceFile->requestRuntimeModule(STRING_RT); |
| 336 | } | ||
| 337 | |||
| 338 |
3/6✓ Branch 38 → 39 taken 335 times.
✗ Branch 38 → 54 not taken.
✓ Branch 39 → 40 taken 335 times.
✗ Branch 39 → 54 not taken.
✓ Branch 40 → 41 taken 335 times.
✗ Branch 40 → 54 not taken.
|
670 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 339 | } | ||
| 340 | |||
| 341 | 2233 | std::any TypeChecker::visitBuiltinPanicCall(FctCallNode *node) const { | |
| 342 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2233 times.
|
2233 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_PANIC); |
| 343 | |||
| 344 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2233 times.
|
2233 | assert(node->hasArgs); |
| 345 | 2233 | const ExprNode *assignExpr = node->argLst->args.front(); | |
| 346 |
1/2✓ Branch 9 → 10 taken 2233 times.
✗ Branch 9 → 47 not taken.
|
2233 | QualType argType = assignExpr->getEvaluatedSymbolType(manIdx); |
| 347 |
2/8✓ Branch 10 → 11 taken 2233 times.
✗ Branch 10 → 47 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 16 taken 2233 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 36 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 36 not taken.
|
2233 | HANDLE_UNRESOLVED_TYPE_ER(argType) |
| 348 |
1/2✓ Branch 16 → 17 taken 2233 times.
✗ Branch 16 → 37 not taken.
|
2233 | argType = argType.removeReferenceWrapper(); |
| 349 | |||
| 350 | // Check if arg is of type array | ||
| 351 |
3/4✓ Branch 17 → 18 taken 2233 times.
✗ Branch 17 → 47 not taken.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 18 → 29 taken 2232 times.
|
2233 | if (!argType.isErrorObj()) |
| 352 |
4/8✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 40 not taken.
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 38 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 44 not taken.
✓ Branch 26 → 27 taken 1 time.
✗ Branch 26 → 44 not taken.
|
4 | SOFT_ERROR_ER(assignExpr, EXPECTED_ERROR_TYPE, "The panic builtin can only work with errors") |
| 353 | |||
| 354 |
3/6✓ Branch 29 → 30 taken 2232 times.
✗ Branch 29 → 45 not taken.
✓ Branch 30 → 31 taken 2232 times.
✗ Branch 30 → 45 not taken.
✓ Branch 31 → 32 taken 2232 times.
✗ Branch 31 → 45 not taken.
|
4464 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_DYN), manIdx)}; |
| 355 | } | ||
| 356 | |||
| 357 | 4 | std::any TypeChecker::visitBuiltinSyscallCall(FctCallNode *node) const { | |
| 358 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 4 times.
|
4 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_SYSCALL); |
| 359 | |||
| 360 | // Check if the syscall number if of type short | ||
| 361 | 4 | const ExprNode *sysCallNumberExpr = node->argLst->args.front(); | |
| 362 |
1/2✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 57 not taken.
|
4 | const QualType sysCallNumberType = sysCallNumberExpr->getEvaluatedSymbolType(manIdx); |
| 363 |
3/4✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 57 not taken.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 20 taken 3 times.
|
4 | if (!sysCallNumberType.is(TY_SHORT)) |
| 364 |
4/8✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 43 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 41 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 47 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 47 not taken.
|
4 | SOFT_ERROR_ER(sysCallNumberExpr, INVALID_SYSCALL_NUMBER_TYPE, "Syscall number must be of type short") |
| 365 | |||
| 366 | // Check if the syscall number is out of range | ||
| 367 | // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/ | ||
| 368 |
2/4✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 57 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 34 taken 3 times.
|
3 | if (node->hasCompileTimeValue(manIdx)) { |
| 369 | ✗ | const unsigned short sysCallNumber = node->getCompileTimeValue(manIdx).shortValue; | |
| 370 | ✗ | if (sysCallNumber < 0 || sysCallNumber > 439) | |
| 371 | ✗ | SOFT_ERROR_ER(node, SYSCALL_NUMBER_OUT_OF_RANGE, "Only syscall numbers between 0 and 439 are supported") | |
| 372 | } | ||
| 373 | |||
| 374 |
3/6✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 55 not taken.
✓ Branch 35 → 36 taken 3 times.
✗ Branch 35 → 55 not taken.
✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 55 not taken.
|
6 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)}; |
| 375 | } | ||
| 376 | |||
| 377 | 6 | std::any TypeChecker::visitBuiltinIsSameCall(FctCallNode *node) const { | |
| 378 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 6 times.
|
6 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IS_SAME); |
| 379 | |||
| 380 | // Directly set compile time value here, so that compile time ifs can be evaluated. | ||
| 381 |
1/2✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 26 not taken.
|
6 | node->setCompileTimeValue({.boolValue = true}, manIdx); |
| 382 | 6 | const std::vector<DataTypeNode *> &dataTypeNodes = node->templateTypeLst->dataTypes; | |
| 383 |
1/2✓ Branch 8 → 9 taken 6 times.
✗ Branch 8 → 31 not taken.
|
6 | const QualType firstType = dataTypeNodes.front()->getEvaluatedSymbolType(manIdx); |
| 384 |
2/2✓ Branch 19 → 10 taken 6 times.
✓ Branch 19 → 20 taken 2 times.
|
8 | for (size_t i = 1; i < dataTypeNodes.size(); i++) { |
| 385 |
2/4✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 28 not taken.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 28 not taken.
|
6 | const QualType qualType = dataTypeNodes.at(i)->getEvaluatedSymbolType(manIdx); |
| 386 |
3/4✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 28 not taken.
✓ Branch 13 → 14 taken 4 times.
✓ Branch 13 → 16 taken 2 times.
|
6 | if (!qualType.matches(firstType, false, true, false)) { |
| 387 |
1/2✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 27 not taken.
|
4 | node->setCompileTimeValue({.boolValue = false}, manIdx); |
| 388 | 4 | break; | |
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 |
3/6✓ Branch 20 → 21 taken 6 times.
✗ Branch 20 → 29 not taken.
✓ Branch 21 → 22 taken 6 times.
✗ Branch 21 → 29 not taken.
✓ Branch 22 → 23 taken 6 times.
✗ Branch 22 → 29 not taken.
|
12 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 393 | } | ||
| 394 | |||
| 395 | 1 | std::any TypeChecker::visitBuiltinImplementsInterfaceCall(FctCallNode *node) const { | |
| 396 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE); |
| 397 | |||
| 398 |
1/2✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 28 not taken.
|
1 | const QualType interfaceType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 399 |
1/2✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 28 not taken.
|
1 | const QualType structType = node->templateTypeLst->dataTypes.back()->getEvaluatedSymbolType(manIdx); |
| 400 |
6/12✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 28 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 17 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 28 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 17 not taken.
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 28 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 17 not taken.
|
1 | const bool value = interfaceType.is(TY_INTERFACE) && structType.is(TY_STRUCT) && structType.doesImplement(interfaceType, node); |
| 401 |
1/2✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 25 not taken.
|
1 | node->setCompileTimeValue({.boolValue = value}, manIdx); |
| 402 | |||
| 403 |
3/6✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 26 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 26 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 26 not taken.
|
2 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 404 | } | ||
| 405 | |||
| 406 | 47 | std::any TypeChecker::visitBuiltinGetBuildVarCall(FctCallNode *node) const { | |
| 407 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 47 times.
|
47 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_GET_BUILD_VAR); |
| 408 | |||
| 409 | 47 | const DataTypeNode *requestedTypeNode = node->templateTypeLst->dataTypes.front(); | |
| 410 |
1/2✓ Branch 7 → 8 taken 47 times.
✗ Branch 7 → 210 not taken.
|
47 | const QualType requestedType = requestedTypeNode->getEvaluatedSymbolType(manIdx); |
| 411 |
3/4✓ Branch 8 → 9 taken 47 times.
✗ Branch 8 → 120 not taken.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 20 taken 46 times.
|
47 | if (!requestedType.isOneOf({TY_STRING, TY_INT, TY_BOOL})) |
| 412 |
4/8✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 123 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 121 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 127 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 127 not taken.
|
4 | SOFT_ERROR_ER(requestedTypeNode, BUILTIN_SIGNATURE_MISMATCH, "Build var type must be string, int or bool") |
| 413 | |||
| 414 |
1/2✓ Branch 20 → 21 taken 46 times.
✗ Branch 20 → 210 not taken.
|
46 | const ExprNode *varNameNode = node->argLst->args.at(0); |
| 415 |
1/2✓ Branch 21 → 22 taken 46 times.
✗ Branch 21 → 210 not taken.
|
46 | const QualType varNameType = varNameNode->getEvaluatedSymbolType(manIdx); |
| 416 |
3/4✓ Branch 22 → 23 taken 46 times.
✗ Branch 22 → 210 not taken.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 34 taken 45 times.
|
46 | if (!varNameType.is(TY_STRING)) |
| 417 |
4/8✓ Branch 26 → 27 taken 1 time.
✗ Branch 26 → 130 not taken.
✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 128 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 134 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 134 not taken.
|
4 | SOFT_ERROR_ER(varNameNode, BUILTIN_ARG_TYPE_MISMATCH, "Build var name must be a string") |
| 418 |
3/4✓ Branch 34 → 35 taken 45 times.
✗ Branch 34 → 210 not taken.
✓ Branch 35 → 36 taken 1 time.
✓ Branch 35 → 46 taken 44 times.
|
45 | if (!varNameNode->hasCompileTimeValue(manIdx)) |
| 419 |
4/8✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 137 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 135 not taken.
✓ Branch 42 → 43 taken 1 time.
✗ Branch 42 → 141 not taken.
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 141 not taken.
|
4 | SOFT_ERROR_ER(varNameNode, EXPECTED_COMPILE_TIME_VALUE, "Var name must be known at compile time") |
| 420 | |||
| 421 | 44 | const bool hasDefaultValue = node->argLst->args.size() == 2; | |
| 422 | 44 | CompileTimeValue defaultValue; | |
| 423 |
2/2✓ Branch 47 → 48 taken 35 times.
✓ Branch 47 → 77 taken 9 times.
|
44 | if (hasDefaultValue) { |
| 424 |
1/2✓ Branch 48 → 49 taken 35 times.
✗ Branch 48 → 156 not taken.
|
35 | const ExprNode *defaultValueNode = node->argLst->args.at(1); |
| 425 |
1/2✓ Branch 49 → 50 taken 35 times.
✗ Branch 49 → 156 not taken.
|
35 | const QualType defaultValueType = defaultValueNode->getEvaluatedSymbolType(manIdx); |
| 426 |
3/4✓ Branch 50 → 51 taken 35 times.
✗ Branch 50 → 156 not taken.
✓ Branch 51 → 52 taken 1 time.
✓ Branch 51 → 62 taken 34 times.
|
35 | if (!defaultValueType.matches(requestedType, false, true, true)) |
| 427 |
4/8✓ Branch 54 → 55 taken 1 time.
✗ Branch 54 → 144 not taken.
✓ Branch 55 → 56 taken 1 time.
✗ Branch 55 → 142 not taken.
✓ Branch 58 → 59 taken 1 time.
✗ Branch 58 → 148 not taken.
✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 148 not taken.
|
4 | SOFT_ERROR_ER(defaultValueNode, BUILTIN_ARG_TYPE_MISMATCH, "Default value type must be the same as the requested type") |
| 428 |
3/4✓ Branch 62 → 63 taken 34 times.
✗ Branch 62 → 156 not taken.
✓ Branch 63 → 64 taken 1 time.
✓ Branch 63 → 74 taken 33 times.
|
34 | if (!defaultValueNode->hasCompileTimeValue(manIdx)) |
| 429 |
4/8✓ Branch 66 → 67 taken 1 time.
✗ Branch 66 → 151 not taken.
✓ Branch 67 → 68 taken 1 time.
✗ Branch 67 → 149 not taken.
✓ Branch 70 → 71 taken 1 time.
✗ Branch 70 → 155 not taken.
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 155 not taken.
|
4 | SOFT_ERROR_ER(defaultValueNode, EXPECTED_COMPILE_TIME_VALUE, "Default value must be known at compile time") |
| 430 |
1/2✓ Branch 74 → 75 taken 33 times.
✗ Branch 74 → 156 not taken.
|
33 | defaultValue = defaultValueNode->getCompileTimeValue(manIdx); |
| 431 | } | ||
| 432 | |||
| 433 |
1/2✓ Branch 77 → 78 taken 42 times.
✗ Branch 77 → 210 not taken.
|
42 | const size_t stringValueOffset = varNameNode->getCompileTimeValue(manIdx).stringValueOffset; |
| 434 |
1/2✓ Branch 78 → 79 taken 42 times.
✗ Branch 78 → 210 not taken.
|
42 | const std::string &varName = resourceManager.compileTimeStringValues.at(stringValueOffset); |
| 435 |
1/2✓ Branch 79 → 80 taken 42 times.
✗ Branch 79 → 210 not taken.
|
42 | const auto it = cliOptions.buildVars.find(varName); |
| 436 |
2/2✓ Branch 82 → 83 taken 15 times.
✓ Branch 82 → 102 taken 27 times.
|
42 | if (it != cliOptions.buildVars.end()) { |
| 437 | try { | ||
| 438 |
3/4✓ Branch 83 → 84 taken 15 times.
✗ Branch 83 → 160 not taken.
✓ Branch 84 → 85 taken 8 times.
✓ Branch 84 → 90 taken 7 times.
|
15 | if (requestedType.is(TY_STRING)) { |
| 439 | 8 | const size_t value = resourceManager.compileTimeStringValues.size(); | |
| 440 |
1/2✓ Branch 87 → 88 taken 8 times.
✗ Branch 87 → 160 not taken.
|
8 | resourceManager.compileTimeStringValues.push_back(it->second); |
| 441 |
1/2✓ Branch 88 → 89 taken 8 times.
✗ Branch 88 → 157 not taken.
|
8 | node->setCompileTimeValue({.stringValueOffset = value}, manIdx); |
| 442 |
3/4✓ Branch 90 → 91 taken 7 times.
✗ Branch 90 → 160 not taken.
✓ Branch 91 → 92 taken 3 times.
✓ Branch 91 → 96 taken 4 times.
|
7 | } else if (requestedType.is(TY_INT)) { |
| 443 |
2/2✓ Branch 93 → 94 taken 1 time.
✓ Branch 93 → 160 taken 2 times.
|
3 | const int value = std::stoi(it->second); |
| 444 |
1/2✓ Branch 94 → 95 taken 1 time.
✗ Branch 94 → 158 not taken.
|
1 | node->setCompileTimeValue({.intValue = value}, manIdx); |
| 445 |
2/4✓ Branch 96 → 97 taken 4 times.
✗ Branch 96 → 160 not taken.
✓ Branch 97 → 98 taken 4 times.
✗ Branch 97 → 114 not taken.
|
4 | } else if (requestedType.is(TY_BOOL)) { |
| 446 |
1/2✓ Branch 99 → 100 taken 4 times.
✗ Branch 99 → 160 not taken.
|
4 | const bool value = it->second == "true"; |
| 447 |
1/2✓ Branch 100 → 101 taken 4 times.
✗ Branch 100 → 159 not taken.
|
4 | node->setCompileTimeValue({.boolValue = value}, manIdx); |
| 448 | } | ||
| 449 |
1/3✗ Branch 160 → 161 not taken.
✓ Branch 160 → 162 taken 2 times.
✗ Branch 160 → 173 not taken.
|
2 | } catch (const std::invalid_argument &) { |
| 450 |
4/8✓ Branch 165 → 166 taken 2 times.
✗ Branch 165 → 186 not taken.
✓ Branch 166 → 167 taken 2 times.
✗ Branch 166 → 184 not taken.
✓ Branch 169 → 170 taken 2 times.
✗ Branch 169 → 190 not taken.
✓ Branch 170 → 171 taken 2 times.
✗ Branch 170 → 190 not taken.
|
6 | SOFT_ERROR_ER(node, BUILTIN_ARG_TYPE_MISMATCH, "Error while parsing the provided value to the requested type") |
| 451 | 2 | } catch (const std::out_of_range &) { | |
| 452 | ✗ | SOFT_ERROR_ER(node, BUILTIN_ARG_TYPE_MISMATCH, "Error while parsing the provided value to the requested type") | |
| 453 | ✗ | } | |
| 454 | } else { | ||
| 455 |
2/2✓ Branch 102 → 103 taken 1 time.
✓ Branch 102 → 113 taken 26 times.
|
27 | if (!hasDefaultValue) |
| 456 |
4/8✓ Branch 105 → 106 taken 1 time.
✗ Branch 105 → 204 not taken.
✓ Branch 106 → 107 taken 1 time.
✗ Branch 106 → 202 not taken.
✓ Branch 109 → 110 taken 1 time.
✗ Branch 109 → 208 not taken.
✓ Branch 110 → 111 taken 1 time.
✗ Branch 110 → 208 not taken.
|
4 | SOFT_ERROR_ER(varNameNode, BUILTIN_ARG_TYPE_MISMATCH, "Build var with this name was not provided"); |
| 457 |
1/2✓ Branch 113 → 114 taken 26 times.
✗ Branch 113 → 210 not taken.
|
26 | node->setCompileTimeValue(defaultValue, manIdx); |
| 458 | } | ||
| 459 | |||
| 460 |
2/4✓ Branch 114 → 115 taken 39 times.
✗ Branch 114 → 209 not taken.
✓ Branch 115 → 116 taken 39 times.
✗ Branch 115 → 209 not taken.
|
78 | return ExprResult{node->setEvaluatedSymbolType(requestedType, manIdx)}; |
| 461 | } | ||
| 462 | |||
| 463 | 4 | std::any TypeChecker::visitBuiltinIsTriviallyConstructible(FctCallNode *node) const { | |
| 464 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 4 times.
|
4 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IS_TRIVIALLY_CONSTRUCTIBLE); |
| 465 | |||
| 466 |
1/2✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 19 not taken.
|
4 | const QualType type = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 467 |
1/2✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 19 not taken.
|
4 | const bool value = type.isTriviallyConstructible(node); |
| 468 |
1/2✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 16 not taken.
|
4 | node->setCompileTimeValue({.boolValue = value}, manIdx); |
| 469 | |||
| 470 |
3/6✓ Branch 10 → 11 taken 4 times.
✗ Branch 10 → 17 not taken.
✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 17 not taken.
✓ Branch 12 → 13 taken 4 times.
✗ Branch 12 → 17 not taken.
|
8 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 471 | } | ||
| 472 | |||
| 473 | 11 | std::any TypeChecker::visitBuiltinIsTriviallyCopyable(FctCallNode *node) const { | |
| 474 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 11 times.
|
11 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IS_TRIVIALLY_COPYABLE); |
| 475 | |||
| 476 |
1/2✓ Branch 7 → 8 taken 11 times.
✗ Branch 7 → 19 not taken.
|
11 | const QualType type = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 477 |
1/2✓ Branch 8 → 9 taken 11 times.
✗ Branch 8 → 19 not taken.
|
11 | const bool value = type.isTriviallyCopyable(node); |
| 478 |
1/2✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 16 not taken.
|
11 | node->setCompileTimeValue({.boolValue = value}, manIdx); |
| 479 | |||
| 480 |
3/6✓ Branch 10 → 11 taken 11 times.
✗ Branch 10 → 17 not taken.
✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 17 not taken.
✓ Branch 12 → 13 taken 11 times.
✗ Branch 12 → 17 not taken.
|
22 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 481 | } | ||
| 482 | |||
| 483 | 63 | std::any TypeChecker::visitBuiltinIsTriviallyDestructible(FctCallNode *node) const { | |
| 484 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 63 times.
|
63 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_IS_TRIVIALLY_DESTRUCTIBLE); |
| 485 | |||
| 486 |
1/2✓ Branch 7 → 8 taken 63 times.
✗ Branch 7 → 19 not taken.
|
63 | const QualType type = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 487 |
1/2✓ Branch 8 → 9 taken 63 times.
✗ Branch 8 → 19 not taken.
|
63 | const bool value = type.isTriviallyDestructible(node); |
| 488 |
1/2✓ Branch 9 → 10 taken 63 times.
✗ Branch 9 → 16 not taken.
|
63 | node->setCompileTimeValue({.boolValue = value}, manIdx); |
| 489 | |||
| 490 |
3/6✓ Branch 10 → 11 taken 63 times.
✗ Branch 10 → 17 not taken.
✓ Branch 11 → 12 taken 63 times.
✗ Branch 11 → 17 not taken.
✓ Branch 12 → 13 taken 63 times.
✗ Branch 12 → 17 not taken.
|
126 | return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)}; |
| 491 | } | ||
| 492 | |||
| 493 | 52 | std::any TypeChecker::visitBuiltinNewCall(FctCallNode *node) const { | |
| 494 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 52 times.
|
52 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_NEW); |
| 495 | |||
| 496 |
1/2✓ Branch 6 → 7 taken 52 times.
✗ Branch 6 → 160 not taken.
|
52 | FctCallNode::FctCallData &data = node->data.at(manIdx); |
| 497 |
1/2✓ Branch 8 → 9 taken 52 times.
✗ Branch 8 → 160 not taken.
|
52 | const QualType templateType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 498 | |||
| 499 |
3/4✓ Branch 9 → 10 taken 52 times.
✗ Branch 9 → 160 not taken.
✓ Branch 10 → 11 taken 46 times.
✓ Branch 10 → 57 taken 6 times.
|
52 | if (templateType.is(TY_STRUCT)) { |
| 500 |
1/2✓ Branch 11 → 12 taken 46 times.
✗ Branch 11 → 160 not taken.
|
46 | Scope *bodyScope = templateType.getBodyScope(); |
| 501 |
2/4✓ Branch 15 → 16 taken 46 times.
✗ Branch 15 → 104 not taken.
✓ Branch 16 → 17 taken 46 times.
✗ Branch 16 → 102 not taken.
|
138 | Function *ctor = FunctionManager::match(bodyScope, CTOR_FUNCTION_NAME, templateType, data.args, {}, false, node); |
| 502 |
2/2✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 56 taken 45 times.
|
46 | if (ctor == nullptr) { |
| 503 |
1/2✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 160 not taken.
|
1 | const bool copyCtorCall = isCopyCtorCall(node, templateType); |
| 504 |
4/8✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 26 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 160 not taken.
✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 26 not taken.
✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 39 not taken.
|
1 | if (!copyCtorCall && !templateType.isTriviallyConstructible(node)) |
| 505 |
6/12✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 117 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 115 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 113 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 111 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 120 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 120 not taken.
|
2 | SOFT_ERROR_ER(node, NO_MATCHING_CTOR_FOUND, |
| 506 | "No matching constructor found for type '" + templateType.getName(false) + "'") | ||
| 507 | ✗ | if (copyCtorCall && !templateType.isTriviallyCopyable(node)) | |
| 508 | ✗ | SOFT_ERROR_ER(node, NO_MATCHING_CTOR_FOUND, | |
| 509 | "No matching copy constructor found for type '" + templateType.getName(false) + "'") | ||
| 510 | } | ||
| 511 | 45 | data.callee = ctor; | |
| 512 |
2/2✓ Branch 58 → 59 taken 1 time.
✓ Branch 58 → 69 taken 5 times.
|
6 | } else if (data.args.size() > 1) { |
| 513 |
2/4✓ Branch 60 → 61 taken 1 time.
✗ Branch 60 → 133 not taken.
✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 131 not taken.
|
1 | const auto msg = "Expected no or 1 argument for __new on primitive type, got " + std::to_string(data.args.size()); |
| 514 |
3/6✓ Branch 63 → 64 taken 1 time.
✗ Branch 63 → 135 not taken.
✓ Branch 64 → 65 taken 1 time.
✗ Branch 64 → 134 not taken.
✓ Branch 65 → 66 taken 1 time.
✗ Branch 65 → 134 not taken.
|
1 | SOFT_ERROR_ER(node, BUILTIN_ARG_TYPE_MISMATCH, msg) |
| 515 |
2/2✓ Branch 70 → 71 taken 3 times.
✓ Branch 70 → 94 taken 2 times.
|
6 | } else if (data.args.size() == 1) { |
| 516 |
2/4✓ Branch 72 → 73 taken 3 times.
✗ Branch 72 → 138 not taken.
✓ Branch 73 → 74 taken 3 times.
✗ Branch 73 → 138 not taken.
|
3 | const QualType argType = data.args.front().first.removeReferenceWrapper().toNonConst(); |
| 517 |
2/4✓ Branch 74 → 75 taken 3 times.
✗ Branch 74 → 158 not taken.
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 93 taken 3 times.
|
3 | if (!templateType.matches(argType, false, false, true)) { |
| 518 | ✗ | const auto msg = "Argument type '" + argType.getName() + "' does not match template type '" + templateType.getName() + "'"; | |
| 519 | ✗ | SOFT_ERROR_ER(node, BUILTIN_ARG_TYPE_MISMATCH, msg) | |
| 520 | ✗ | } | |
| 521 | } | ||
| 522 | |||
| 523 |
1/2✓ Branch 94 → 95 taken 50 times.
✗ Branch 94 → 160 not taken.
|
50 | QualType returnType = templateType.toPtr(node); |
| 524 |
1/2✓ Branch 95 → 96 taken 50 times.
✗ Branch 95 → 160 not taken.
|
50 | returnType.makeHeap(); |
| 525 |
2/4✓ Branch 96 → 97 taken 50 times.
✗ Branch 96 → 159 not taken.
✓ Branch 97 → 98 taken 50 times.
✗ Branch 97 → 159 not taken.
|
100 | return ExprResult{node->setEvaluatedSymbolType(returnType, manIdx)}; |
| 526 | } | ||
| 527 | |||
| 528 | 386 | std::any TypeChecker::visitBuiltinPlacementNewCall(FctCallNode *node) const { | |
| 529 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 386 times.
|
386 | assert(node->fqFunctionName == BUILTIN_FCT_NAME_PLACEMENT_NEW); |
| 530 | |||
| 531 |
1/2✓ Branch 6 → 7 taken 386 times.
✗ Branch 6 → 212 not taken.
|
386 | FctCallNode::FctCallData &data = node->data.at(manIdx); |
| 532 |
1/2✓ Branch 8 → 9 taken 386 times.
✗ Branch 8 → 212 not taken.
|
386 | const QualType templateType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx); |
| 533 | |||
| 534 | // Validate first arg is a byte pointer or a heap pointer to the template type | ||
| 535 |
1/2✓ Branch 10 → 11 taken 386 times.
✗ Branch 10 → 212 not taken.
|
386 | const QualType ptrArgType = data.args.front().first.removeReferenceWrapper(); |
| 536 |
1/2✓ Branch 11 → 12 taken 386 times.
✗ Branch 11 → 212 not taken.
|
386 | const bool isBytePtr = ptrArgType.isPtrTo(TY_BYTE); |
| 537 |
6/10✓ Branch 12 → 13 taken 386 times.
✗ Branch 12 → 138 not taken.
✓ Branch 13 → 14 taken 386 times.
✗ Branch 13 → 18 not taken.
✓ Branch 14 → 15 taken 386 times.
✗ Branch 14 → 138 not taken.
✓ Branch 15 → 16 taken 386 times.
✗ Branch 15 → 138 not taken.
✓ Branch 16 → 17 taken 385 times.
✓ Branch 16 → 18 taken 1 time.
|
386 | const bool isStructPtr = ptrArgType.isPtr() && ptrArgType.getContained() == templateType; |
| 538 |
3/4✓ Branch 19 → 20 taken 386 times.
✗ Branch 19 → 32 not taken.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 32 taken 385 times.
|
386 | if (!isBytePtr && !isStructPtr) |
| 539 |
4/8✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 141 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 139 not taken.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 145 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 145 not taken.
|
4 | SOFT_ERROR_ER(node->argLst->args.front(), BUILTIN_ARG_TYPE_MISMATCH, |
| 540 | "__placement_new expects a 'byte*' or 'T*' as its first argument") | ||
| 541 | |||
| 542 |
3/4✓ Branch 32 → 33 taken 385 times.
✗ Branch 32 → 212 not taken.
✓ Branch 33 → 34 taken 294 times.
✓ Branch 33 → 94 taken 91 times.
|
385 | if (templateType.is(TY_STRUCT)) { |
| 543 |
1/2✓ Branch 34 → 35 taken 294 times.
✗ Branch 34 → 181 not taken.
|
294 | Scope *bodyScope = templateType.getBodyScope(); |
| 544 |
1/2✓ Branch 42 → 43 taken 294 times.
✗ Branch 42 → 146 not taken.
|
882 | const ArgList ctorArgs(data.args.begin() + 1, data.args.end()); |
| 545 |
2/4✓ Branch 47 → 48 taken 294 times.
✗ Branch 47 → 152 not taken.
✓ Branch 48 → 49 taken 294 times.
✗ Branch 48 → 150 not taken.
|
882 | Function *ctor = FunctionManager::match(bodyScope, CTOR_FUNCTION_NAME, templateType, ctorArgs, {}, false, node); |
| 546 |
2/2✓ Branch 52 → 53 taken 13 times.
✓ Branch 52 → 88 taken 281 times.
|
294 | if (ctor == nullptr) { |
| 547 |
1/2✓ Branch 53 → 54 taken 13 times.
✗ Branch 53 → 179 not taken.
|
13 | const bool copyCtorCall = isCopyCtorCall(node, templateType); |
| 548 |
6/8✓ Branch 54 → 55 taken 1 time.
✓ Branch 54 → 58 taken 12 times.
✓ Branch 55 → 56 taken 1 time.
✗ Branch 55 → 179 not taken.
✓ Branch 56 → 57 taken 1 time.
✗ Branch 56 → 58 not taken.
✓ Branch 59 → 60 taken 1 time.
✓ Branch 59 → 71 taken 12 times.
|
13 | if (!copyCtorCall && !templateType.isTriviallyConstructible(node)) |
| 549 |
6/12✓ Branch 60 → 61 taken 1 time.
✗ Branch 60 → 165 not taken.
✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 163 not taken.
✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 161 not taken.
✓ Branch 63 → 64 taken 1 time.
✗ Branch 63 → 159 not taken.
✓ Branch 67 → 68 taken 1 time.
✗ Branch 67 → 168 not taken.
✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 168 not taken.
|
2 | SOFT_ERROR_ER(node, NO_MATCHING_CTOR_FOUND, |
| 550 | "No matching constructor found for type '" + templateType.getName(false) + "'") | ||
| 551 |
4/8✓ Branch 71 → 72 taken 12 times.
✗ Branch 71 → 75 not taken.
✓ Branch 72 → 73 taken 12 times.
✗ Branch 72 → 179 not taken.
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 75 taken 12 times.
✗ Branch 76 → 77 not taken.
✓ Branch 76 → 88 taken 12 times.
|
12 | if (copyCtorCall && !templateType.isTriviallyCopyable(node)) |
| 552 | ✗ | SOFT_ERROR_ER(node, NO_MATCHING_CTOR_FOUND, | |
| 553 | "No matching copy constructor found for type '" + templateType.getName(false) + "'") | ||
| 554 | } | ||
| 555 | 293 | data.callee = ctor; | |
| 556 |
4/4✓ Branch 90 → 91 taken 293 times.
✓ Branch 90 → 93 taken 1 time.
✓ Branch 95 → 96 taken 1 time.
✓ Branch 95 → 106 taken 90 times.
|
385 | } else if (data.args.size() > 2) { |
| 557 |
2/4✓ Branch 97 → 98 taken 1 time.
✗ Branch 97 → 184 not taken.
✓ Branch 98 → 99 taken 1 time.
✗ Branch 98 → 182 not taken.
|
1 | const auto msg = "Expected 1 or 2 arguments for __placement_new, got " + std::to_string(data.args.size()); |
| 558 |
3/6✓ Branch 100 → 101 taken 1 time.
✗ Branch 100 → 186 not taken.
✓ Branch 101 → 102 taken 1 time.
✗ Branch 101 → 185 not taken.
✓ Branch 102 → 103 taken 1 time.
✗ Branch 102 → 185 not taken.
|
1 | SOFT_ERROR_ER(node, BUILTIN_ARG_TYPE_MISMATCH, msg) |
| 559 |
1/2✓ Branch 107 → 108 taken 90 times.
✗ Branch 107 → 131 not taken.
|
91 | } else if (data.args.size() == 2) { |
| 560 |
2/4✓ Branch 109 → 110 taken 90 times.
✗ Branch 109 → 189 not taken.
✓ Branch 110 → 111 taken 90 times.
✗ Branch 110 → 189 not taken.
|
90 | const QualType argType = data.args.back().first.removeReferenceWrapper().toNonConst(); |
| 561 |
2/4✓ Branch 111 → 112 taken 90 times.
✗ Branch 111 → 209 not taken.
✗ Branch 112 → 113 not taken.
✓ Branch 112 → 130 taken 90 times.
|
90 | if (!templateType.matches(argType, false, false, true)) { |
| 562 | ✗ | const auto msg = "Argument type '" + argType.getName() + "' does not match template type '" + templateType.getName() + "'"; | |
| 563 | ✗ | SOFT_ERROR_ER(node, BUILTIN_ARG_TYPE_MISMATCH, msg) | |
| 564 | ✗ | } | |
| 565 | } | ||
| 566 | |||
| 567 |
3/6✓ Branch 131 → 132 taken 383 times.
✗ Branch 131 → 210 not taken.
✓ Branch 132 → 133 taken 383 times.
✗ Branch 132 → 210 not taken.
✓ Branch 133 → 134 taken 383 times.
✗ Branch 133 → 210 not taken.
|
766 | return ExprResult{node->setEvaluatedSymbolType(templateType.toPtr(node), manIdx)}; |
| 568 | } | ||
| 569 | |||
| 570 | } // namespace spice::compiler | ||
| 571 |