GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeCheckerValues.cpp
Date: 2025-03-05 01:50:32
Exec Total Coverage
Lines: 396 415 95.4%
Functions: 12 13 92.3%
Branches: 632 1199 52.7%

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "TypeChecker.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTNodes.h>
7 #include <ast/Attributes.h>
8 #include <global/GlobalResourceManager.h>
9 #include <symboltablebuilder/ScopeHandle.h>
10 #include <symboltablebuilder/SymbolTableBuilder.h>
11 #include <typechecker/MacroDefs.h>
12 #include <typechecker/TypeMatcher.h>
13
14 namespace spice::compiler {
15
16 15097 std::any TypeChecker::visitValue(ValueNode *node) {
17 // Function call
18
2/2
✓ Branch 0 (2→3) taken 13511 times.
✓ Branch 1 (2→4) taken 1586 times.
15097 if (node->fctCall)
19 13511 return visit(node->fctCall);
20
21 // Array initialization
22
2/2
✓ Branch 0 (4→5) taken 74 times.
✓ Branch 1 (4→6) taken 1512 times.
1586 if (node->arrayInitialization)
23 74 return visit(node->arrayInitialization);
24
25 // Struct instantiation
26
2/2
✓ Branch 0 (6→7) taken 284 times.
✓ Branch 1 (6→8) taken 1228 times.
1512 if (node->structInstantiation)
27 284 return visit(node->structInstantiation);
28
29 // Lambda function
30
2/2
✓ Branch 0 (8→9) taken 12 times.
✓ Branch 1 (8→10) taken 1216 times.
1228 if (node->lambdaFunc)
31 12 return visit(node->lambdaFunc);
32
33 // Lambda procedure
34
2/2
✓ Branch 0 (10→11) taken 28 times.
✓ Branch 1 (10→12) taken 1188 times.
1216 if (node->lambdaProc)
35 28 return visit(node->lambdaProc);
36
37 // Lambda expression
38
2/2
✓ Branch 0 (12→13) taken 1 times.
✓ Branch 1 (12→14) taken 1187 times.
1188 if (node->lambdaExpr)
39 1 return visit(node->lambdaExpr);
40
41 // Typed nil
42
1/2
✓ Branch 0 (14→15) taken 1187 times.
✗ Branch 1 (14→41) not taken.
1187 if (node->isNil) {
43
2/4
✓ Branch 0 (15→16) taken 1187 times.
✗ Branch 1 (15→52) not taken.
✓ Branch 2 (16→17) taken 1187 times.
✗ Branch 3 (16→50) not taken.
1187 const auto nilType = std::any_cast<QualType>(visit(node->nilType));
44
2/8
✓ Branch 0 (18→19) taken 1187 times.
✗ Branch 1 (18→62) not taken.
✗ Branch 2 (19→20) not taken.
✓ Branch 3 (19→24) taken 1187 times.
✗ Branch 4 (20→21) not taken.
✗ Branch 5 (20→53) not taken.
✗ Branch 6 (21→22) not taken.
✗ Branch 7 (21→53) not taken.
1187 HANDLE_UNRESOLVED_TYPE_ER(nilType)
45
2/4
✓ Branch 0 (24→25) taken 1187 times.
✗ Branch 1 (24→62) not taken.
✗ Branch 2 (25→26) not taken.
✓ Branch 3 (25→36) taken 1187 times.
1187 if (nilType.is(TY_DYN))
46 SOFT_ERROR_ER(node->nilType, UNEXPECTED_DYN_TYPE, "Nil must have an explicit type")
47
2/4
✓ Branch 0 (36→37) taken 1187 times.
✗ Branch 1 (36→61) not taken.
✓ Branch 2 (37→38) taken 1187 times.
✗ Branch 3 (37→61) not taken.
1187 return ExprResult{node->setEvaluatedSymbolType(nilType, manIdx)};
48 }
49
50 throw CompilerError(UNHANDLED_BRANCH, "Value fall-through"); // GCOV_EXCL_LINE
51 }
52
53 18205 std::any TypeChecker::visitConstant(ConstantNode *node) {
54 SuperType superType;
55
7/9
✓ Branch 0 (2→3) taken 309 times.
✓ Branch 1 (2→4) taken 3142 times.
✓ Branch 2 (2→5) taken 540 times.
✓ Branch 3 (2→6) taken 6713 times.
✗ Branch 4 (2→7) not taken.
✓ Branch 5 (2→8) taken 2165 times.
✓ Branch 6 (2→9) taken 3096 times.
✓ Branch 7 (2→10) taken 2240 times.
✗ Branch 8 (2→11) not taken.
18205 switch (node->type) {
56 309 case ConstantNode::PrimitiveValueType::TYPE_DOUBLE:
57 309 superType = TY_DOUBLE;
58 309 break;
59 3142 case ConstantNode::PrimitiveValueType::TYPE_INT:
60 3142 superType = TY_INT;
61 3142 break;
62 540 case ConstantNode::PrimitiveValueType::TYPE_SHORT:
63 540 superType = TY_SHORT;
64 540 break;
65 6713 case ConstantNode::PrimitiveValueType::TYPE_LONG:
66 6713 superType = TY_LONG;
67 6713 break;
68 case ConstantNode::PrimitiveValueType::TYPE_BYTE:
69 superType = TY_BYTE;
70 break;
71 2165 case ConstantNode::PrimitiveValueType::TYPE_CHAR:
72 2165 superType = TY_CHAR;
73 2165 break;
74 3096 case ConstantNode::PrimitiveValueType::TYPE_STRING:
75 3096 superType = TY_STRING;
76 3096 break;
77 2240 case ConstantNode::PrimitiveValueType::TYPE_BOOL:
78 2240 superType = TY_BOOL;
79 2240 break;
80 default: // GCOV_EXCL_LINE
81 throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE
82 }
83
3/6
✓ Branch 0 (19→20) taken 18205 times.
✗ Branch 1 (19→34) not taken.
✓ Branch 2 (20→21) taken 18205 times.
✗ Branch 3 (20→34) not taken.
✓ Branch 4 (21→22) taken 18205 times.
✗ Branch 5 (21→34) not taken.
18205 return ExprResult{node->setEvaluatedSymbolType(QualType(superType), manIdx)};
84 }
85
86 13511 std::any TypeChecker::visitFctCall(FctCallNode *node) {
87
1/2
✓ Branch 0 (2→3) taken 13511 times.
✗ Branch 1 (2→501) not taken.
13511 FctCallNode::FctCallData &data = node->data.at(manIdx);
88 13511 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
89
90 // Retrieve arg types
91 13511 args.clear();
92
2/2
✓ Branch 0 (4→5) taken 10477 times.
✓ Branch 1 (4→28) taken 3034 times.
13511 if (node->hasArgs) {
93
1/2
✓ Branch 0 (6→7) taken 10477 times.
✗ Branch 1 (6→501) not taken.
10477 args.reserve(node->argLst->args.size());
94
2/2
✓ Branch 0 (26→9) taken 16079 times.
✓ Branch 1 (26→27) taken 10477 times.
26556 for (AssignExprNode *arg : node->argLst->args) {
95 // Visit argument
96
2/4
✓ Branch 0 (10→11) taken 16079 times.
✗ Branch 1 (10→386) not taken.
✓ Branch 2 (11→12) taken 16079 times.
✗ Branch 3 (11→384) not taken.
16079 const auto argResult = std::any_cast<ExprResult>(visit(arg));
97
2/8
✓ Branch 0 (13→14) taken 16079 times.
✗ Branch 1 (13→389) not taken.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→19) taken 16079 times.
✗ Branch 4 (15→16) not taken.
✗ Branch 5 (15→387) not taken.
✗ Branch 6 (16→17) not taken.
✗ Branch 7 (16→387) not taken.
16079 HANDLE_UNRESOLVED_TYPE_ER(argResult.type)
98
2/4
✓ Branch 0 (19→20) taken 16079 times.
✗ Branch 1 (19→389) not taken.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→22) taken 16079 times.
16079 assert(!argResult.type.hasAnyGenericParts());
99 // Save arg type to arg types list
100
1/2
✓ Branch 0 (23→24) taken 16079 times.
✗ Branch 1 (23→388) not taken.
16079 args.emplace_back(argResult.type, argResult.isTemporary());
101 }
102 }
103
104 // Retrieve entry of the first fragment
105 13511 const std::string &firstFrag = node->functionNameFragments.front();
106
1/2
✓ Branch 0 (29→30) taken 13511 times.
✗ Branch 1 (29→501) not taken.
13511 SymbolTableEntry *firstFragEntry = currentScope->lookup(firstFrag);
107
2/2
✓ Branch 0 (32→33) taken 8381 times.
✓ Branch 1 (32→70) taken 5130 times.
13511 if (firstFragEntry) {
108 // Check if we have seen a 'this.' prefix, because the generator needs that
109
6/8
✓ Branch 0 (33→34) taken 1 times.
✓ Branch 1 (33→37) taken 8380 times.
✓ Branch 2 (34→35) taken 1 times.
✗ Branch 3 (34→401) not taken.
✓ Branch 4 (35→36) taken 1 times.
✗ Branch 5 (35→37) not taken.
✓ Branch 6 (38→39) taken 1 times.
✓ Branch 7 (38→48) taken 8380 times.
8381 if (firstFragEntry->scope->type == ScopeType::STRUCT && firstFrag != THIS_VARIABLE_NAME)
110
5/10
✓ Branch 0 (39→40) taken 1 times.
✗ Branch 1 (39→395) not taken.
✓ Branch 2 (40→41) taken 1 times.
✗ Branch 3 (40→393) not taken.
✓ Branch 4 (41→42) taken 1 times.
✗ Branch 5 (41→391) not taken.
✓ Branch 6 (44→45) taken 1 times.
✗ Branch 7 (44→397) not taken.
✓ Branch 8 (45→46) taken 1 times.
✗ Branch 9 (45→397) not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE,
111 "The symbol '" + firstFrag + "' could not be found. Missing 'this.' prefix?")
112
113 8380 firstFragEntry->used = true;
114 // Decide of which type the function call is
115
2/4
✓ Branch 0 (48→49) taken 8380 times.
✗ Branch 1 (48→401) not taken.
✓ Branch 2 (49→50) taken 8380 times.
✗ Branch 3 (49→401) not taken.
8380 const QualType &baseType = firstFragEntry->getQualType().getBase();
116
5/8
✓ Branch 0 (50→51) taken 8380 times.
✗ Branch 1 (50→401) not taken.
✓ Branch 2 (51→52) taken 4 times.
✓ Branch 3 (51→56) taken 8376 times.
✓ Branch 4 (52→53) taken 4 times.
✗ Branch 5 (52→398) not taken.
✓ Branch 6 (53→54) taken 4 times.
✗ Branch 7 (53→398) not taken.
8380 HANDLE_UNRESOLVED_TYPE_ER(baseType)
117
3/4
✓ Branch 0 (56→57) taken 8376 times.
✗ Branch 1 (56→399) not taken.
✓ Branch 2 (57→58) taken 6355 times.
✓ Branch 3 (57→61) taken 2021 times.
8376 if (baseType.isOneOf({TY_STRUCT, TY_INTERFACE})) {
118
2/2
✓ Branch 0 (58→59) taken 949 times.
✓ Branch 1 (58→60) taken 5406 times.
6355 if (firstFragEntry->scope->type == ScopeType::GLOBAL)
119 949 callType = FctCallNode::FctCallType::TYPE_CTOR;
120 else
121 5406 callType = FctCallNode::FctCallType::TYPE_METHOD;
122
7/8
✓ Branch 0 (61→62) taken 2021 times.
✗ Branch 1 (61→400) not taken.
✓ Branch 2 (62→63) taken 1945 times.
✓ Branch 3 (62→65) taken 76 times.
✓ Branch 4 (63→64) taken 48 times.
✓ Branch 5 (63→65) taken 1897 times.
✓ Branch 6 (66→67) taken 48 times.
✓ Branch 7 (66→68) taken 1973 times.
2021 } else if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && firstFragEntry->scope->type != ScopeType::GLOBAL) {
123 48 callType = FctCallNode::FctCallType::TYPE_FCT_PTR;
124 }
125 }
126
127 // Get struct name. Retrieve it from alias if required
128
1/2
✓ Branch 0 (70→71) taken 13506 times.
✗ Branch 1 (70→501) not taken.
13506 const auto &[structEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqFunctionName);
129
4/6
✓ Branch 0 (73→74) taken 1 times.
✓ Branch 1 (73→77) taken 13505 times.
✓ Branch 2 (74→75) taken 1 times.
✗ Branch 3 (74→501) not taken.
✓ Branch 4 (75→76) taken 1 times.
✗ Branch 5 (75→501) not taken.
13506 const std::string &fqFunctionName = isAlias ? structEntry->getQualType().getSubType() : node->fqFunctionName;
130
131 // Get the concrete template types
132 13506 templateTypes.clear();
133
2/2
✓ Branch 0 (79→80) taken 1 times.
✓ Branch 1 (79→99) taken 13505 times.
13506 if (isAlias) {
134 // Retrieve concrete template types from type alias
135
3/6
✓ Branch 0 (80→81) taken 1 times.
✗ Branch 1 (80→501) not taken.
✓ Branch 2 (81→82) taken 1 times.
✗ Branch 3 (81→501) not taken.
✓ Branch 4 (82→83) taken 1 times.
✗ Branch 5 (82→501) not taken.
1 templateTypes = structEntry->getQualType().getTemplateTypes();
136 // Check if the aliased type specified template types and the struct instantiation does
137
3/6
✓ Branch 0 (84→85) taken 1 times.
✗ Branch 1 (84→87) not taken.
✗ Branch 2 (85→86) not taken.
✓ Branch 3 (85→87) taken 1 times.
✗ Branch 4 (88→89) not taken.
✓ Branch 5 (88→99) taken 1 times.
1 if (!templateTypes.empty() && node->hasTemplateTypes)
138 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
139 }
140
141 // Get concrete template types
142
2/2
✓ Branch 0 (99→100) taken 508 times.
✓ Branch 1 (99→135) taken 12998 times.
13506 if (node->hasTemplateTypes) {
143
2/2
✓ Branch 0 (133→102) taken 600 times.
✓ Branch 1 (133→134) taken 508 times.
1108 for (DataTypeNode *templateTypeNode : node->templateTypeLst->dataTypes) {
144
2/4
✓ Branch 0 (103→104) taken 600 times.
✗ Branch 1 (103→411) not taken.
✓ Branch 2 (104→105) taken 600 times.
✗ Branch 3 (104→409) not taken.
600 auto templateType = std::any_cast<QualType>(visit(templateTypeNode));
145
2/4
✓ Branch 0 (106→107) taken 600 times.
✗ Branch 1 (106→412) not taken.
✗ Branch 2 (107→108) not taken.
✓ Branch 3 (107→109) taken 600 times.
600 assert(!templateType.isOneOf({TY_DYN, TY_INVALID}));
146
147 // Abort if the type is unresolved
148
2/4
✓ Branch 0 (109→110) taken 600 times.
✗ Branch 1 (109→422) not taken.
✗ Branch 2 (110→111) not taken.
✓ Branch 3 (110→117) taken 600 times.
600 if (templateType.is(TY_UNRESOLVED))
149 HANDLE_UNRESOLVED_TYPE_ER(templateType)
150
151 // Check if the given type is generic
152
2/4
✓ Branch 0 (117→118) taken 600 times.
✗ Branch 1 (117→422) not taken.
✗ Branch 2 (118→119) not taken.
✓ Branch 3 (118→129) taken 600 times.
600 if (templateType.is(TY_GENERIC))
153 SOFT_ERROR_ER(templateTypeNode, EXPECTED_NON_GENERIC_TYPE, "You must specify a concrete type here")
154
155
1/2
✓ Branch 0 (129→130) taken 600 times.
✗ Branch 1 (129→422) not taken.
600 templateTypes.push_back(templateType);
156 }
157 }
158
159 // Check if this is a method call or a normal function call
160
2/2
✓ Branch 0 (136→137) taken 5406 times.
✓ Branch 1 (136→151) taken 8100 times.
13506 if (data.isMethodCall()) {
161 // This is a method call
162
1/2
✓ Branch 0 (137→138) taken 5406 times.
✗ Branch 1 (137→501) not taken.
5406 thisType = firstFragEntry->getQualType();
163
2/4
✓ Branch 0 (138→139) taken 5406 times.
✗ Branch 1 (138→424) not taken.
✓ Branch 2 (139→140) taken 5406 times.
✗ Branch 3 (139→424) not taken.
5406 Scope *structBodyScope = thisType.getBase().getBodyScope();
164
1/2
✗ Branch 0 (140→141) not taken.
✓ Branch 1 (140→142) taken 5406 times.
5406 assert(structBodyScope != nullptr);
165
3/4
✓ Branch 0 (142→143) taken 5406 times.
✗ Branch 1 (142→501) not taken.
✓ Branch 2 (143→144) taken 2 times.
✓ Branch 3 (143→149) taken 5404 times.
5406 if (!visitMethodCall(node, structBodyScope)) // Check if soft errors occurred
166
3/6
✓ Branch 0 (144→145) taken 2 times.
✗ Branch 1 (144→425) not taken.
✓ Branch 2 (145→146) taken 2 times.
✗ Branch 3 (145→425) not taken.
✓ Branch 4 (146→147) taken 2 times.
✗ Branch 5 (146→425) not taken.
2 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
167
1/2
✗ Branch 0 (149→150) not taken.
✓ Branch 1 (149→187) taken 5404 times.
5404 assert(calleeParentScope != nullptr);
168
2/2
✓ Branch 0 (152→153) taken 48 times.
✓ Branch 1 (152→166) taken 8052 times.
8100 } else if (data.isFctPtrCall()) {
169 // This is a function pointer call
170
2/4
✓ Branch 0 (153→154) taken 48 times.
✗ Branch 1 (153→430) not taken.
✓ Branch 2 (154→155) taken 48 times.
✗ Branch 3 (154→430) not taken.
48 const QualType &functionType = firstFragEntry->getQualType().getBase();
171
2/4
✓ Branch 0 (155→156) taken 48 times.
✗ Branch 1 (155→427) not taken.
✗ Branch 2 (156→157) not taken.
✓ Branch 3 (156→158) taken 48 times.
48 assert(functionType.isOneOf({TY_FUNCTION, TY_PROCEDURE}));
172
2/4
✓ Branch 0 (158→159) taken 48 times.
✗ Branch 1 (158→430) not taken.
✗ Branch 2 (159→160) not taken.
✓ Branch 3 (159→165) taken 48 times.
48 if (!visitFctPtrCall(node, functionType)) // Check if soft errors occurred
173 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
174 } else {
175 // This is an ordinary function call
176
3/4
✓ Branch 0 (167→168) taken 954 times.
✓ Branch 1 (167→171) taken 7098 times.
✗ Branch 2 (169→170) not taken.
✓ Branch 3 (169→171) taken 954 times.
8052 assert(data.isOrdinaryCall() || data.isCtorCall());
177
5/6
✓ Branch 0 (171→172) taken 8052 times.
✗ Branch 1 (171→433) not taken.
✓ Branch 2 (172→173) taken 8050 times.
✓ Branch 3 (172→431) taken 2 times.
✓ Branch 4 (174→175) taken 4 times.
✓ Branch 5 (174→180) taken 8046 times.
8054 if (!visitOrdinaryFctCall(node, fqFunctionName)) // Check if soft errors occurred
178
3/6
✓ Branch 0 (175→176) taken 4 times.
✗ Branch 1 (175→434) not taken.
✓ Branch 2 (176→177) taken 4 times.
✗ Branch 3 (176→434) not taken.
✓ Branch 4 (177→178) taken 4 times.
✗ Branch 5 (177→434) not taken.
4 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
179
1/2
✗ Branch 0 (180→181) not taken.
✓ Branch 1 (180→182) taken 8046 times.
8046 assert(calleeParentScope != nullptr);
180
181 // If the call is no ordinary call, it must be a constructor, which takes a struct as this type.
182
4/6
✓ Branch 0 (183→184) taken 2027 times.
✓ Branch 1 (183→187) taken 6019 times.
✓ Branch 2 (184→185) taken 2027 times.
✗ Branch 3 (184→501) not taken.
✗ Branch 4 (185→186) not taken.
✓ Branch 5 (185→187) taken 2027 times.
8046 assert(data.isOrdinaryCall() || data.thisType.is(TY_STRUCT));
183 }
184
185
2/2
✓ Branch 0 (188→189) taken 13450 times.
✓ Branch 1 (188→260) taken 48 times.
13498 if (!data.isFctPtrCall()) {
186 // Check if we were able to find a function
187
2/2
✓ Branch 0 (189→190) taken 12 times.
✓ Branch 1 (189→227) taken 13438 times.
13450 if (!callee) {
188 // Build error message
189
6/10
✓ Branch 0 (191→192) taken 2 times.
✓ Branch 1 (191→195) taken 10 times.
✓ Branch 2 (194→197) taken 2 times.
✗ Branch 3 (194→436) not taken.
✓ Branch 4 (196→197) taken 10 times.
✗ Branch 5 (196→436) not taken.
✓ Branch 6 (197→198) taken 2 times.
✓ Branch 7 (197→200) taken 10 times.
✗ Branch 8 (436→437) not taken.
✗ Branch 9 (436→439) not taken.
14 const std::string functionName = data.isCtorCall() ? CTOR_FUNCTION_NAME : node->functionNameFragments.back();
190 12 ParamList errArgTypes;
191
1/2
✓ Branch 0 (201→202) taken 12 times.
✗ Branch 1 (201→456) not taken.
12 errArgTypes.reserve(args.size());
192
5/8
✓ Branch 0 (202→203) taken 12 times.
✗ Branch 1 (202→442) not taken.
✓ Branch 2 (203→204) taken 12 times.
✗ Branch 3 (203→442) not taken.
✓ Branch 4 (204→205) taken 12 times.
✗ Branch 5 (204→442) not taken.
✓ Branch 6 (210→206) taken 7 times.
✓ Branch 7 (210→211) taken 12 times.
19 for (const auto &type : args | std::views::keys)
193
1/2
✓ Branch 0 (207→208) taken 7 times.
✗ Branch 1 (207→441) not taken.
7 errArgTypes.push_back({type, false});
194
2/4
✓ Branch 0 (212→213) taken 12 times.
✗ Branch 1 (212→443) not taken.
✓ Branch 2 (213→214) taken 12 times.
✗ Branch 3 (213→443) not taken.
12 const std::string signature = Function::getSignature(functionName, thisType, QualType(TY_DYN), errArgTypes, {}, false);
195 // Throw error
196
5/10
✓ Branch 0 (215→216) taken 12 times.
✗ Branch 1 (215→451) not taken.
✓ Branch 2 (216→217) taken 12 times.
✗ Branch 3 (216→449) not taken.
✓ Branch 4 (217→218) taken 12 times.
✗ Branch 5 (217→447) not taken.
✓ Branch 6 (220→221) taken 12 times.
✗ Branch 7 (220→453) not taken.
✓ Branch 8 (221→222) taken 12 times.
✗ Branch 9 (221→453) not taken.
12 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_FUNCTION, "Function/procedure '" + signature + "' could not be found")
197 12 }
198
199 // Check if we need to request a re-visit, because the function body was not type-checked yet
200
1/2
✓ Branch 0 (227→228) taken 13438 times.
✗ Branch 1 (227→501) not taken.
13438 requestRevisitIfRequired(callee);
201
202 // Get function entry from function object
203 13438 SymbolTableEntry *functionEntry = callee->entry;
204
205 // Check if the called function has sufficient visibility
206
1/2
✓ Branch 0 (228→229) taken 13438 times.
✗ Branch 1 (228→501) not taken.
13438 isImported = calleeParentScope->isImportedBy(rootScope);
207
8/10
✓ Branch 0 (229→230) taken 3796 times.
✓ Branch 1 (229→234) taken 9642 times.
✓ Branch 2 (230→231) taken 3796 times.
✗ Branch 3 (230→501) not taken.
✓ Branch 4 (231→232) taken 3796 times.
✗ Branch 5 (231→501) not taken.
✓ Branch 6 (232→233) taken 1 times.
✓ Branch 7 (232→234) taken 3795 times.
✓ Branch 8 (235→236) taken 1 times.
✓ Branch 9 (235→260) taken 13437 times.
13438 if (isImported && !functionEntry->getQualType().isPublic()) {
208
1/2
✓ Branch 0 (236→237) taken 1 times.
✗ Branch 1 (236→477) not taken.
1 const QualType functionEntryType = functionEntry->getQualType();
209
1/2
✓ Branch 0 (237→238) taken 1 times.
✗ Branch 1 (237→477) not taken.
1 const std::string signature = callee->getSignature();
210
2/4
✓ Branch 0 (238→239) taken 1 times.
✗ Branch 1 (238→475) not taken.
✓ Branch 2 (239→240) taken 1 times.
✗ Branch 3 (239→249) not taken.
1 if (functionEntryType.is(TY_FUNCTION))
211
5/10
✓ Branch 0 (240→241) taken 1 times.
✗ Branch 1 (240→465) not taken.
✓ Branch 2 (241→242) taken 1 times.
✗ Branch 3 (241→463) not taken.
✓ Branch 4 (242→243) taken 1 times.
✗ Branch 5 (242→461) not taken.
✓ Branch 6 (245→246) taken 1 times.
✗ Branch 7 (245→467) not taken.
✓ Branch 8 (246→247) taken 1 times.
✗ Branch 9 (246→467) not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Function '" + signature + "' has insufficient visibility")
212 else
213 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Procedure '" + signature + "' has insufficient visibility")
214 1 }
215 }
216
217 // Generate arg infos
218
2/2
✓ Branch 0 (260→261) taken 10465 times.
✓ Branch 1 (260→302) taken 3020 times.
13485 if (node->hasArgs) {
219 10465 QualTypeList paramTypes;
220
2/2
✓ Branch 0 (262→263) taken 25 times.
✓ Branch 1 (262→269) taken 10440 times.
10465 if (data.isFctPtrCall()) {
221
2/4
✓ Branch 0 (263→264) taken 25 times.
✗ Branch 1 (263→479) not taken.
✓ Branch 2 (264→265) taken 25 times.
✗ Branch 3 (264→479) not taken.
25 const QualType &functionType = firstFragEntry->getQualType().getBase();
222
1/2
✓ Branch 0 (265→266) taken 25 times.
✗ Branch 1 (265→478) not taken.
25 paramTypes = functionType.getFunctionParamTypes();
223 } else {
224
1/2
✗ Branch 0 (269→270) not taken.
✓ Branch 1 (269→271) taken 10440 times.
10440 assert(callee != nullptr);
225
1/2
✓ Branch 0 (271→272) taken 10440 times.
✗ Branch 1 (271→480) not taken.
10440 paramTypes = callee->getParamTypes();
226 }
227
228 10465 node->argLst->argInfos.clear();
229
2/2
✓ Branch 0 (295→277) taken 16064 times.
✓ Branch 1 (295→296) taken 10465 times.
26529 for (size_t argIdx = 0; argIdx < args.size(); argIdx++) {
230
1/2
✓ Branch 0 (277→278) taken 16064 times.
✗ Branch 1 (277→482) not taken.
16064 const QualType &expectedType = paramTypes.at(argIdx);
231
1/2
✓ Branch 0 (278→279) taken 16064 times.
✗ Branch 1 (278→482) not taken.
16064 const auto &[actualType, _] = args.at(argIdx);
232
233 16064 Function *copyCtor = nullptr;
234
10/14
✓ Branch 0 (281→282) taken 16064 times.
✗ Branch 1 (281→482) not taken.
✓ Branch 2 (282→283) taken 32 times.
✓ Branch 3 (282→288) taken 16032 times.
✓ Branch 4 (283→284) taken 32 times.
✗ Branch 5 (283→482) not taken.
✓ Branch 6 (284→285) taken 32 times.
✗ Branch 7 (284→288) not taken.
✓ Branch 8 (285→286) taken 32 times.
✗ Branch 9 (285→482) not taken.
✓ Branch 10 (286→287) taken 14 times.
✓ Branch 11 (286→288) taken 18 times.
✓ Branch 12 (289→290) taken 14 times.
✓ Branch 13 (289→292) taken 16050 times.
16064 if (expectedType.is(TY_STRUCT) && actualType.is(TY_STRUCT) && !actualType.isTriviallyCopyable(node)) {
235
1/2
✓ Branch 0 (290→291) taken 14 times.
✗ Branch 1 (290→482) not taken.
14 copyCtor = matchCopyCtor(actualType, node);
236 // Insert anonymous symbol to track the dtor call of the copy
237
1/2
✓ Branch 0 (291→292) taken 14 times.
✗ Branch 1 (291→482) not taken.
14 currentScope->symbolTable.insertAnonymous(actualType, node, argIdx + 1); // +1 because 0 is reserved for return value
238 }
239
240
1/2
✓ Branch 0 (292→293) taken 16064 times.
✗ Branch 1 (292→481) not taken.
16064 node->argLst->argInfos.push_back(ArgLstNode::ArgInfo{copyCtor});
241 }
242
1/2
✗ Branch 0 (298→299) not taken.
✓ Branch 1 (298→300) taken 10465 times.
10465 assert(node->argLst->argInfos.size() == node->argLst->args.size());
243 10465 }
244
245 // Retrieve return type
246
6/10
✓ Branch 0 (303→304) taken 48 times.
✓ Branch 1 (303→308) taken 13437 times.
✓ Branch 2 (304→305) taken 48 times.
✗ Branch 3 (304→485) not taken.
✓ Branch 4 (305→306) taken 48 times.
✗ Branch 5 (305→485) not taken.
✓ Branch 6 (306→307) taken 48 times.
✗ Branch 7 (306→485) not taken.
✓ Branch 8 (308→309) taken 13437 times.
✗ Branch 9 (308→485) not taken.
26922 const bool isFct = data.isFctPtrCall() ? firstFragEntry->getQualType().getBase().is(TY_FUNCTION) : callee->isFunction();
247 13485 QualType returnType;
248
2/2
✓ Branch 0 (313→314) taken 48 times.
✓ Branch 1 (313→321) taken 13437 times.
13485 if (data.isFctPtrCall()) {
249
6/10
✓ Branch 0 (314→315) taken 20 times.
✓ Branch 1 (314→319) taken 28 times.
✓ Branch 2 (315→316) taken 20 times.
✗ Branch 3 (315→486) not taken.
✓ Branch 4 (316→317) taken 20 times.
✗ Branch 5 (316→486) not taken.
✓ Branch 6 (317→318) taken 20 times.
✗ Branch 7 (317→486) not taken.
✓ Branch 8 (319→320) taken 28 times.
✗ Branch 9 (319→486) not taken.
48 returnType = isFct ? firstFragEntry->getQualType().getBase().getFunctionReturnType() : QualType(TY_BOOL);
250
2/2
✓ Branch 0 (322→323) taken 2025 times.
✓ Branch 1 (322→324) taken 11412 times.
13437 } else if (data.isCtorCall()) {
251 2025 returnType = thisType;
252
3/4
✓ Branch 0 (324→325) taken 11412 times.
✗ Branch 1 (324→501) not taken.
✓ Branch 2 (327→328) taken 2660 times.
✓ Branch 3 (327→330) taken 8752 times.
22824 } else if (callee->isProcedure()) {
253
1/2
✓ Branch 0 (328→329) taken 2660 times.
✗ Branch 1 (328→488) not taken.
2660 returnType = QualType(TY_DYN);
254 } else {
255 8752 returnType = callee->returnType;
256 }
257
1/2
✓ Branch 0 (331→332) taken 13485 times.
✗ Branch 1 (331→501) not taken.
13485 const QualType returnBaseType = returnType.getBase();
258
259 // Make sure this source file knows about the return type
260
3/4
✓ Branch 0 (332→333) taken 13485 times.
✗ Branch 1 (332→501) not taken.
✓ Branch 2 (333→334) taken 3157 times.
✓ Branch 3 (333→337) taken 10328 times.
13485 if (returnBaseType.is(TY_STRUCT))
261
2/4
✓ Branch 0 (334→335) taken 3157 times.
✗ Branch 1 (334→489) not taken.
✓ Branch 2 (335→336) taken 3157 times.
✗ Branch 3 (335→489) not taken.
3157 returnType = mapImportedScopeTypeToLocalType(returnBaseType.getBodyScope(), returnType);
262
263 // Add anonymous symbol to keep track of dtor call, if non-trivially destructible
264 13485 SymbolTableEntry *anonymousSymbol = nullptr;
265
8/10
✓ Branch 0 (337→338) taken 13485 times.
✗ Branch 1 (337→501) not taken.
✓ Branch 2 (338→339) taken 2783 times.
✓ Branch 3 (338→342) taken 10702 times.
✓ Branch 4 (339→340) taken 2783 times.
✗ Branch 5 (339→501) not taken.
✓ Branch 6 (340→341) taken 1849 times.
✓ Branch 7 (340→342) taken 934 times.
✓ Branch 8 (343→344) taken 1849 times.
✓ Branch 9 (343→346) taken 11636 times.
13485 if (returnType.is(TY_STRUCT) && !returnType.isTriviallyDestructible(node))
266
1/2
✓ Branch 0 (344→345) taken 1849 times.
✗ Branch 1 (344→501) not taken.
1849 anonymousSymbol = currentScope->symbolTable.insertAnonymous(returnType, node);
267
268 // Remove public qualifier to not have public local variables
269 13485 returnType.getQualifiers().isPublic = false;
270
271 // Check if the return value gets discarded
272
7/8
✓ Branch 0 (347→348) taken 8772 times.
✓ Branch 1 (347→351) taken 4713 times.
✓ Branch 2 (348→349) taken 8772 times.
✗ Branch 3 (348→501) not taken.
✓ Branch 4 (349→350) taken 148 times.
✓ Branch 5 (349→351) taken 8624 times.
✓ Branch 6 (352→353) taken 148 times.
✓ Branch 7 (352→378) taken 13337 times.
13485 if (isFct && !node->hasReturnValueReceiver()) {
273 // Check if we want to ignore the discarded return value
274 148 bool ignoreUnusedReturnValue = false;
275
2/2
✓ Branch 0 (354→355) taken 145 times.
✓ Branch 1 (354→375) taken 3 times.
148 if (!data.isFctPtrCall()) {
276
1/2
✗ Branch 0 (355→356) not taken.
✓ Branch 1 (355→357) taken 145 times.
145 assert(callee != nullptr);
277
1/2
✓ Branch 0 (357→358) taken 145 times.
✗ Branch 1 (357→359) not taken.
145 auto fctDef = dynamic_cast<const FctDefNode *>(callee->declNode);
278
12/18
✓ Branch 0 (360→361) taken 95 times.
✓ Branch 1 (360→368) taken 50 times.
✓ Branch 2 (361→362) taken 24 times.
✓ Branch 3 (361→368) taken 71 times.
✓ Branch 4 (364→365) taken 24 times.
✗ Branch 5 (364→490) not taken.
✓ Branch 6 (365→366) taken 24 times.
✗ Branch 7 (365→490) not taken.
✓ Branch 8 (366→367) taken 23 times.
✓ Branch 9 (366→368) taken 1 times.
✓ Branch 10 (369→370) taken 24 times.
✓ Branch 11 (369→371) taken 121 times.
✓ Branch 12 (371→372) taken 24 times.
✓ Branch 13 (371→374) taken 121 times.
✗ Branch 14 (490→491) not taken.
✗ Branch 15 (490→492) not taken.
✗ Branch 16 (494→495) not taken.
✗ Branch 17 (494→497) not taken.
193 ignoreUnusedReturnValue = fctDef && fctDef->attrs && fctDef->attrs->attrLst->hasAttr(ATTR_IGNORE_UNUSED_RETURN_VALUE);
279 }
280
281
2/2
✓ Branch 0 (375→376) taken 125 times.
✓ Branch 1 (375→378) taken 23 times.
148 if (!ignoreUnusedReturnValue)
282
1/2
✓ Branch 0 (376→377) taken 125 times.
✗ Branch 1 (376→499) not taken.
125 warnings.emplace_back(node->codeLoc, UNUSED_RETURN_VALUE, "The return value of the function call is unused");
283 }
284
285
2/4
✓ Branch 0 (378→379) taken 13485 times.
✗ Branch 1 (378→500) not taken.
✓ Branch 2 (379→380) taken 13485 times.
✗ Branch 3 (379→500) not taken.
13485 return ExprResult{node->setEvaluatedSymbolType(returnType, manIdx), anonymousSymbol};
286 }
287
288 8052 bool TypeChecker::visitOrdinaryFctCall(FctCallNode *node, std::string fqFunctionName) {
289
1/2
✓ Branch 0 (2→3) taken 8052 times.
✗ Branch 1 (2→106) not taken.
8052 FctCallNode::FctCallData &data = node->data.at(manIdx);
290 8052 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
291
292 // Check if this is a well-known ctor/fct call
293
2/2
✓ Branch 0 (4→5) taken 7982 times.
✓ Branch 1 (4→7) taken 70 times.
8052 if (node->functionNameFragments.size() == 1) {
294
1/2
✓ Branch 0 (5→6) taken 7982 times.
✗ Branch 1 (5→106) not taken.
7982 ensureLoadedRuntimeForTypeName(fqFunctionName);
295
1/2
✓ Branch 0 (6→7) taken 7982 times.
✗ Branch 1 (6→106) not taken.
7982 ensureLoadedRuntimeForFunctionName(fqFunctionName);
296 }
297
298 // Check if the type is generic (possible in case of ctor call)
299
1/2
✓ Branch 0 (7→8) taken 8052 times.
✗ Branch 1 (7→106) not taken.
8052 const QualType *genericType = rootScope->lookupGenericTypeStrict(fqFunctionName);
300
6/8
✓ Branch 0 (8→9) taken 1 times.
✓ Branch 1 (8→12) taken 8051 times.
✓ Branch 2 (9→10) taken 1 times.
✗ Branch 3 (9→106) not taken.
✓ Branch 4 (10→11) taken 1 times.
✗ Branch 5 (10→12) not taken.
✓ Branch 6 (13→14) taken 1 times.
✓ Branch 7 (13→19) taken 8051 times.
8052 if (genericType && typeMapping.contains(fqFunctionName)) {
301
1/2
✓ Branch 0 (14→15) taken 1 times.
✗ Branch 1 (14→106) not taken.
1 const QualType &replacementType = typeMapping.at(fqFunctionName);
302
2/4
✓ Branch 0 (15→16) taken 1 times.
✗ Branch 1 (15→106) not taken.
✓ Branch 2 (16→17) taken 1 times.
✗ Branch 3 (16→19) not taken.
1 if (replacementType.is(TY_STRUCT))
303
2/4
✓ Branch 0 (17→18) taken 1 times.
✗ Branch 1 (17→106) not taken.
✓ Branch 2 (18→19) taken 1 times.
✗ Branch 3 (18→106) not taken.
1 fqFunctionName = replacementType.getSubType();
304 }
305
306 // Check if the exported name registry contains that function name
307
1/2
✓ Branch 0 (19→20) taken 8052 times.
✗ Branch 1 (19→106) not taken.
8052 const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName);
308
2/2
✓ Branch 0 (20→21) taken 3 times.
✓ Branch 1 (20→29) taken 8049 times.
8052 if (!functionRegistryEntry) {
309
2/4
✓ Branch 0 (22→23) taken 3 times.
✗ Branch 1 (22→86) not taken.
✓ Branch 2 (23→24) taken 3 times.
✗ Branch 3 (23→84) not taken.
3 const std::string msg = "Function/procedure/struct '" + node->functionNameFragments.back() + "' could not be found";
310
1/2
✓ Branch 0 (25→26) taken 3 times.
✗ Branch 1 (25→87) not taken.
3 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, msg)
311 3 }
312 8049 const SymbolTableEntry *functionEntry = functionRegistryEntry->targetEntry;
313 8049 calleeParentScope = functionRegistryEntry->targetScope;
314
315 // Check if the target symbol is a struct -> this must be a constructor call
316
1/2
✓ Branch 0 (30→31) taken 8049 times.
✗ Branch 1 (30→106) not taken.
8049 std::string functionName = node->functionNameFragments.back();
317
7/10
✓ Branch 0 (31→32) taken 8049 times.
✗ Branch 1 (31→36) not taken.
✓ Branch 2 (32→33) taken 8049 times.
✗ Branch 3 (32→104) not taken.
✓ Branch 4 (33→34) taken 8049 times.
✗ Branch 5 (33→104) not taken.
✓ Branch 6 (34→35) taken 2028 times.
✓ Branch 7 (34→36) taken 6021 times.
✓ Branch 8 (37→38) taken 2028 times.
✓ Branch 9 (37→54) taken 6021 times.
8049 if (functionEntry != nullptr && functionEntry->getQualType().is(TY_STRUCT)) {
318 2028 callType = FctCallNode::FctCallType::TYPE_CTOR;
319
1/2
✓ Branch 0 (38→39) taken 2028 times.
✗ Branch 1 (38→104) not taken.
2028 functionName = CTOR_FUNCTION_NAME;
320
321 2028 const NameRegistryEntry *structRegistryEntry = functionRegistryEntry;
322 2028 const SymbolTableEntry *structEntry = functionEntry;
323
324 // Substantiate potentially generic this struct
325
2/4
✓ Branch 0 (39→40) taken 2028 times.
✗ Branch 1 (39→104) not taken.
✓ Branch 2 (40→41) taken 2028 times.
✗ Branch 3 (40→104) not taken.
2028 const Struct *thisStruct = structEntry->getQualType().getStruct(node, templateTypes);
326
2/2
✓ Branch 0 (41→42) taken 1 times.
✓ Branch 1 (41→51) taken 2027 times.
2028 if (!thisStruct) {
327
1/2
✓ Branch 0 (42→43) taken 1 times.
✗ Branch 1 (42→97) not taken.
1 const std::string signature = Struct::getSignature(structRegistryEntry->targetEntry->name, templateTypes);
328
2/4
✓ Branch 0 (43→44) taken 1 times.
✗ Branch 1 (43→92) not taken.
✓ Branch 2 (44→45) taken 1 times.
✗ Branch 3 (44→90) not taken.
1 const std::string errorMsg = "Could not find struct candidate for struct '" + signature + "'. Do the template types match?";
329
1/2
✓ Branch 0 (46→47) taken 1 times.
✗ Branch 1 (46→93) not taken.
1 SOFT_ERROR_BOOL(node, UNKNOWN_DATATYPE, errorMsg)
330 1 }
331
332 // Set the 'this' type of the function to the struct type
333
2/4
✓ Branch 0 (51→52) taken 2027 times.
✗ Branch 1 (51→98) not taken.
✓ Branch 2 (52→53) taken 2027 times.
✗ Branch 3 (52→98) not taken.
2027 thisType = structEntry->getQualType().getWithBodyScope(thisStruct->scope);
334 2027 calleeParentScope = thisStruct->scope;
335 }
336
337 // Attach the concrete template types to the 'this' type
338
7/8
✓ Branch 0 (54→55) taken 8048 times.
✗ Branch 1 (54→104) not taken.
✓ Branch 2 (55→56) taken 2027 times.
✓ Branch 3 (55→59) taken 6021 times.
✓ Branch 4 (57→58) taken 314 times.
✓ Branch 5 (57→59) taken 1713 times.
✓ Branch 6 (60→61) taken 314 times.
✓ Branch 7 (60→63) taken 7734 times.
8048 if (!thisType.is(TY_DYN) && !templateTypes.empty())
339
1/2
✓ Branch 0 (61→62) taken 314 times.
✗ Branch 1 (61→99) not taken.
314 thisType = thisType.getWithTemplateTypes(templateTypes);
340
341 // Map local arg types to imported types
342
5/8
✓ Branch 0 (63→64) taken 8048 times.
✗ Branch 1 (63→101) not taken.
✓ Branch 2 (64→65) taken 8048 times.
✗ Branch 3 (64→101) not taken.
✓ Branch 4 (65→66) taken 8048 times.
✗ Branch 5 (65→101) not taken.
✓ Branch 6 (71→67) taken 12079 times.
✓ Branch 7 (71→72) taken 8048 times.
20127 for (QualType &argType : args | std::views::keys)
343
1/2
✓ Branch 0 (68→69) taken 12079 times.
✗ Branch 1 (68→100) not taken.
12079 argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType);
344
345 // Map local template types to imported types
346
2/2
✓ Branch 0 (78→74) taken 601 times.
✓ Branch 1 (78→79) taken 8048 times.
8649 for (QualType &templateType : templateTypes)
347
1/2
✓ Branch 0 (75→76) taken 601 times.
✗ Branch 1 (75→102) not taken.
601 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
348
349 // Retrieve function object
350 8048 Scope *matchScope = calleeParentScope;
351
2/2
✓ Branch 0 (79→80) taken 8046 times.
✓ Branch 1 (79→104) taken 2 times.
8048 callee = FunctionManager::match(this, matchScope, functionName, data.thisType, data.args, templateTypes, false, node);
352
353 8046 return true;
354 8049 }
355
356 48 bool TypeChecker::visitFctPtrCall(const FctCallNode *node, const QualType &functionType) const {
357
1/2
✓ Branch 0 (2→3) taken 48 times.
✗ Branch 1 (2→75) not taken.
48 const FctCallNode::FctCallData &data = node->data.at(manIdx);
358 48 const auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
359
360 // Check if the given argument types match the type
361
1/2
✓ Branch 0 (3→4) taken 48 times.
✗ Branch 1 (3→75) not taken.
48 const QualTypeList expectedArgTypes = functionType.getFunctionParamTypes();
362
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→14) taken 48 times.
48 if (args.size() != expectedArgTypes.size())
363 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, "Expected and actual number of arguments do not match")
364
365 // Create resolver function, that always returns a nullptr
366 48 TypeMatcher::ResolverFct resolverFct = [](const std::string &) { return nullptr; };
367
368
2/2
✓ Branch 0 (41→16) taken 31 times.
✓ Branch 1 (41→42) taken 48 times.
79 for (size_t i = 0; i < args.size(); i++) {
369
1/2
✓ Branch 0 (16→17) taken 31 times.
✗ Branch 1 (16→71) not taken.
31 const QualType &actualType = args.at(i).first;
370
1/2
✓ Branch 0 (17→18) taken 31 times.
✗ Branch 1 (17→71) not taken.
31 const QualType &expectedType = expectedArgTypes.at(i);
371
2/4
✓ Branch 0 (19→20) taken 31 times.
✗ Branch 1 (19→68) not taken.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→34) taken 31 times.
31 if (TypeMapping tm; !TypeMatcher::matchRequestedToCandidateType(expectedType, actualType, tm, resolverFct, false))
372
1/16
✗ Branch 0 (21→22) not taken.
✗ Branch 1 (21→66) not taken.
✗ Branch 2 (22→23) not taken.
✗ Branch 3 (22→61) not taken.
✗ Branch 4 (23→24) not taken.
✗ Branch 5 (23→59) not taken.
✗ Branch 6 (24→25) not taken.
✗ Branch 7 (24→57) not taken.
✗ Branch 8 (25→26) not taken.
✗ Branch 9 (25→55) not taken.
✗ Branch 10 (26→27) not taken.
✗ Branch 11 (26→53) not taken.
✗ Branch 12 (27→28) not taken.
✗ Branch 13 (27→53) not taken.
✓ Branch 14 (36→37) taken 31 times.
✗ Branch 15 (36→39) not taken.
31 SOFT_ERROR_BOOL(node->argLst->args.at(i), REFERENCED_UNDEFINED_FUNCTION,
373 "Expected " + expectedType.getName(false) + " but got " + actualType.getName(false))
374 }
375 48 return true;
376 48 }
377
378 5406 bool TypeChecker::visitMethodCall(FctCallNode *node, Scope *structScope) {
379 5406 FctCallNode::FctCallData &data = node->data.at(manIdx);
380 5406 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
381
382 // Traverse through structs - the first fragment is already looked up and the last one is the method name
383
2/2
✓ Branch 0 (41→4) taken 688 times.
✓ Branch 1 (41→42) taken 5404 times.
6092 for (size_t i = 1; i < node->functionNameFragments.size() - 1; i++) {
384 688 const std::string &identifier = node->functionNameFragments.at(i);
385
386 // Retrieve field entry
387 688 SymbolTableEntry *fieldEntry = structScope->lookupStrict(identifier);
388
2/2
✓ Branch 0 (8→9) taken 1 times.
✓ Branch 1 (8→24) taken 687 times.
688 if (!fieldEntry) {
389
1/2
✓ Branch 0 (9→10) taken 1 times.
✗ Branch 1 (9→82) not taken.
1 std::stringstream errorMsg;
390
1/2
✓ Branch 0 (10→11) taken 1 times.
✗ Branch 1 (10→80) not taken.
1 errorMsg << "The type '";
391
3/6
✓ Branch 0 (11→12) taken 1 times.
✗ Branch 1 (11→75) not taken.
✓ Branch 2 (12→13) taken 1 times.
✗ Branch 3 (12→75) not taken.
✓ Branch 4 (13→14) taken 1 times.
✗ Branch 5 (13→73) not taken.
1 errorMsg << thisType.getBase().getName(false, true);
392
3/6
✓ Branch 0 (15→16) taken 1 times.
✗ Branch 1 (15→80) not taken.
✓ Branch 2 (16→17) taken 1 times.
✗ Branch 3 (16→80) not taken.
✓ Branch 4 (17→18) taken 1 times.
✗ Branch 5 (17→80) not taken.
1 errorMsg << "' does not have a member with the name '" << identifier << "'";
393
2/4
✓ Branch 0 (18→19) taken 1 times.
✗ Branch 1 (18→79) not taken.
✓ Branch 2 (19→20) taken 1 times.
✗ Branch 3 (19→77) not taken.
1 SOFT_ERROR_BOOL(node, ACCESS_TO_NON_EXISTING_MEMBER, errorMsg.str())
394 1 }
395
5/8
✓ Branch 0 (24→25) taken 687 times.
✗ Branch 1 (24→84) not taken.
✓ Branch 2 (25→26) taken 687 times.
✗ Branch 3 (25→84) not taken.
✓ Branch 4 (26→27) taken 687 times.
✗ Branch 5 (26→83) not taken.
✓ Branch 6 (27→28) taken 1 times.
✓ Branch 7 (27→34) taken 686 times.
687 if (!fieldEntry->getQualType().getBase().isOneOf({TY_STRUCT, TY_INTERFACE}))
396
3/6
✓ Branch 0 (28→29) taken 1 times.
✗ Branch 1 (28→89) not taken.
✓ Branch 2 (29→30) taken 1 times.
✗ Branch 3 (29→87) not taken.
✓ Branch 4 (30→31) taken 1 times.
✗ Branch 5 (30→85) not taken.
1 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS,
397 "Cannot call a method on '" + identifier + "', since it is no struct or interface")
398 686 fieldEntry->used = true;
399
400 // Get struct type and scope
401 686 thisType = fieldEntry->getQualType();
402
2/4
✓ Branch 0 (35→36) taken 686 times.
✗ Branch 1 (35→91) not taken.
✓ Branch 2 (36→37) taken 686 times.
✗ Branch 3 (36→91) not taken.
686 structScope = thisType.getBase().getBodyScope();
403
1/2
✗ Branch 0 (37→38) not taken.
✓ Branch 1 (37→39) taken 686 times.
686 assert(structScope != nullptr);
404 }
405
406
1/2
✗ Branch 0 (43→44) not taken.
✓ Branch 1 (43→51) taken 5404 times.
5404 if (thisType.is(TY_INTERFACE))
407 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS, "Cannot call a method on an interface")
408
409 // Map local arg types to imported types
410 5404 Scope *matchScope = calleeParentScope = structScope;
411
5/8
✓ Branch 0 (51→52) taken 5404 times.
✗ Branch 1 (51→99) not taken.
✓ Branch 2 (52→53) taken 5404 times.
✗ Branch 3 (52→99) not taken.
✓ Branch 4 (53→54) taken 5404 times.
✗ Branch 5 (53→99) not taken.
✓ Branch 6 (59→55) taken 3963 times.
✓ Branch 7 (59→60) taken 5404 times.
9367 for (QualType &argType : args | std::views::keys)
412
1/2
✓ Branch 0 (56→57) taken 3963 times.
✗ Branch 1 (56→98) not taken.
3963 argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType);
413
414 // Map local template types to imported types
415
1/2
✗ Branch 0 (66→62) not taken.
✓ Branch 1 (66→67) taken 5404 times.
5404 for (QualType &templateType : templateTypes)
416 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
417
418 // 'this' type
419
1/2
✓ Branch 0 (67→68) taken 5404 times.
✗ Branch 1 (67→102) not taken.
5404 thisType = thisType.autoDeReference();
420
1/2
✓ Branch 0 (68→69) taken 5404 times.
✗ Branch 1 (68→103) not taken.
5404 thisType = mapLocalTypeToImportedScopeType(calleeParentScope, thisType);
421
422 // Retrieve function object
423 5404 const std::string &functionName = node->functionNameFragments.back();
424 5404 callee = FunctionManager::match(this, matchScope, functionName, thisType, args, templateTypes, false, node);
425
426 5404 return true;
427 }
428
429 74 std::any TypeChecker::visitArrayInitialization(ArrayInitializationNode *node) {
430
5/6
✓ Branch 0 (2→3) taken 73 times.
✓ Branch 1 (2→5) taken 1 times.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 73 times.
✓ Branch 4 (7→8) taken 1 times.
✓ Branch 5 (7→18) taken 73 times.
74 if (!node->itemLst || node->itemLst->args.empty())
431
4/8
✓ Branch 0 (10→11) taken 1 times.
✗ Branch 1 (10→68) not taken.
✓ Branch 2 (11→12) taken 1 times.
✗ Branch 3 (11→66) not taken.
✓ Branch 4 (14→15) taken 1 times.
✗ Branch 5 (14→72) not taken.
✓ Branch 6 (15→16) taken 1 times.
✗ Branch 7 (15→72) not taken.
3 SOFT_ERROR_ER(node, ARRAY_SIZE_INVALID, "Array initializers must at least contain one value");
432 73 node->actualSize = node->itemLst->args.size();
433
434
1/2
✓ Branch 0 (19→20) taken 73 times.
✗ Branch 1 (19→97) not taken.
73 QualType actualItemType(TY_DYN);
435 // Check if all values have the same type
436
2/2
✓ Branch 0 (55→22) taken 491 times.
✓ Branch 1 (55→56) taken 72 times.
563 for (AssignExprNode *arg : node->itemLst->args) {
437
2/4
✓ Branch 0 (23→24) taken 491 times.
✗ Branch 1 (23→75) not taken.
✓ Branch 2 (24→25) taken 491 times.
✗ Branch 3 (24→73) not taken.
491 const QualType itemType = std::any_cast<ExprResult>(visit(arg)).type;
438
2/8
✓ Branch 0 (26→27) taken 491 times.
✗ Branch 1 (26→94) not taken.
✗ Branch 2 (27→28) not taken.
✓ Branch 3 (27→32) taken 491 times.
✗ Branch 4 (28→29) not taken.
✗ Branch 5 (28→77) not taken.
✗ Branch 6 (29→30) not taken.
✗ Branch 7 (29→77) not taken.
491 HANDLE_UNRESOLVED_TYPE_ER(itemType)
439
3/4
✓ Branch 0 (32→33) taken 491 times.
✗ Branch 1 (32→94) not taken.
✓ Branch 2 (33→34) taken 73 times.
✓ Branch 3 (33→35) taken 418 times.
491 if (actualItemType.is(TY_DYN)) // Perform type inference
440 73 actualItemType = itemType;
441
3/4
✓ Branch 0 (35→36) taken 418 times.
✗ Branch 1 (35→94) not taken.
✓ Branch 2 (36→37) taken 1 times.
✓ Branch 3 (36→52) taken 417 times.
418 else if (itemType != actualItemType) // Check if types are matching
442
8/16
✓ Branch 0 (37→38) taken 1 times.
✗ Branch 1 (37→91) not taken.
✓ Branch 2 (38→39) taken 1 times.
✗ Branch 3 (38→86) not taken.
✓ Branch 4 (39→40) taken 1 times.
✗ Branch 5 (39→84) not taken.
✓ Branch 6 (40→41) taken 1 times.
✗ Branch 7 (40→82) not taken.
✓ Branch 8 (41→42) taken 1 times.
✗ Branch 9 (41→80) not taken.
✓ Branch 10 (42→43) taken 1 times.
✗ Branch 11 (42→78) not taken.
✓ Branch 12 (48→49) taken 1 times.
✗ Branch 13 (48→93) not taken.
✓ Branch 14 (49→50) taken 1 times.
✗ Branch 15 (49→93) not taken.
1 SOFT_ERROR_ER(arg, ARRAY_ITEM_TYPE_NOT_MATCHING,
443 "All provided values have to be of the same data type. You provided " + actualItemType.getName(false) +
444 " and " + itemType.getName(false))
445 }
446
2/4
✓ Branch 0 (56→57) taken 72 times.
✗ Branch 1 (56→97) not taken.
✗ Branch 2 (57→58) not taken.
✓ Branch 3 (57→59) taken 72 times.
72 assert(!actualItemType.is(TY_DYN));
447
448
1/2
✓ Branch 0 (59→60) taken 72 times.
✗ Branch 1 (59→97) not taken.
72 const QualType arrayType = actualItemType.toArr(node, node->actualSize, true);
449
2/4
✓ Branch 0 (60→61) taken 72 times.
✗ Branch 1 (60→96) not taken.
✓ Branch 2 (61→62) taken 72 times.
✗ Branch 3 (61→96) not taken.
72 return ExprResult{node->setEvaluatedSymbolType(arrayType, manIdx)};
450 }
451
452 284 std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) {
453 // Retrieve struct name
454
1/2
✓ Branch 0 (2→3) taken 284 times.
✗ Branch 1 (2→264) not taken.
284 const auto [aliasedEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqStructName);
455
4/6
✓ Branch 0 (5→6) taken 1 times.
✓ Branch 1 (5→9) taken 283 times.
✓ Branch 2 (6→7) taken 1 times.
✗ Branch 3 (6→264) not taken.
✓ Branch 4 (7→8) taken 1 times.
✗ Branch 5 (7→264) not taken.
284 const std::string &structName = isAlias ? aliasedEntry->getQualType().getSubType() : node->fqStructName;
456
457 // Retrieve struct
458
1/2
✓ Branch 0 (10→11) taken 284 times.
✗ Branch 1 (10→264) not taken.
284 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(structName);
459
2/2
✓ Branch 0 (11→12) taken 1 times.
✓ Branch 1 (11→21) taken 283 times.
284 if (!registryEntry)
460
5/10
✓ Branch 0 (12→13) taken 1 times.
✗ Branch 1 (12→195) not taken.
✓ Branch 2 (13→14) taken 1 times.
✗ Branch 3 (13→193) not taken.
✓ Branch 4 (14→15) taken 1 times.
✗ Branch 5 (14→191) not taken.
✓ Branch 6 (17→18) taken 1 times.
✗ Branch 7 (17→197) not taken.
✓ Branch 8 (18→19) taken 1 times.
✗ Branch 9 (18→197) not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Cannot find struct '" + structName + "'")
461
2/4
✓ Branch 0 (21→22) taken 283 times.
✗ Branch 1 (21→24) not taken.
✓ Branch 2 (22→23) taken 283 times.
✗ Branch 3 (22→24) not taken.
283 assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr);
462 283 SymbolTableEntry *structEntry = registryEntry->targetEntry;
463
464 // Check visibility
465
9/12
✓ Branch 0 (25→26) taken 283 times.
✗ Branch 1 (25→264) not taken.
✓ Branch 2 (26→27) taken 283 times.
✗ Branch 3 (26→264) not taken.
✓ Branch 4 (27→28) taken 58 times.
✓ Branch 5 (27→31) taken 225 times.
✓ Branch 6 (28→29) taken 58 times.
✗ Branch 7 (28→264) not taken.
✓ Branch 8 (29→30) taken 1 times.
✓ Branch 9 (29→31) taken 57 times.
✓ Branch 10 (32→33) taken 1 times.
✓ Branch 11 (32→42) taken 282 times.
283 if (!structEntry->getQualType().isPublic() && structEntry->scope->isImportedBy(currentScope))
466
5/10
✓ Branch 0 (33→34) taken 1 times.
✗ Branch 1 (33→202) not taken.
✓ Branch 2 (34→35) taken 1 times.
✗ Branch 3 (34→200) not taken.
✓ Branch 4 (35→36) taken 1 times.
✗ Branch 5 (35→198) not taken.
✓ Branch 6 (38→39) taken 1 times.
✗ Branch 7 (38→204) not taken.
✓ Branch 8 (39→40) taken 1 times.
✗ Branch 9 (39→204) not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Struct '" + structName + "' has insufficient visibility")
467
468 // Get struct type
469
1/2
✓ Branch 0 (42→43) taken 282 times.
✗ Branch 1 (42→264) not taken.
282 QualType structType = structEntry->getQualType();
470
471 // Get the concrete template types
472 282 QualTypeList concreteTemplateTypes;
473
2/2
✓ Branch 0 (43→44) taken 1 times.
✓ Branch 1 (43→63) taken 281 times.
282 if (isAlias) {
474 // Retrieve concrete template types from type alias
475
3/6
✓ Branch 0 (44→45) taken 1 times.
✗ Branch 1 (44→262) not taken.
✓ Branch 2 (45→46) taken 1 times.
✗ Branch 3 (45→262) not taken.
✓ Branch 4 (46→47) taken 1 times.
✗ Branch 5 (46→262) not taken.
1 concreteTemplateTypes = aliasedEntry->getQualType().getTemplateTypes();
476 // Check if the aliased type specified template types and the struct instantiation does
477
3/6
✓ Branch 0 (48→49) taken 1 times.
✗ Branch 1 (48→51) not taken.
✗ Branch 2 (49→50) not taken.
✓ Branch 3 (49→51) taken 1 times.
✗ Branch 4 (52→53) not taken.
✓ Branch 5 (52→63) taken 1 times.
1 if (!concreteTemplateTypes.empty() && node->templateTypeLst)
478 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
479 }
480
481
2/2
✓ Branch 0 (63→64) taken 15 times.
✓ Branch 1 (63→96) taken 267 times.
282 if (node->templateTypeLst) {
482
1/2
✓ Branch 0 (65→66) taken 15 times.
✗ Branch 1 (65→262) not taken.
15 concreteTemplateTypes.reserve(node->templateTypeLst->dataTypes.size());
483
2/2
✓ Branch 0 (94→68) taken 23 times.
✓ Branch 1 (94→95) taken 15 times.
38 for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) {
484
2/4
✓ Branch 0 (69→70) taken 23 times.
✗ Branch 1 (69→214) not taken.
✓ Branch 2 (70→71) taken 23 times.
✗ Branch 3 (70→212) not taken.
23 auto concreteType = std::any_cast<QualType>(visit(dataType));
485
2/8
✓ Branch 0 (72→73) taken 23 times.
✗ Branch 1 (72→223) not taken.
✗ Branch 2 (73→74) not taken.
✓ Branch 3 (73→78) taken 23 times.
✗ Branch 4 (74→75) not taken.
✗ Branch 5 (74→215) not taken.
✗ Branch 6 (75→76) not taken.
✗ Branch 7 (75→215) not taken.
23 HANDLE_UNRESOLVED_TYPE_ER(concreteType)
486 // Check if generic type
487
2/4
✓ Branch 0 (78→79) taken 23 times.
✗ Branch 1 (78→223) not taken.
✗ Branch 2 (79→80) not taken.
✓ Branch 3 (79→90) taken 23 times.
23 if (concreteType.is(TY_GENERIC))
488 SOFT_ERROR_ER(dataType, EXPECTED_NON_GENERIC_TYPE, "Struct instantiations may only take concrete template types")
489
1/2
✓ Branch 0 (90→91) taken 23 times.
✗ Branch 1 (90→223) not taken.
23 concreteTemplateTypes.push_back(concreteType);
490 }
491 }
492
493 // Get the struct instance
494
2/4
✓ Branch 0 (96→97) taken 282 times.
✗ Branch 1 (96→262) not taken.
✓ Branch 2 (97→98) taken 282 times.
✗ Branch 3 (97→262) not taken.
282 Struct *spiceStruct = node->instantiatedStructs.at(manIdx) = structType.getStructAndAdjustType(node, concreteTemplateTypes);
495
1/2
✗ Branch 0 (98→99) not taken.
✓ Branch 1 (98→110) taken 282 times.
282 if (!spiceStruct)
496 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + spiceStruct->getSignature() + "' could not be found")
497
498 // Struct instantiation for an inheriting struct is forbidden, because the vtable needs to be initialized and this is done in
499 // the ctor of the struct, which is never called in case of struct instantiation
500
2/2
✓ Branch 0 (111→112) taken 1 times.
✓ Branch 1 (111→122) taken 281 times.
282 if (!spiceStruct->interfaceTypes.empty())
501
4/8
✓ Branch 0 (114→115) taken 1 times.
✗ Branch 1 (114→237) not taken.
✓ Branch 2 (115→116) taken 1 times.
✗ Branch 3 (115→235) not taken.
✓ Branch 4 (118→119) taken 1 times.
✗ Branch 5 (118→241) not taken.
✓ Branch 6 (119→120) taken 1 times.
✗ Branch 7 (119→241) not taken.
3 SOFT_ERROR_ER(node, INVALID_STRUCT_INSTANTIATION, "Struct instantiations for inheriting structs are forbidden")
502
503 // Check if the number of fields matches
504
2/2
✓ Branch 0 (122→123) taken 267 times.
✓ Branch 1 (122→166) taken 14 times.
281 if (node->fieldLst) { // Check if any fields are passed. Empty braces are also allowed
505
2/2
✓ Branch 0 (125→126) taken 1 times.
✓ Branch 1 (125→136) taken 266 times.
267 if (spiceStruct->fieldTypes.size() != node->fieldLst->args.size())
506
4/8
✓ Branch 0 (128→129) taken 1 times.
✗ Branch 1 (128→244) not taken.
✓ Branch 2 (129→130) taken 1 times.
✗ Branch 3 (129→242) not taken.
✓ Branch 4 (132→133) taken 1 times.
✗ Branch 5 (132→248) not taken.
✓ Branch 6 (133→134) taken 1 times.
✗ Branch 7 (133→248) not taken.
3 SOFT_ERROR_ER(node->fieldLst, NUMBER_OF_FIELDS_NOT_MATCHING,
507 "You've passed too less/many field values. Pass either none or all of them")
508
509 // Check if the field types are matching
510 266 const size_t fieldCount = spiceStruct->fieldTypes.size();
511
1/2
✓ Branch 0 (137→138) taken 266 times.
✗ Branch 1 (137→262) not taken.
266 const size_t explicitFieldsStartIdx = spiceStruct->scope->getFieldCount() - fieldCount;
512
2/2
✓ Branch 0 (165→139) taken 387 times.
✓ Branch 1 (165→178) taken 265 times.
652 for (size_t i = 0; i < node->fieldLst->args.size(); i++) {
513 // Get actual type
514
1/2
✓ Branch 0 (139→140) taken 387 times.
✗ Branch 1 (139→253) not taken.
387 AssignExprNode *assignExpr = node->fieldLst->args.at(i);
515
2/4
✓ Branch 0 (140→141) taken 387 times.
✗ Branch 1 (140→251) not taken.
✓ Branch 2 (141→142) taken 387 times.
✗ Branch 3 (141→249) not taken.
387 auto fieldResult = std::any_cast<ExprResult>(visit(assignExpr));
516
2/8
✓ Branch 0 (143→144) taken 387 times.
✗ Branch 1 (143→253) not taken.
✗ Branch 2 (144→145) not taken.
✓ Branch 3 (144→149) taken 387 times.
✗ Branch 4 (145→146) not taken.
✗ Branch 5 (145→252) not taken.
✗ Branch 6 (146→147) not taken.
✗ Branch 7 (146→252) not taken.
387 HANDLE_UNRESOLVED_TYPE_ER(fieldResult.type)
517 // Get expected type
518
1/2
✗ Branch 0 (149→150) not taken.
✓ Branch 1 (149→151) taken 387 times.
387 SymbolTableEntry *expectedField = spiceStruct->scope->lookupField(explicitFieldsStartIdx + i);
519
1/2
✗ Branch 0 (154→155) not taken.
✓ Branch 1 (154→156) taken 387 times.
387 assert(expectedField != nullptr);
520
1/2
✓ Branch 0 (156→157) taken 387 times.
✗ Branch 1 (156→253) not taken.
387 const ExprResult expected = {expectedField->getQualType(), expectedField};
521
1/2
✓ Branch 0 (157→158) taken 387 times.
✗ Branch 1 (157→253) not taken.
387 const bool rhsIsImmediate = assignExpr->hasCompileTimeValue();
522
523 // Check if actual type matches expected type
524
2/2
✓ Branch 0 (158→159) taken 386 times.
✓ Branch 1 (158→253) taken 1 times.
387 (void)opRuleManager.getFieldAssignResultType(assignExpr, expected, fieldResult, rhsIsImmediate, true);
525
526 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
527
4/4
✓ Branch 0 (159→160) taken 99 times.
✓ Branch 1 (159→163) taken 287 times.
✓ Branch 2 (160→161) taken 3 times.
✓ Branch 3 (160→163) taken 96 times.
386 if (fieldResult.entry != nullptr && fieldResult.entry->anonymous) {
528
1/2
✓ Branch 0 (161→162) taken 3 times.
✗ Branch 1 (161→253) not taken.
3 currentScope->symbolTable.deleteAnonymous(fieldResult.entry->name);
529 3 fieldResult.entry = nullptr;
530 }
531 }
532 } else {
533
2/4
✓ Branch 0 (166→167) taken 14 times.
✗ Branch 1 (166→262) not taken.
✗ Branch 2 (167→168) not taken.
✓ Branch 3 (167→178) taken 14 times.
57 if (std::ranges::any_of(spiceStruct->fieldTypes, [](const QualType &fieldType) { return fieldType.isRef(); }))
534 SOFT_ERROR_ER(node, REFERENCE_WITHOUT_INITIALIZER,
535 "The struct takes at least one reference field. You need to instantiate it with all fields.")
536 }
537
538 // Update type of struct entry
539
1/2
✓ Branch 0 (178→179) taken 279 times.
✗ Branch 1 (178→262) not taken.
279 structEntry->updateType(structType, true);
540
541 // Add anonymous symbol to keep track of dtor call, if non-trivially destructible
542 279 SymbolTableEntry *anonymousEntry = nullptr;
543
3/4
✓ Branch 0 (179→180) taken 279 times.
✗ Branch 1 (179→262) not taken.
✓ Branch 2 (180→181) taken 21 times.
✓ Branch 3 (180→183) taken 258 times.
279 if (!structType.isTriviallyDestructible(node))
544
1/2
✓ Branch 0 (181→182) taken 21 times.
✗ Branch 1 (181→262) not taken.
21 anonymousEntry = currentScope->symbolTable.insertAnonymous(structType, node);
545
546 // Remove public qualifier to not have public local variables
547 279 structType.getQualifiers().isPublic = false;
548
549
2/4
✓ Branch 0 (184→185) taken 279 times.
✗ Branch 1 (184→261) not taken.
✓ Branch 2 (185→186) taken 279 times.
✗ Branch 3 (185→261) not taken.
279 return ExprResult{node->setEvaluatedSymbolType(structType, manIdx), anonymousEntry};
550 282 }
551
552 12 std::any TypeChecker::visitLambdaFunc(LambdaFuncNode *node) {
553 // Check if all control paths in the lambda body return
554 12 bool returnsOnAllControlPaths = true;
555
3/4
✓ Branch 0 (2→3) taken 12 times.
✗ Branch 1 (2→186) not taken.
✓ Branch 2 (3→4) taken 1 times.
✓ Branch 3 (3→14) taken 11 times.
12 if (!node->returnsOnAllControlPaths(&returnsOnAllControlPaths))
556
4/8
✓ Branch 0 (6→7) taken 1 times.
✗ Branch 1 (6→112) not taken.
✓ Branch 2 (7→8) taken 1 times.
✗ Branch 3 (7→110) not taken.
✓ Branch 4 (10→11) taken 1 times.
✗ Branch 5 (10→116) not taken.
✓ Branch 6 (11→12) taken 1 times.
✗ Branch 7 (11→116) not taken.
3 SOFT_ERROR_ER(node, MISSING_RETURN_STMT, "Not all control paths of this lambda function have a return statement")
557
558 // Change to function scope
559
2/4
✓ Branch 0 (14→15) taken 11 times.
✗ Branch 1 (14→119) not taken.
✓ Branch 2 (15→16) taken 11 times.
✗ Branch 3 (15→117) not taken.
11 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
560
1/2
✓ Branch 0 (17→18) taken 11 times.
✗ Branch 1 (17→120) not taken.
11 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
561
562 // Visit return type
563
2/4
✓ Branch 0 (18→19) taken 11 times.
✗ Branch 1 (18→123) not taken.
✓ Branch 2 (19→20) taken 11 times.
✗ Branch 3 (19→121) not taken.
11 const auto returnType = std::any_cast<QualType>(visit(node->returnType));
564
2/8
✓ Branch 0 (21→22) taken 11 times.
✗ Branch 1 (21→184) not taken.
✗ Branch 2 (22→23) not taken.
✓ Branch 3 (22→27) taken 11 times.
✗ Branch 4 (23→24) not taken.
✗ Branch 5 (23→124) not taken.
✗ Branch 6 (24→25) not taken.
✗ Branch 7 (24→124) not taken.
11 HANDLE_UNRESOLVED_TYPE_ER(returnType)
565
3/4
✓ Branch 0 (27→28) taken 11 times.
✗ Branch 1 (27→184) not taken.
✓ Branch 2 (28→29) taken 1 times.
✓ Branch 3 (28→39) taken 10 times.
11 if (returnType.is(TY_DYN))
566
4/8
✓ Branch 0 (31→32) taken 1 times.
✗ Branch 1 (31→127) not taken.
✓ Branch 2 (32→33) taken 1 times.
✗ Branch 3 (32→125) not taken.
✓ Branch 4 (35→36) taken 1 times.
✗ Branch 5 (35→131) not taken.
✓ Branch 6 (36→37) taken 1 times.
✗ Branch 7 (36→131) not taken.
3 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
567
568 // Set the type of the result variable
569
1/2
✓ Branch 0 (41→42) taken 10 times.
✗ Branch 1 (41→134) not taken.
30 SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
570
1/2
✗ Branch 0 (47→48) not taken.
✓ Branch 1 (47→49) taken 10 times.
10 assert(resultVarEntry != nullptr);
571
1/2
✓ Branch 0 (49→50) taken 10 times.
✗ Branch 1 (49→184) not taken.
10 resultVarEntry->updateType(returnType, true);
572 10 resultVarEntry->used = true;
573
574 // Visit parameters
575 10 QualTypeList paramTypes;
576 10 ParamList paramList;
577
2/2
✓ Branch 0 (50→51) taken 6 times.
✓ Branch 1 (50→72) taken 4 times.
10 if (node->hasParams) {
578 // Visit param list to retrieve the param names
579
2/4
✓ Branch 0 (51→52) taken 6 times.
✗ Branch 1 (51→140) not taken.
✓ Branch 2 (52→53) taken 6 times.
✗ Branch 3 (52→138) not taken.
6 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
580
2/2
✓ Branch 0 (69→56) taken 10 times.
✓ Branch 1 (69→70) taken 6 times.
16 for (const auto &[name, qualType, isOptional] : namedParamList) {
581
1/2
✗ Branch 0 (57→58) not taken.
✓ Branch 1 (57→65) taken 10 times.
10 if (isOptional)
582 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
583
584
1/2
✓ Branch 0 (65→66) taken 10 times.
✗ Branch 1 (65→148) not taken.
10 paramTypes.push_back(qualType);
585
1/2
✓ Branch 0 (66→67) taken 10 times.
✗ Branch 1 (66→147) not taken.
10 paramList.push_back({qualType, isOptional});
586 }
587 6 }
588
589 // Visit lambda body
590
2/2
✓ Branch 0 (72→73) taken 9 times.
✓ Branch 1 (72→152) taken 1 times.
10 visit(node->body);
591
592 // Leave function body scope
593
1/2
✓ Branch 0 (74→75) taken 9 times.
✗ Branch 1 (74→180) not taken.
9 scopeHandle.leaveScopeEarly();
594
595 // Prepare type of function
596
1/2
✓ Branch 0 (75→76) taken 9 times.
✗ Branch 1 (75→153) not taken.
9 const QualType functionType = QualType(TY_FUNCTION)
597
1/2
✓ Branch 0 (76→77) taken 9 times.
✗ Branch 1 (76→153) not taken.
9 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
598
1/2
✓ Branch 0 (78→79) taken 9 times.
✗ Branch 1 (78→153) not taken.
9 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
599
600 // Create function object
601
2/4
✓ Branch 0 (79→80) taken 9 times.
✗ Branch 1 (79→157) not taken.
✓ Branch 2 (80→81) taken 9 times.
✗ Branch 3 (80→155) not taken.
9 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
602
4/8
✓ Branch 0 (83→84) taken 9 times.
✗ Branch 1 (83→166) not taken.
✓ Branch 2 (84→85) taken 9 times.
✗ Branch 3 (84→163) not taken.
✓ Branch 4 (85→86) taken 9 times.
✗ Branch 5 (85→162) not taken.
✓ Branch 6 (87→88) taken 9 times.
✗ Branch 7 (87→158) not taken.
9 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
603
1/2
✓ Branch 0 (93→94) taken 9 times.
✗ Branch 1 (93→178) not taken.
9 node->manifestations.at(manIdx).bodyScope = bodyScope;
604
3/6
✓ Branch 0 (94→95) taken 9 times.
✗ Branch 1 (94→175) not taken.
✓ Branch 2 (95→96) taken 9 times.
✗ Branch 3 (95→173) not taken.
✓ Branch 4 (96→97) taken 9 times.
✗ Branch 5 (96→171) not taken.
9 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
605
606 // Check special requirements if this is an async lambda
607
1/2
✓ Branch 0 (100→101) taken 9 times.
✗ Branch 1 (100→178) not taken.
9 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
608
609
2/4
✓ Branch 0 (101→102) taken 9 times.
✗ Branch 1 (101→177) not taken.
✓ Branch 2 (102→103) taken 9 times.
✗ Branch 3 (102→177) not taken.
9 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
610 13 }
611
612 28 std::any TypeChecker::visitLambdaProc(LambdaProcNode *node) {
613 // Mark unreachable statements
614 28 bool doSetPredecessorsUnreachable = true;
615
1/2
✓ Branch 0 (2→3) taken 28 times.
✗ Branch 1 (2→123) not taken.
28 node->returnsOnAllControlPaths(&doSetPredecessorsUnreachable);
616
617 // Change to function scope
618
2/4
✓ Branch 0 (3→4) taken 28 times.
✗ Branch 1 (3→71) not taken.
✓ Branch 2 (4→5) taken 28 times.
✗ Branch 3 (4→69) not taken.
28 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
619
1/2
✓ Branch 0 (6→7) taken 28 times.
✗ Branch 1 (6→72) not taken.
28 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
620
621 // Visit parameters
622 28 QualTypeList paramTypes;
623 28 ParamList paramList;
624
2/2
✓ Branch 0 (7→8) taken 7 times.
✓ Branch 1 (7→29) taken 21 times.
28 if (node->hasParams) {
625 // Visit param list to retrieve the param names
626
2/4
✓ Branch 0 (8→9) taken 7 times.
✗ Branch 1 (8→75) not taken.
✓ Branch 2 (9→10) taken 7 times.
✗ Branch 3 (9→73) not taken.
7 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
627
2/2
✓ Branch 0 (26→13) taken 11 times.
✓ Branch 1 (26→27) taken 7 times.
18 for (const auto &[_, qualType, isOptional] : namedParamList) {
628
2/2
✓ Branch 0 (14→15) taken 1 times.
✓ Branch 1 (14→22) taken 10 times.
11 if (isOptional)
629
2/4
✓ Branch 0 (17→18) taken 1 times.
✗ Branch 1 (17→78) not taken.
✓ Branch 2 (18→19) taken 1 times.
✗ Branch 3 (18→76) not taken.
2 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
630
631
1/2
✓ Branch 0 (22→23) taken 11 times.
✗ Branch 1 (22→83) not taken.
11 paramTypes.push_back(qualType);
632
1/2
✓ Branch 0 (23→24) taken 11 times.
✗ Branch 1 (23→82) not taken.
11 paramList.push_back({qualType, isOptional});
633 }
634 7 }
635
636 // Visit lambda body
637
1/2
✓ Branch 0 (29→30) taken 28 times.
✗ Branch 1 (29→87) not taken.
28 visit(node->body);
638
639 // Leave function body scope
640
1/2
✓ Branch 0 (31→32) taken 28 times.
✗ Branch 1 (31→117) not taken.
28 scopeHandle.leaveScopeEarly();
641
642 // Prepare type of function
643
1/2
✓ Branch 0 (32→33) taken 28 times.
✗ Branch 1 (32→89) not taken.
28 const QualType functionType = QualType(TY_PROCEDURE)
644
2/4
✓ Branch 0 (33→34) taken 28 times.
✗ Branch 1 (33→88) not taken.
✓ Branch 2 (34→35) taken 28 times.
✗ Branch 3 (34→88) not taken.
28 .getWithFunctionParamAndReturnTypes(QualType(TY_DYN), paramTypes)
645
1/2
✓ Branch 0 (36→37) taken 28 times.
✗ Branch 1 (36→88) not taken.
28 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
646
647 // Create function object
648
2/4
✓ Branch 0 (37→38) taken 28 times.
✗ Branch 1 (37→93) not taken.
✓ Branch 2 (38→39) taken 28 times.
✗ Branch 3 (38→91) not taken.
28 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
649
5/10
✓ Branch 0 (41→42) taken 28 times.
✗ Branch 1 (41→103) not taken.
✓ Branch 2 (42→43) taken 28 times.
✗ Branch 3 (42→100) not taken.
✓ Branch 4 (43→44) taken 28 times.
✗ Branch 5 (43→99) not taken.
✓ Branch 6 (44→45) taken 28 times.
✗ Branch 7 (44→98) not taken.
✓ Branch 8 (46→47) taken 28 times.
✗ Branch 9 (46→94) not taken.
28 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), QualType(TY_DYN), paramList, {}, node);
650
1/2
✓ Branch 0 (52→53) taken 28 times.
✗ Branch 1 (52→115) not taken.
28 node->manifestations.at(manIdx).bodyScope = bodyScope;
651
3/6
✓ Branch 0 (53→54) taken 28 times.
✗ Branch 1 (53→112) not taken.
✓ Branch 2 (54→55) taken 28 times.
✗ Branch 3 (54→110) not taken.
✓ Branch 4 (55→56) taken 28 times.
✗ Branch 5 (55→108) not taken.
28 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
652
653 // Check special requirements if this is an async lambda
654
1/2
✓ Branch 0 (59→60) taken 28 times.
✗ Branch 1 (59→115) not taken.
28 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
655
656
2/4
✓ Branch 0 (60→61) taken 28 times.
✗ Branch 1 (60→114) not taken.
✓ Branch 2 (61→62) taken 28 times.
✗ Branch 3 (61→114) not taken.
56 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
657 28 }
658
659 1 std::any TypeChecker::visitLambdaExpr(LambdaExprNode *node) {
660 // Change to function scope
661
2/4
✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→90) not taken.
✓ Branch 2 (3→4) taken 1 times.
✗ Branch 3 (3→88) not taken.
1 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
662
1/2
✓ Branch 0 (5→6) taken 1 times.
✗ Branch 1 (5→91) not taken.
1 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
663
664 // Visit parameters
665 1 QualTypeList paramTypes;
666 1 ParamList paramList;
667
1/2
✓ Branch 0 (6→7) taken 1 times.
✗ Branch 1 (6→28) not taken.
1 if (node->hasParams) {
668 // Visit param list to retrieve the param names
669
2/4
✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→94) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→92) not taken.
1 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
670
2/2
✓ Branch 0 (25→12) taken 2 times.
✓ Branch 1 (25→26) taken 1 times.
3 for (const NamedParam &param : namedParamList) {
671
1/2
✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→21) taken 2 times.
2 if (param.isOptional)
672 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
673
674
1/2
✓ Branch 0 (21→22) taken 2 times.
✗ Branch 1 (21→102) not taken.
2 paramTypes.push_back(param.qualType);
675
1/2
✓ Branch 0 (22→23) taken 2 times.
✗ Branch 1 (22→101) not taken.
2 paramList.push_back({param.qualType, param.isOptional});
676 }
677 1 }
678
679 // Visit lambda expression
680
2/4
✓ Branch 0 (28→29) taken 1 times.
✗ Branch 1 (28→108) not taken.
✓ Branch 2 (29→30) taken 1 times.
✗ Branch 3 (29→106) not taken.
1 const QualType returnType = std::any_cast<ExprResult>(visit(node->lambdaExpr)).type;
681
2/8
✓ Branch 0 (31→32) taken 1 times.
✗ Branch 1 (31→145) not taken.
✗ Branch 2 (32→33) not taken.
✓ Branch 3 (32→37) taken 1 times.
✗ Branch 4 (33→34) not taken.
✗ Branch 5 (33→110) not taken.
✗ Branch 6 (34→35) not taken.
✗ Branch 7 (34→110) not taken.
1 HANDLE_UNRESOLVED_TYPE_ER(returnType)
682
2/4
✓ Branch 0 (37→38) taken 1 times.
✗ Branch 1 (37→145) not taken.
✗ Branch 2 (38→39) not taken.
✓ Branch 3 (38→49) taken 1 times.
1 if (returnType.is(TY_DYN))
683 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
684
685 // Leave function body scope
686
1/2
✓ Branch 0 (49→50) taken 1 times.
✗ Branch 1 (49→145) not taken.
1 scopeHandle.leaveScopeEarly();
687
688 // Prepare type of function
689
2/4
✓ Branch 0 (50→51) taken 1 times.
✗ Branch 1 (50→145) not taken.
✗ Branch 2 (51→52) not taken.
✓ Branch 3 (51→53) taken 1 times.
1 const SuperType superType = returnType.is(TY_DYN) ? TY_PROCEDURE : TY_FUNCTION;
690
1/2
✓ Branch 0 (54→55) taken 1 times.
✗ Branch 1 (54→118) not taken.
1 const QualType functionType = QualType(superType)
691
1/2
✓ Branch 0 (55→56) taken 1 times.
✗ Branch 1 (55→118) not taken.
1 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
692
1/2
✓ Branch 0 (57→58) taken 1 times.
✗ Branch 1 (57→118) not taken.
1 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
693
694 // Create function object
695
2/4
✓ Branch 0 (58→59) taken 1 times.
✗ Branch 1 (58→122) not taken.
✓ Branch 2 (59→60) taken 1 times.
✗ Branch 3 (59→120) not taken.
1 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
696
4/8
✓ Branch 0 (62→63) taken 1 times.
✗ Branch 1 (62→131) not taken.
✓ Branch 2 (63→64) taken 1 times.
✗ Branch 3 (63→128) not taken.
✓ Branch 4 (64→65) taken 1 times.
✗ Branch 5 (64→127) not taken.
✓ Branch 6 (66→67) taken 1 times.
✗ Branch 7 (66→123) not taken.
1 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
697
1/2
✓ Branch 0 (72→73) taken 1 times.
✗ Branch 1 (72→143) not taken.
1 node->manifestations.at(manIdx).bodyScope = bodyScope;
698
3/6
✓ Branch 0 (73→74) taken 1 times.
✗ Branch 1 (73→140) not taken.
✓ Branch 2 (74→75) taken 1 times.
✗ Branch 3 (74→138) not taken.
✓ Branch 4 (75→76) taken 1 times.
✗ Branch 5 (75→136) not taken.
1 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
699
700
2/4
✓ Branch 0 (79→80) taken 1 times.
✗ Branch 1 (79→142) not taken.
✓ Branch 2 (80→81) taken 1 times.
✗ Branch 3 (80→142) not taken.
1 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
701 1 }
702
703 } // namespace spice::compiler
704