GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 95.6% 151 / 0 / 158
Functions: 100.0% 11 / 0 / 11
Branches: 53.2% 281 / 0 / 528

src/typechecker/TypeCheckBuiltinFunctions.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 <global/GlobalResourceManager.h>
8 #include <global/TypeRegistry.h>
9 #include <typechecker/Builtins.h>
10 #include <typechecker/MacroDefs.h>
11
12 namespace spice::compiler {
13
14 1858 std::any TypeChecker::visitBuiltinCall(FctCallNode *node) const {
15
2/4
✓ Branch 3 → 4 taken 1858 times.
✗ Branch 3 → 68 not taken.
✓ Branch 4 → 5 taken 1858 times.
✗ Branch 4 → 6 not taken.
1858 assert(BUILTIN_FUNCTIONS_MAP.contains(node->fqFunctionName) && "Builtin function not implemented!");
16
1/2
✓ Branch 8 → 9 taken 1858 times.
✗ Branch 8 → 69 not taken.
1858 const auto &info = BUILTIN_FUNCTIONS_MAP.find(node->fqFunctionName)->second;
17
18 14 const auto buildErrorMessage = [](unsigned int min, unsigned int max, unsigned int actual, const char *suffix) {
19 14 std::string expectedStr;
20
2/2
✓ Branch 3 → 4 taken 7 times.
✓ Branch 3 → 15 taken 7 times.
14 if (min == max)
21
5/8
✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 8 taken 4 times.
✓ Branch 7 → 9 taken 3 times.
✗ Branch 7 → 46 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 14 taken 4 times.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 49 not taken.
13 expectedStr = min == 0 ? "no" : std::to_string(min);
22 else
23
5/10
✓ Branch 17 → 18 taken 7 times.
✗ Branch 17 → 60 not taken.
✓ Branch 18 → 19 taken 7 times.
✗ Branch 18 → 58 not taken.
✓ Branch 19 → 20 taken 7 times.
✗ Branch 19 → 56 not taken.
✓ Branch 20 → 21 taken 7 times.
✗ Branch 20 → 54 not taken.
✓ Branch 21 → 22 taken 7 times.
✗ Branch 21 → 52 not taken.
7 expectedStr = "between " + std::to_string(min) + " and " + std::to_string(max) + " " + suffix;
24
5/10
✓ Branch 32 → 33 taken 14 times.
✗ Branch 32 → 79 not taken.
✓ Branch 33 → 34 taken 14 times.
✗ Branch 33 → 77 not taken.
✓ Branch 34 → 35 taken 14 times.
✗ Branch 34 → 75 not taken.
✓ Branch 35 → 36 taken 14 times.
✗ Branch 35 → 73 not taken.
✓ Branch 36 → 37 taken 14 times.
✗ Branch 36 → 71 not taken.
28 return "This builtin expects " + expectedStr + " " + suffix + ", but got " + std::to_string(actual);
25 14 };
26
27 // Do basic checks of template types and args, based on the builtin function info
28
2/2
✓ Branch 10 → 11 taken 157 times.
✓ Branch 10 → 12 taken 1701 times.
1858 const size_t numTemplateTypes = node->hasTemplateTypes ? node->templateTypeLst->dataTypes.size() : 0;
29
4/4
✓ Branch 13 → 14 taken 1856 times.
✓ Branch 13 → 15 taken 2 times.
✓ Branch 14 → 15 taken 5 times.
✓ Branch 14 → 22 taken 1851 times.
1858 if (numTemplateTypes < info.minTemplateTypes || numTemplateTypes > info.maxTemplateTypes) {
30
1/2
✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 74 not taken.
7 const auto msg = buildErrorMessage(info.minTemplateTypes, info.maxTemplateTypes, numTemplateTypes, "template type(s)");
31
3/6
✓ Branch 16 → 17 taken 7 times.
✗ Branch 16 → 72 not taken.
✓ Branch 17 → 18 taken 7 times.
✗ Branch 17 → 71 not taken.
✓ Branch 18 → 19 taken 7 times.
✗ Branch 18 → 71 not taken.
7 SOFT_ERROR_ER(node, BUILTIN_TEMPLATE_TYPE_COUNT_MISMATCH, msg);
32 7 }
33
34
2/2
✓ Branch 22 → 23 taken 1702 times.
✓ Branch 22 → 24 taken 149 times.
1851 const size_t numArgs = node->hasArgs ? node->argLst->args.size() : 0;
35
4/4
✓ Branch 25 → 26 taken 1850 times.
✓ Branch 25 → 27 taken 1 time.
✓ Branch 26 → 27 taken 6 times.
✓ Branch 26 → 34 taken 1844 times.
1851 if (numArgs < info.minArgTypes || numArgs > info.maxArgTypes) {
36
1/2
✓ Branch 27 → 28 taken 7 times.
✗ Branch 27 → 78 not taken.
7 const auto msg = buildErrorMessage(info.minArgTypes, info.maxArgTypes, numArgs, "argument(s)");
37
3/6
✓ Branch 28 → 29 taken 7 times.
✗ Branch 28 → 76 not taken.
✓ Branch 29 → 30 taken 7 times.
✗ Branch 29 → 75 not taken.
✓ Branch 30 → 31 taken 7 times.
✗ Branch 30 → 75 not taken.
7 SOFT_ERROR_ER(node, BUILTIN_ARG_COUNT_MISMATCH, msg);
38 7 }
39
40
2/2
✓ Branch 34 → 35 taken 180 times.
✓ Branch 34 → 59 taken 1664 times.
1844 if (info.allTemplateTypesOrAllArgTypes) {
41
4/4
✓ Branch 35 → 36 taken 141 times.
✓ Branch 35 → 47 taken 39 times.
✓ Branch 36 → 37 taken 3 times.
✓ Branch 36 → 47 taken 138 times.
180 if (numTemplateTypes > 0 && numArgs > 0)
42
4/8
✓ Branch 39 → 40 taken 3 times.
✗ Branch 39 → 81 not taken.
✓ Branch 40 → 41 taken 3 times.
✗ Branch 40 → 79 not taken.
✓ Branch 43 → 44 taken 3 times.
✗ Branch 43 → 85 not taken.
✓ Branch 44 → 45 taken 3 times.
✗ Branch 44 → 85 not taken.
9 SOFT_ERROR_ER(node, BUILTIN_SIGNATURE_MISMATCH, "This builtin expects either template types or arguments, but got both");
43
4/4
✓ Branch 47 → 48 taken 39 times.
✓ Branch 47 → 59 taken 138 times.
✓ Branch 48 → 49 taken 3 times.
✓ Branch 48 → 59 taken 36 times.
177 if (numTemplateTypes == 0 && numArgs == 0)
44
4/8
✓ Branch 51 → 52 taken 3 times.
✗ Branch 51 → 88 not taken.
✓ Branch 52 → 53 taken 3 times.
✗ Branch 52 → 86 not taken.
✓ Branch 55 → 56 taken 3 times.
✗ Branch 55 → 92 not taken.
✓ Branch 56 → 57 taken 3 times.
✗ Branch 56 → 92 not taken.
9 SOFT_ERROR_ER(node, BUILTIN_SIGNATURE_MISMATCH, "This builtin expects either template types or arguments, but got none");
45 }
46
47 // If specified, call to TypeChecker delegate to execute further checks
48
3/8
✓ Branch 59 → 60 taken 1838 times.
✗ Branch 59 → 64 not taken.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 1838 times.
✓ Branch 63 → 65 taken 1838 times.
✗ Branch 63 → 93 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 93 not taken.
1838 return info.typeCheckerVisitMethod != nullptr ? (this->*info.typeCheckerVisitMethod)(node) : nullptr;
49 }
50
51 852 std::any TypeChecker::visitBuiltinPrintfCall(FctCallNode *node) const {
52
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 852 times.
852 assert(node->fqFunctionName == BUILTIN_FCT_NAME_PRINTF);
53
54 // Retrieve templated string
55
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 852 times.
852 assert(node->hasArgs);
56 852 const AssignExprNode *firstArg = node->argLst->args.front();
57
5/10
✓ Branch 9 → 10 taken 852 times.
✗ Branch 9 → 223 not taken.
✓ Branch 10 → 11 taken 852 times.
✗ Branch 10 → 223 not taken.
✓ Branch 11 → 12 taken 852 times.
✗ Branch 11 → 15 not taken.
✓ Branch 12 → 13 taken 852 times.
✗ Branch 12 → 223 not taken.
✓ Branch 13 → 14 taken 852 times.
✗ Branch 13 → 15 not taken.
852 assert(firstArg->getEvaluatedSymbolType(manIdx).is(TY_STRING) && firstArg->hasCompileTimeValue(manIdx));
58
1/2
✓ Branch 16 → 17 taken 852 times.
✗ Branch 16 → 223 not taken.
852 const size_t stringOffset = firstArg->getCompileTimeValue(manIdx).stringValueOffset;
59
2/4
✓ Branch 17 → 18 taken 852 times.
✗ Branch 17 → 223 not taken.
✓ Branch 18 → 19 taken 852 times.
✗ Branch 18 → 223 not taken.
852 const std::string templatedString = resourceManager.compileTimeStringValues.at(stringOffset);
60
61 // Check if assignment types match placeholder types
62 852 size_t placeholderCount = 0;
63 852 size_t index = templatedString.find_first_of('%');
64
5/6
✓ Branch 133 → 134 taken 699 times.
✓ Branch 133 → 137 taken 845 times.
✓ Branch 135 → 136 taken 699 times.
✗ Branch 135 → 137 not taken.
✓ Branch 138 → 20 taken 699 times.
✓ Branch 138 → 139 taken 845 times.
1544 while (index != std::string::npos && index != templatedString.size() - 1) {
65 // Check if there is another assignExpr
66
2/2
✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 32 taken 698 times.
699 if (node->argLst->args.size() - 1 <= placeholderCount)
67
4/8
✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 161 not taken.
✓ Branch 25 → 26 taken 1 time.
✗ Branch 25 → 159 not taken.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 165 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 165 not taken.
3 SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains more placeholders than arguments")
68
69 // Get next assignment
70
1/2
✓ Branch 32 → 33 taken 698 times.
✗ Branch 32 → 211 not taken.
698 const AssignExprNode *assignment = node->argLst->args.at(placeholderCount + 1);
71 // Visit assignment
72
1/2
✓ Branch 33 → 34 taken 698 times.
✗ Branch 33 → 211 not taken.
698 QualType argType = assignment->getEvaluatedSymbolType(manIdx);
73
2/8
✓ Branch 34 → 35 taken 698 times.
✗ Branch 34 → 211 not taken.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 40 taken 698 times.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 166 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 166 not taken.
698 HANDLE_UNRESOLVED_TYPE_ER(argType)
74
1/2
✓ Branch 40 → 41 taken 698 times.
✗ Branch 40 → 167 not taken.
698 argType = argType.removeReferenceWrapper();
75
76
6/8
✓ Branch 41 → 42 taken 698 times.
✗ Branch 41 → 211 not taken.
✓ Branch 42 → 43 taken 29 times.
✓ Branch 42 → 55 taken 351 times.
✓ Branch 42 → 67 taken 54 times.
✓ Branch 42 → 79 taken 258 times.
✓ Branch 42 → 100 taken 6 times.
✗ Branch 42 → 119 not taken.
698 switch (templatedString.at(index + 1)) {
77 29 case 'c': {
78
3/4
✓ Branch 43 → 44 taken 29 times.
✗ Branch 43 → 211 not taken.
✓ Branch 44 → 45 taken 1 time.
✓ Branch 44 → 54 taken 28 times.
29 if (!argType.is(TY_CHAR))
79
5/10
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 172 not taken.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 170 not taken.
✓ Branch 47 → 48 taken 1 time.
✗ Branch 47 → 168 not taken.
✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 174 not taken.
✓ Branch 51 → 52 taken 1 time.
✗ Branch 51 → 174 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects char, but got " + argType.getName(false))
80 28 placeholderCount++;
81 28 break;
82 }
83 351 case 'd':
84 case 'i':
85 case 'l':
86 case 'o':
87 case 'u':
88 case 'x':
89 case 'X': {
90
3/4
✓ Branch 55 → 56 taken 351 times.
✗ Branch 55 → 175 not taken.
✓ Branch 56 → 57 taken 2 times.
✓ Branch 56 → 66 taken 349 times.
351 if (!argType.isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_BOOL}))
91
5/10
✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 180 not taken.
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 178 not taken.
✓ Branch 59 → 60 taken 2 times.
✗ Branch 59 → 176 not taken.
✓ Branch 62 → 63 taken 2 times.
✗ Branch 62 → 182 not taken.
✓ Branch 63 → 64 taken 2 times.
✗ Branch 63 → 182 not taken.
2 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR,
92 "The placeholder string expects int, short, long, byte or bool, but got " + argType.getName(false))
93 349 placeholderCount++;
94 349 break;
95 }
96 54 case 'a':
97 case 'A':
98 case 'f':
99 case 'F':
100 case 'e':
101 case 'E':
102 case 'g':
103 case 'G': {
104
3/4
✓ Branch 67 → 68 taken 54 times.
✗ Branch 67 → 211 not taken.
✓ Branch 68 → 69 taken 1 time.
✓ Branch 68 → 78 taken 53 times.
54 if (!argType.is(TY_DOUBLE))
105
5/10
✓ Branch 69 → 70 taken 1 time.
✗ Branch 69 → 187 not taken.
✓ Branch 70 → 71 taken 1 time.
✗ Branch 70 → 185 not taken.
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 183 not taken.
✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 189 not taken.
✓ Branch 75 → 76 taken 1 time.
✗ Branch 75 → 189 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects double, but got " + argType.getName(false))
106 53 placeholderCount++;
107 53 break;
108 }
109 258 case 's': {
110
13/18
✓ Branch 79 → 80 taken 258 times.
✗ Branch 79 → 211 not taken.
✓ Branch 80 → 81 taken 63 times.
✓ Branch 80 → 88 taken 195 times.
✓ Branch 81 → 82 taken 63 times.
✗ Branch 81 → 211 not taken.
✓ Branch 82 → 83 taken 2 times.
✓ Branch 82 → 88 taken 61 times.
✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 211 not taken.
✓ Branch 84 → 85 taken 1 time.
✓ Branch 84 → 88 taken 1 time.
✓ Branch 85 → 86 taken 1 time.
✗ Branch 85 → 211 not taken.
✓ Branch 86 → 87 taken 1 time.
✗ Branch 86 → 88 not taken.
✓ Branch 89 → 90 taken 1 time.
✓ Branch 89 → 99 taken 257 times.
258 if (!argType.is(TY_STRING) && !argType.isStringObj() && !argType.isPtrTo(TY_CHAR) && !argType.isArrayOf(TY_CHAR))
111
5/10
✓ Branch 90 → 91 taken 1 time.
✗ Branch 90 → 194 not taken.
✓ Branch 91 → 92 taken 1 time.
✗ Branch 91 → 192 not taken.
✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 190 not taken.
✓ Branch 95 → 96 taken 1 time.
✗ Branch 95 → 196 not taken.
✓ Branch 96 → 97 taken 1 time.
✗ Branch 96 → 196 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR,
112 "The placeholder string expects string, String, char* or char[], but got " + argType.getName(false))
113 257 placeholderCount++;
114 257 break;
115 }
116 6 case 'p': {
117
9/14
✓ Branch 100 → 101 taken 6 times.
✗ Branch 100 → 211 not taken.
✓ Branch 101 → 102 taken 1 time.
✓ Branch 101 → 107 taken 5 times.
✓ Branch 102 → 103 taken 1 time.
✗ Branch 102 → 211 not taken.
✓ Branch 103 → 104 taken 1 time.
✗ Branch 103 → 107 not taken.
✓ Branch 104 → 105 taken 1 time.
✗ Branch 104 → 211 not taken.
✓ Branch 105 → 106 taken 1 time.
✗ Branch 105 → 107 not taken.
✓ Branch 108 → 109 taken 1 time.
✓ Branch 108 → 118 taken 5 times.
6 if (!argType.isPtr() && !argType.isArray() && !argType.is(TY_STRING))
118
5/10
✓ Branch 109 → 110 taken 1 time.
✗ Branch 109 → 201 not taken.
✓ Branch 110 → 111 taken 1 time.
✗ Branch 110 → 199 not taken.
✓ Branch 111 → 112 taken 1 time.
✗ Branch 111 → 197 not taken.
✓ Branch 114 → 115 taken 1 time.
✗ Branch 114 → 203 not taken.
✓ Branch 115 → 116 taken 1 time.
✗ Branch 115 → 203 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR,
119 "The placeholder string expects pointer, array or string, but got " + argType.getName(false))
120 5 placeholderCount++;
121 5 break;
122 }
123 default:
124 SOFT_ERROR_ER(node, PRINTF_TYPE_ERROR, "The placeholder string contains an invalid placeholder")
125 }
126 692 index = templatedString.find_first_of('%', index + 2); // We can also skip the following char
127 }
128
129 // Check if the number of placeholders matches the number of args
130
2/2
✓ Branch 140 → 141 taken 1 time.
✓ Branch 140 → 151 taken 844 times.
845 if (placeholderCount < node->argLst->args.size() - 1)
131
4/8
✓ Branch 143 → 144 taken 1 time.
✗ Branch 143 → 214 not taken.
✓ Branch 144 → 145 taken 1 time.
✗ Branch 144 → 212 not taken.
✓ Branch 147 → 148 taken 1 time.
✗ Branch 147 → 218 not taken.
✓ Branch 148 → 149 taken 1 time.
✗ Branch 148 → 218 not taken.
3 SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains less placeholders than arguments")
132
133
3/6
✓ Branch 151 → 152 taken 844 times.
✗ Branch 151 → 219 not taken.
✓ Branch 152 → 153 taken 844 times.
✗ Branch 152 → 219 not taken.
✓ Branch 153 → 154 taken 844 times.
✗ Branch 153 → 219 not taken.
844 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_INT), manIdx)};
134 852 }
135
136 153 std::any TypeChecker::visitBuiltinSizeOfCall(FctCallNode *node) const {
137
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 153 times.
153 assert(node->fqFunctionName == BUILTIN_FCT_NAME_SIZEOF);
138
139 // Directly set compile time value here, so that compile time ifs can be evaluated.
140 153 QualType qualType;
141
2/2
✓ Branch 6 → 7 taken 129 times.
✓ Branch 6 → 10 taken 24 times.
153 if (node->hasTemplateTypes) { // Align of type
142
1/2
✓ Branch 8 → 9 taken 129 times.
✗ Branch 8 → 54 not taken.
129 qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx);
143 } else { // Align of value
144
1/2
✓ Branch 11 → 12 taken 24 times.
✗ Branch 11 → 54 not taken.
24 qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx);
145 }
146
147
3/4
✓ Branch 13 → 14 taken 153 times.
✗ Branch 13 → 40 not taken.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 25 taken 151 times.
153 if (qualType.isOneOf({TY_UNRESOLVED, TY_DYN}))
148
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.
6 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Cannot use sizeof on a dyn or unresolved type");
149
150
1/2
✓ Branch 25 → 26 taken 151 times.
✗ Branch 25 → 54 not taken.
151 llvm::Type *type = qualType.toLLVMType(sourceFile);
151
3/6
✓ Branch 27 → 28 taken 151 times.
✗ Branch 27 → 50 not taken.
✓ Branch 28 → 29 taken 151 times.
✗ Branch 28 → 48 not taken.
✓ Branch 29 → 30 taken 151 times.
✗ Branch 29 → 48 not taken.
151 const int64_t typeSize = sourceFile->targetMachine->createDataLayout().getTypeAllocSize(type);
152
1/2
✓ Branch 31 → 32 taken 151 times.
✗ Branch 31 → 54 not taken.
151 node->data.at(manIdx).setCompileTimeValue({.longValue = typeSize});
153
154
3/6
✓ Branch 33 → 34 taken 151 times.
✗ Branch 33 → 52 not taken.
✓ Branch 34 → 35 taken 151 times.
✗ Branch 34 → 52 not taken.
✓ Branch 35 → 36 taken 151 times.
✗ Branch 35 → 52 not taken.
151 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
155 }
156
157 13 std::any TypeChecker::visitBuiltinAlignOfCall(FctCallNode *node) const {
158
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 13 times.
13 assert(node->fqFunctionName == BUILTIN_FCT_NAME_ALIGNOF);
159
160 // Directly set compile time value here, so that compile time ifs can be evaluated.
161 13 QualType qualType;
162
2/2
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 10 taken 11 times.
13 if (node->hasTemplateTypes) { // Align of type
163
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 54 not taken.
2 qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx);
164 } else { // Align of value
165
1/2
✓ Branch 11 → 12 taken 11 times.
✗ Branch 11 → 54 not taken.
11 qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx);
166 }
167
168
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}))
169
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.
6 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Cannot use alignof on a dyn or unresolved type");
170
171
1/2
✓ Branch 25 → 26 taken 11 times.
✗ Branch 25 → 54 not taken.
11 llvm::Type *type = qualType.toLLVMType(sourceFile);
172
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();
173
1/2
✓ Branch 31 → 32 taken 11 times.
✗ Branch 31 → 54 not taken.
11 node->data.at(manIdx).setCompileTimeValue({.longValue = typeAlignment});
174
175
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.
11 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
176 }
177
178 8 std::any TypeChecker::visitBuiltinTypeIdCall(FctCallNode *node) const {
179
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 8 times.
8 assert(node->fqFunctionName == BUILTIN_FCT_NAME_TYPEID);
180
181 // Directly set compile time value here, so that compile time ifs can be evaluated.
182 8 QualType qualType;
183
2/2
✓ Branch 6 → 7 taken 7 times.
✓ Branch 6 → 10 taken 1 time.
8 if (node->hasTemplateTypes) { // typeid of type
184
1/2
✓ Branch 8 → 9 taken 7 times.
✗ Branch 8 → 26 not taken.
7 qualType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx);
185 } else { // typeid of value
186
1/2
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 26 not taken.
1 qualType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx);
187 }
188
1/2
✓ Branch 14 → 15 taken 8 times.
✗ Branch 14 → 26 not taken.
8 const uint64_t typeId = TypeRegistry::getTypeHash(*qualType.getType());
189
1/2
✓ Branch 15 → 16 taken 8 times.
✗ Branch 15 → 26 not taken.
8 node->data.at(manIdx).setCompileTimeValue({.longValue = std::bit_cast<int64_t>(typeId)});
190
191
3/6
✓ Branch 18 → 19 taken 8 times.
✗ Branch 18 → 24 not taken.
✓ Branch 19 → 20 taken 8 times.
✗ Branch 19 → 24 not taken.
✓ Branch 20 → 21 taken 8 times.
✗ Branch 20 → 24 not taken.
8 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
192 }
193
194 60 std::any TypeChecker::visitBuiltinLenCall(FctCallNode *node) const {
195
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 60 times.
60 assert(node->fqFunctionName == BUILTIN_FCT_NAME_LEN);
196
197 // Directly set compile time value here, so that compile time ifs can be evaluated.
198
1/2
✓ Branch 7 → 8 taken 60 times.
✗ Branch 7 → 56 not taken.
60 QualType argType = node->argLst->args.front()->getEvaluatedSymbolType(manIdx);
199
1/2
✓ Branch 8 → 9 taken 60 times.
✗ Branch 8 → 45 not taken.
60 argType = argType.removeReferenceWrapper();
200
201 // Check if arg is of type array
202
8/10
✓ Branch 9 → 10 taken 60 times.
✗ Branch 9 → 56 not taken.
✓ Branch 10 → 11 taken 36 times.
✓ Branch 10 → 14 taken 24 times.
✓ Branch 11 → 12 taken 36 times.
✗ Branch 11 → 56 not taken.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 35 times.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 27 taken 59 times.
60 if (!argType.isArray() && !argType.is(TY_STRING))
203
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.
3 SOFT_ERROR_ER(node->argLst->args.front(), EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays or strings")
204
205
3/4
✓ Branch 27 → 28 taken 59 times.
✗ Branch 27 → 56 not taken.
✓ Branch 28 → 29 taken 24 times.
✓ Branch 28 → 33 taken 35 times.
59 if (argType.is(TY_ARRAY)) {
206
2/4
✓ Branch 29 → 30 taken 24 times.
✗ Branch 29 → 56 not taken.
✓ Branch 30 → 31 taken 24 times.
✗ Branch 30 → 53 not taken.
24 node->data.at(manIdx).setCompileTimeValue({.longValue = argType.getArraySize()});
207 } else {
208 // If we want to use the len builtin on a string, we need to import the string runtime module
209
3/4
✓ Branch 33 → 34 taken 35 times.
✗ Branch 33 → 56 not taken.
✓ Branch 36 → 37 taken 34 times.
✓ Branch 36 → 38 taken 1 time.
70 if (!sourceFile->isStringRT())
210
1/2
✓ Branch 37 → 38 taken 34 times.
✗ Branch 37 → 56 not taken.
34 sourceFile->requestRuntimeModule(STRING_RT);
211 }
212
213
3/6
✓ Branch 38 → 39 taken 59 times.
✗ Branch 38 → 54 not taken.
✓ Branch 39 → 40 taken 59 times.
✗ Branch 39 → 54 not taken.
✓ Branch 40 → 41 taken 59 times.
✗ Branch 40 → 54 not taken.
59 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
214 }
215
216 744 std::any TypeChecker::visitBuiltinPanicCall(FctCallNode *node) const {
217
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 744 times.
744 assert(node->fqFunctionName == BUILTIN_FCT_NAME_PANIC);
218
219
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 744 times.
744 assert(node->hasArgs);
220 744 const AssignExprNode *assignExpr = node->argLst->args.front();
221
1/2
✓ Branch 9 → 10 taken 744 times.
✗ Branch 9 → 47 not taken.
744 QualType argType = assignExpr->getEvaluatedSymbolType(manIdx);
222
2/8
✓ Branch 10 → 11 taken 744 times.
✗ Branch 10 → 47 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 16 taken 744 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 36 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 36 not taken.
744 HANDLE_UNRESOLVED_TYPE_ER(argType)
223
1/2
✓ Branch 16 → 17 taken 744 times.
✗ Branch 16 → 37 not taken.
744 argType = argType.removeReferenceWrapper();
224
225 // Check if arg is of type array
226
2/4
✓ Branch 17 → 18 taken 744 times.
✗ Branch 17 → 47 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 29 taken 744 times.
744 if (!argType.isErrorObj())
227 SOFT_ERROR_ER(assignExpr, EXPECTED_ERROR_TYPE, "The panic builtin can only work with errors")
228
229
3/6
✓ Branch 29 → 30 taken 744 times.
✗ Branch 29 → 45 not taken.
✓ Branch 30 → 31 taken 744 times.
✗ Branch 30 → 45 not taken.
✓ Branch 31 → 32 taken 744 times.
✗ Branch 31 → 45 not taken.
744 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_DYN), manIdx)};
230 }
231
232 1 std::any TypeChecker::visitBuiltinSyscallCall(FctCallNode *node) const {
233
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
1 assert(node->fqFunctionName == BUILTIN_FCT_NAME_SYSCALL);
234
235 // Check if the syscall number if of type short
236 1 const AssignExprNode *sysCallNumberExpr = node->argLst->args.front();
237
1/2
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 57 not taken.
1 const QualType sysCallNumberType = sysCallNumberExpr->getEvaluatedSymbolType(manIdx);
238
2/4
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 57 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 20 taken 1 time.
1 if (!sysCallNumberType.is(TY_SHORT))
239 SOFT_ERROR_ER(sysCallNumberExpr, INVALID_SYSCALL_NUMBER_TYPE, "Syscall number must be of type short")
240
241 // Check if the syscall number is out of range
242 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
243
2/4
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 57 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 34 taken 1 time.
1 if (node->hasCompileTimeValue(manIdx)) {
244 const unsigned short sysCallNumber = node->getCompileTimeValue(manIdx).shortValue;
245 if (sysCallNumber < 0 || sysCallNumber > 439)
246 SOFT_ERROR_ER(node, SYSCALL_NUMBER_OUT_OF_RANGE, "Only syscall numbers between 0 and 439 are supported")
247 }
248
249
3/6
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 55 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 55 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 55 not taken.
1 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
250 }
251
252 6 std::any TypeChecker::visitBuiltinIsSameCall(FctCallNode *node) const {
253
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 6 times.
6 assert(node->fqFunctionName == BUILTIN_FCT_NAME_IS_SAME);
254
255 // Directly set compile time value here, so that compile time ifs can be evaluated.
256
1/2
✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 25 not taken.
6 node->setCompileTimeValue({.boolValue = true}, manIdx);
257 6 const std::vector<DataTypeNode *> &dataTypeNodes = node->templateTypeLst->dataTypes;
258
1/2
✓ Branch 8 → 9 taken 6 times.
✗ Branch 8 → 30 not taken.
6 const QualType firstType = dataTypeNodes.front()->getEvaluatedSymbolType(manIdx);
259
2/2
✓ Branch 18 → 10 taken 6 times.
✓ Branch 18 → 19 taken 2 times.
8 for (size_t i = 1; i < dataTypeNodes.size(); i++) {
260
2/4
✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 27 not taken.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 27 not taken.
6 const QualType qualType = dataTypeNodes.at(i)->getEvaluatedSymbolType(manIdx);
261
3/4
✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 27 not taken.
✓ Branch 13 → 14 taken 4 times.
✓ Branch 13 → 16 taken 2 times.
6 if (!qualType.matches(firstType, false, true, false)) {
262
1/2
✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 26 not taken.
4 node->setCompileTimeValue({.boolValue = false}, manIdx);
263 4 break;
264 }
265 }
266
267
3/6
✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 28 not taken.
✓ Branch 20 → 21 taken 6 times.
✗ Branch 20 → 28 not taken.
✓ Branch 21 → 22 taken 6 times.
✗ Branch 21 → 28 not taken.
6 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)};
268 }
269
270 1 std::any TypeChecker::visitBuiltinImplementsInterfaceCall(FctCallNode *node) const {
271
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
1 assert(node->fqFunctionName == BUILTIN_FCT_NAME_IMPLEMENTS_INTERFACE);
272
273
1/2
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 28 not taken.
1 const QualType interfaceType = node->templateTypeLst->dataTypes.front()->getEvaluatedSymbolType(manIdx);
274
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 28 not taken.
1 const QualType structType = node->templateTypeLst->dataTypes.back()->getEvaluatedSymbolType(manIdx);
275
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);
276
1/2
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 25 not taken.
1 node->setCompileTimeValue({.boolValue = value}, manIdx);
277
278
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.
1 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx)};
279 }
280
281 } // namespace spice::compiler
282