GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 93.5% 333 / 0 / 356
Functions: 100.0% 21 / 0 / 21
Branches: 51.6% 611 / 0 / 1185

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