GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeCheckerImplicit.cpp
Date: 2025-02-05 01:09:36
Exec Total Coverage
Lines: 233 236 98.7%
Functions: 15 15 100.0%
Branches: 324 536 60.4%

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/ASTBuilder.h>
7 #include <ast/ASTNodes.h>
8 #include <global/GlobalResourceManager.h>
9 #include <symboltablebuilder/SymbolTableBuilder.h>
10 #include <typechecker/TypeMatcher.h>
11
12 namespace spice::compiler {
13
14 static const char *const FCT_NAME_DEALLOC = "sDealloc";
15
16 /**
17 * Create a default struct method
18 * Checks if the given struct scope already has a user-defined constructor and creates a default one if not.
19 *
20 * @param spiceStruct Struct instance
21 * @param entryName Name of the symbol table entry
22 * @param name Name of the method to create
23 * @param params Parameter types of the method
24 */
25 280 void TypeChecker::createDefaultStructMethod(const Struct &spiceStruct, const std::string &entryName, const std::string &name,
26 const ParamList &params) const {
27 280 Scope *structScope = spiceStruct.scope;
28 280 ASTNode *node = spiceStruct.declNode;
29 280 const SymbolTableEntry *structEntry = spiceStruct.entry;
30
1/2
✓ Branch 0 (2→3) taken 280 times.
✗ Branch 1 (2→68) not taken.
280 const QualType &structType = structEntry->getQualType();
31
3/6
✓ Branch 0 (3→4) taken 280 times.
✗ Branch 1 (3→44) not taken.
✓ Branch 2 (4→5) taken 280 times.
✗ Branch 3 (4→44) not taken.
✓ Branch 4 (5→6) taken 280 times.
✗ Branch 5 (5→42) not taken.
280 const std::string fqFctName = structType.getSubType() + MEMBER_ACCESS_TOKEN + name;
32
33 // Procedure type
34
1/2
✓ Branch 0 (7→8) taken 280 times.
✗ Branch 1 (7→66) not taken.
280 QualType procedureType(TY_PROCEDURE);
35
1/2
✓ Branch 0 (8→9) taken 280 times.
✗ Branch 1 (8→66) not taken.
280 procedureType.makePublic(); // Always public
36
37 // Insert symbol for function into the symbol table
38
1/2
✓ Branch 0 (9→10) taken 280 times.
✗ Branch 1 (9→66) not taken.
280 SymbolTableEntry *procEntry = structScope->insert(entryName, structEntry->declNode);
39
1/2
✓ Branch 0 (12→13) taken 280 times.
✗ Branch 1 (12→66) not taken.
280 procEntry->updateType(procedureType, true);
40
41 // Add to external name registry
42
1/2
✓ Branch 0 (13→14) taken 280 times.
✗ Branch 1 (13→66) not taken.
280 sourceFile->addNameRegistryEntry(fqFctName, TY_PROCEDURE, procEntry, structScope, true);
43
44 // Create the default method
45
1/2
✓ Branch 0 (14→15) taken 280 times.
✗ Branch 1 (14→66) not taken.
280 const std::vector<GenericType> templateTypes = spiceStruct.templateTypes;
46
1/2
✓ Branch 0 (15→16) taken 280 times.
✗ Branch 1 (15→64) not taken.
280 const QualType returnType(TY_DYN);
47
3/6
✓ Branch 0 (16→17) taken 280 times.
✗ Branch 1 (16→51) not taken.
✓ Branch 2 (17→18) taken 280 times.
✗ Branch 3 (17→48) not taken.
✓ Branch 4 (18→19) taken 280 times.
✗ Branch 5 (18→45) not taken.
280 Function defaultMethod(name, procEntry, structType, returnType, params, templateTypes, structEntry->declNode);
48 280 defaultMethod.implicitDefault = true;
49
50 // Create function scope
51
2/4
✓ Branch 0 (23→24) taken 280 times.
✗ Branch 1 (23→54) not taken.
✓ Branch 2 (24→25) taken 280 times.
✗ Branch 3 (24→52) not taken.
280 Scope *procScope = structScope->createChildScope(defaultMethod.getSignature(false), ScopeType::FUNC_PROC_BODY, &node->codeLoc);
52 280 defaultMethod.bodyScope = procScope;
53
54 // Create 'this' symbol in the function scope
55
1/2
✓ Branch 0 (28→29) taken 280 times.
✗ Branch 1 (28→57) not taken.
840 SymbolTableEntry *thisEntry = procScope->insert(THIS_VARIABLE_NAME, node);
56
2/4
✓ Branch 0 (34→35) taken 280 times.
✗ Branch 1 (34→61) not taken.
✓ Branch 2 (35→36) taken 280 times.
✗ Branch 3 (35→61) not taken.
280 thisEntry->updateType(structType.toPtr(node), true);
57 280 thisEntry->used = true; // Always set to used to not print warnings for non-existing code
58
59 // Hand it off to the function manager to register the function
60
2/4
✓ Branch 0 (36→37) taken 280 times.
✗ Branch 1 (36→62) not taken.
✓ Branch 2 (37→38) taken 280 times.
✗ Branch 3 (37→62) not taken.
280 FunctionManager::insert(structScope, defaultMethod, structEntry->declNode->getFctManifestations(name));
61 280 }
62
63 /**
64 * Checks if the given struct scope already has a user-defined constructor and creates a default one if not.
65 *
66 * For generating a default ctor, the following conditions need to be met:
67 * - No user-defined constructors
68 *
69 * @param spiceStruct Struct instance
70 * @param structScope Scope of the struct
71 */
72 580 void TypeChecker::createDefaultCtorIfRequired(const Struct &spiceStruct, Scope *structScope) {
73
1/2
✓ Branch 0 (2→3) taken 580 times.
✗ Branch 1 (2→4) not taken.
580 const auto node = spice_pointer_cast<StructDefNode *>(spiceStruct.declNode);
74
2/4
✓ Branch 0 (9→10) taken 580 times.
✗ Branch 1 (9→12) not taken.
✓ Branch 2 (10→11) taken 580 times.
✗ Branch 3 (10→12) not taken.
580 assert(structScope != nullptr && structScope->type == ScopeType::STRUCT);
75
76 // Abort if the struct already has a user-defined constructor
77 580 const SymbolTableEntry *structEntry = spiceStruct.entry;
78
1/2
✓ Branch 0 (13→14) taken 580 times.
✗ Branch 1 (13→128) not taken.
580 const QualType &structType = structEntry->getQualType();
79
3/6
✓ Branch 0 (14→15) taken 580 times.
✗ Branch 1 (14→101) not taken.
✓ Branch 2 (15→16) taken 580 times.
✗ Branch 3 (15→101) not taken.
✓ Branch 4 (16→17) taken 580 times.
✗ Branch 5 (16→99) not taken.
580 const std::string fqFctName = structType.getSubType() + MEMBER_ACCESS_TOKEN + CTOR_FUNCTION_NAME;
80
3/4
✓ Branch 0 (18→19) taken 580 times.
✗ Branch 1 (18→126) not taken.
✓ Branch 2 (19→20) taken 439 times.
✓ Branch 3 (19→21) taken 141 times.
580 if (sourceFile->getNameRegistryEntry(fqFctName))
81 439 return;
82
83 // Check if we have fields, that require us to do anything in the ctor
84
1/2
✓ Branch 0 (21→22) taken 141 times.
✗ Branch 1 (21→126) not taken.
141 const size_t fieldCount = structScope->getFieldCount();
85 141 bool hasFieldsWithDefaultValue = false;
86 141 bool hasFieldsToConstruct = false;
87
2/2
✓ Branch 0 (77→23) taken 302 times.
✓ Branch 1 (77→78) taken 135 times.
437 for (size_t i = 0; i < fieldCount; i++) {
88
1/2
✗ Branch 0 (23→24) not taken.
✓ Branch 1 (23→25) taken 302 times.
302 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
89
1/2
✗ Branch 0 (28→29) not taken.
✓ Branch 1 (28→30) taken 302 times.
302 assert(fieldSymbol != nullptr);
90
1/2
✓ Branch 0 (30→31) taken 302 times.
✗ Branch 1 (30→114) not taken.
302 const QualType &thisType = fieldSymbol->getQualType();
91
92 // Abort if we have a field, that is a reference
93
3/4
✓ Branch 0 (31→32) taken 302 times.
✗ Branch 1 (31→114) not taken.
✓ Branch 2 (32→33) taken 5 times.
✓ Branch 3 (32→34) taken 297 times.
302 if (thisType.isRef())
94 6 return;
95
96
3/4
✓ Branch 0 (34→35) taken 297 times.
✗ Branch 1 (34→36) not taken.
✓ Branch 2 (37→38) taken 278 times.
✓ Branch 3 (37→39) taken 19 times.
297 if (const auto fieldNode = dynamic_cast<FieldNode *>(fieldSymbol->declNode)) {
97 278 hasFieldsWithDefaultValue |= fieldNode->defaultValue != nullptr;
98 } else {
99
2/4
✓ Branch 0 (39→40) taken 19 times.
✗ Branch 1 (39→41) not taken.
✗ Branch 2 (42→43) not taken.
✓ Branch 3 (42→44) taken 19 times.
19 assert(dynamic_cast<DataTypeNode *>(fieldSymbol->declNode) != nullptr);
100 }
101
102
1/2
✓ Branch 0 (44→45) taken 297 times.
✗ Branch 1 (44→114) not taken.
297 const QualType fieldType = fieldSymbol->getQualType();
103
3/4
✓ Branch 0 (45→46) taken 297 times.
✗ Branch 1 (45→114) not taken.
✓ Branch 2 (46→47) taken 24 times.
✓ Branch 3 (46→75) taken 273 times.
297 if (fieldType.is(TY_STRUCT)) {
104
1/2
✓ Branch 0 (47→48) taken 24 times.
✗ Branch 1 (47→114) not taken.
24 Scope *bodyScope = fieldType.getBodyScope();
105
1/2
✓ Branch 0 (48→49) taken 24 times.
✗ Branch 1 (48→114) not taken.
24 const Struct *fieldStruct = fieldType.getStruct(node);
106 // Check if we are required to call a ctor
107
1/2
✓ Branch 0 (49→50) taken 24 times.
✗ Branch 1 (49→51) not taken.
24 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(fieldStruct->declNode);
108
5/6
✓ Branch 0 (56→57) taken 24 times.
✗ Branch 1 (56→114) not taken.
✓ Branch 2 (57→58) taken 23 times.
✓ Branch 3 (57→59) taken 1 times.
✓ Branch 4 (58→59) taken 5 times.
✓ Branch 5 (58→60) taken 18 times.
24 const bool isCtorCallRequired = bodyScope->hasRefFields() || structDeclNode->emitVTable;
109 // Lookup ctor function
110
2/4
✓ Branch 0 (65→66) taken 24 times.
✗ Branch 1 (65→104) not taken.
✓ Branch 2 (66→67) taken 24 times.
✗ Branch 3 (66→102) not taken.
72 const Function *ctorFct = FunctionManager::match(this, bodyScope, CTOR_FUNCTION_NAME, thisType, {}, {}, true, node);
111 // If we are required to construct, but no constructor is found, we can't generate a default ctor for the outer struct
112
4/4
✓ Branch 0 (71→72) taken 12 times.
✓ Branch 1 (71→74) taken 12 times.
✓ Branch 2 (72→73) taken 1 times.
✓ Branch 3 (72→74) taken 11 times.
24 if (!ctorFct && isCtorCallRequired)
113 1 return;
114 23 hasFieldsToConstruct |= ctorFct != nullptr;
115 }
116 }
117
118 // If we don't have any fields, that require us to do anything in the ctor, we can skip it
119
6/6
✓ Branch 0 (78→79) taken 108 times.
✓ Branch 1 (78→82) taken 27 times.
✓ Branch 2 (79→80) taken 96 times.
✓ Branch 3 (79→82) taken 12 times.
✓ Branch 4 (80→81) taken 91 times.
✓ Branch 5 (80→82) taken 5 times.
135 if (!hasFieldsWithDefaultValue && !hasFieldsToConstruct && !node->emitVTable)
120 91 return;
121
122 // Create the default ctor function
123
1/2
✓ Branch 0 (82→83) taken 44 times.
✗ Branch 1 (82→126) not taken.
44 const std::string entryName = Function::getSymbolTableEntryNameDefaultCtor(node->codeLoc);
124
2/4
✓ Branch 0 (86→87) taken 44 times.
✗ Branch 1 (86→117) not taken.
✓ Branch 2 (87→88) taken 44 times.
✗ Branch 3 (87→115) not taken.
132 createDefaultStructMethod(spiceStruct, entryName, CTOR_FUNCTION_NAME, {});
125
2/2
✓ Branch 0 (94→95) taken 44 times.
✓ Branch 1 (94→97) taken 536 times.
580 }
126
127 /**
128 * Checks if the given struct scope already has a user-defined constructor and creates a default one if not.
129 *
130 * For generating a default copy ctor, the following conditions need to be met:
131 * - No user-defined copy ctor
132 * - No user-defined move ctor
133 *
134 * @param spiceStruct Struct instance
135 * @param structScope Scope of the struct
136 */
137 580 void TypeChecker::createDefaultCopyCtorIfRequired(const Struct &spiceStruct, Scope *structScope) {
138
1/2
✓ Branch 0 (2→3) taken 580 times.
✗ Branch 1 (2→4) not taken.
580 const auto node = spice_pointer_cast<const StructDefNode *>(spiceStruct.declNode);
139
2/4
✓ Branch 0 (9→10) taken 580 times.
✗ Branch 1 (9→12) not taken.
✓ Branch 2 (10→11) taken 580 times.
✗ Branch 3 (10→12) not taken.
580 assert(structScope != nullptr && structScope->type == ScopeType::STRUCT);
140
141 // Abort if the struct already has a user-defined copy constructor
142
1/2
✓ Branch 0 (13→14) taken 580 times.
✗ Branch 1 (13→153) not taken.
580 const QualType structType = spiceStruct.entry->getQualType();
143
2/4
✓ Branch 0 (14→15) taken 580 times.
✗ Branch 1 (14→111) not taken.
✓ Branch 2 (18→19) taken 580 times.
✗ Branch 3 (18→107) not taken.
1740 const ArgList lookupArgs = {{structType.toConstRef(node), true}};
144
2/4
✓ Branch 0 (22→23) taken 580 times.
✗ Branch 1 (22→115) not taken.
✓ Branch 2 (23→24) taken 580 times.
✗ Branch 3 (23→113) not taken.
580 const Function *copyCtor = FunctionManager::lookup(structScope, CTOR_FUNCTION_NAME, structType, lookupArgs, true);
145
2/2
✓ Branch 0 (26→27) taken 110 times.
✓ Branch 1 (26→28) taken 470 times.
580 if (copyCtor != nullptr)
146 110 return;
147
148 // Abort if the struct has a user-defined move constructor
149 // ToDo: Check for move ctor
150
151 // Check if we have fields, that require us to do anything in the ctor
152
1/2
✓ Branch 0 (28→29) taken 470 times.
✗ Branch 1 (28→151) not taken.
470 const size_t fieldCount = structScope->getFieldCount();
153 470 bool copyCtorRequired = false;
154
2/2
✓ Branch 0 (82→30) taken 992 times.
✓ Branch 1 (82→83) taken 464 times.
1456 for (size_t i = 0; i < fieldCount; i++) {
155
1/2
✗ Branch 0 (30→31) not taken.
✓ Branch 1 (30→32) taken 992 times.
992 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
156
1/2
✓ Branch 0 (35→36) taken 992 times.
✗ Branch 1 (35→151) not taken.
992 const QualType &fieldType = fieldSymbol->getQualType();
157
158 // If the field is of type struct, check if this struct has a copy ctor that has to be called
159
3/4
✓ Branch 0 (36→37) taken 992 times.
✗ Branch 1 (36→151) not taken.
✓ Branch 2 (37→38) taken 131 times.
✓ Branch 3 (37→75) taken 861 times.
992 if (fieldType.is(TY_STRUCT)) {
160
1/2
✓ Branch 0 (38→39) taken 131 times.
✗ Branch 1 (38→136) not taken.
131 Scope *bodyScope = fieldType.getBodyScope();
161
1/2
✓ Branch 0 (39→40) taken 131 times.
✗ Branch 1 (39→136) not taken.
131 const Struct *fieldStruct = fieldType.getStruct(node);
162 // Check if we are required to call a ctor
163
1/2
✓ Branch 0 (40→41) taken 131 times.
✗ Branch 1 (40→42) not taken.
131 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(fieldStruct->declNode);
164
5/6
✓ Branch 0 (47→48) taken 131 times.
✗ Branch 1 (47→136) not taken.
✓ Branch 2 (48→49) taken 126 times.
✓ Branch 3 (48→50) taken 5 times.
✓ Branch 4 (49→50) taken 29 times.
✓ Branch 5 (49→51) taken 97 times.
131 const bool isCtorCallRequired = bodyScope->hasRefFields() || structDeclNode->emitVTable;
165 // Lookup copy ctor function
166
2/4
✓ Branch 0 (52→53) taken 131 times.
✗ Branch 1 (52→123) not taken.
✓ Branch 2 (56→57) taken 131 times.
✗ Branch 3 (56→119) not taken.
262 const ArgList args = {{fieldType.toConstRef(node), false /* we always have the field as storage */}};
167
2/4
✓ Branch 0 (61→62) taken 131 times.
✗ Branch 1 (61→127) not taken.
✓ Branch 2 (62→63) taken 131 times.
✗ Branch 3 (62→125) not taken.
393 const Function *ctorFct = FunctionManager::match(this, bodyScope, CTOR_FUNCTION_NAME, fieldType, args, {}, true, node);
168 // If we are required to construct, but no constructor is found, we can't generate a default ctor for the outer struct
169
4/4
✓ Branch 0 (66→67) taken 66 times.
✓ Branch 1 (66→69) taken 65 times.
✓ Branch 2 (67→68) taken 6 times.
✓ Branch 3 (67→69) taken 60 times.
131 if (!ctorFct && isCtorCallRequired)
170 6 return;
171 125 copyCtorRequired |= ctorFct != nullptr;
172
2/2
✓ Branch 0 (71→72) taken 125 times.
✓ Branch 1 (71→74) taken 6 times.
131 }
173
174 // If we have an owning heap pointer, we need to do a memcpy of the heap storage and therefore need a default copy ctor
175
3/4
✓ Branch 0 (75→76) taken 986 times.
✗ Branch 1 (75→151) not taken.
✓ Branch 2 (76→77) taken 20 times.
✓ Branch 3 (76→81) taken 966 times.
986 if (fieldType.isHeap()) {
176
2/4
✓ Branch 0 (77→78) taken 20 times.
✗ Branch 1 (77→151) not taken.
✗ Branch 2 (78→79) not taken.
✓ Branch 3 (78→80) taken 20 times.
20 assert(fieldType.isPtr());
177 20 copyCtorRequired = true;
178 }
179 }
180
181 // If we don't have any fields, that require us to do anything in the copy ctor, we can skip it
182
4/4
✓ Branch 0 (83→84) taken 408 times.
✓ Branch 1 (83→86) taken 56 times.
✓ Branch 2 (84→85) taken 303 times.
✓ Branch 3 (84→86) taken 105 times.
464 if (!copyCtorRequired && !node->emitVTable)
183 303 return;
184
185 // Create the default copy ctor function
186
1/2
✓ Branch 0 (86→87) taken 161 times.
✗ Branch 1 (86→151) not taken.
161 const std::string entryName = Function::getSymbolTableEntryNameDefaultCopyCtor(node->codeLoc);
187
2/4
✓ Branch 0 (87→88) taken 161 times.
✗ Branch 1 (87→140) not taken.
✓ Branch 2 (90→91) taken 161 times.
✗ Branch 3 (90→137) not taken.
483 const ParamList paramTypes = {{structType.toConstRef(node), false}};
188
2/4
✓ Branch 0 (94→95) taken 161 times.
✗ Branch 1 (94→143) not taken.
✓ Branch 2 (95→96) taken 161 times.
✗ Branch 3 (95→141) not taken.
161 createDefaultStructMethod(spiceStruct, entryName, CTOR_FUNCTION_NAME, paramTypes);
189
2/2
✓ Branch 0 (102→103) taken 161 times.
✓ Branch 1 (102→105) taken 419 times.
580 }
190
191 /**
192 * Checks if the given struct scope already has a user-defined destructor and creates a default one if not.
193 *
194 * For generating a default dtor, the following conditions need to be met:
195 * - No user-defined dtor
196 *
197 * @param spiceStruct Struct instance
198 * @param structScope Scope of the struct
199 */
200 580 void TypeChecker::createDefaultDtorIfRequired(const Struct &spiceStruct, Scope *structScope) {
201 580 const ASTNode *node = spiceStruct.declNode;
202
2/4
✓ Branch 0 (2→3) taken 580 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 580 times.
✗ Branch 3 (3→5) not taken.
580 assert(structScope != nullptr && structScope->type == ScopeType::STRUCT);
203
204 // Abort if the struct already has a user-defined destructor
205 580 const SymbolTableEntry *structEntry = spiceStruct.entry;
206
1/2
✓ Branch 0 (6→7) taken 580 times.
✗ Branch 1 (6→143) not taken.
580 const QualType &structType = structEntry->getQualType();
207
3/6
✓ Branch 0 (7→8) taken 580 times.
✗ Branch 1 (7→98) not taken.
✓ Branch 2 (8→9) taken 580 times.
✗ Branch 3 (8→98) not taken.
✓ Branch 4 (9→10) taken 580 times.
✗ Branch 5 (9→96) not taken.
580 const std::string fqFctName = structType.getSubType() + MEMBER_ACCESS_TOKEN + DTOR_FUNCTION_NAME;
208
3/4
✓ Branch 0 (11→12) taken 580 times.
✗ Branch 1 (11→141) not taken.
✓ Branch 2 (12→13) taken 101 times.
✓ Branch 3 (12→14) taken 479 times.
580 if (sourceFile->getNameRegistryEntry(fqFctName))
209 101 return;
210
211 // Check we have field types, that require use to do anything in the destructor
212
1/2
✓ Branch 0 (14→15) taken 479 times.
✗ Branch 1 (14→141) not taken.
479 const size_t fieldCount = structScope->getFieldCount();
213 479 bool hasFieldsToDeAllocate = false;
214 479 bool hasFieldsToDestruct = false;
215
2/2
✓ Branch 0 (41→16) taken 1076 times.
✓ Branch 1 (41→42) taken 479 times.
1555 for (size_t i = 0; i < fieldCount; i++) {
216
1/2
✗ Branch 0 (16→17) not taken.
✓ Branch 1 (16→18) taken 1076 times.
1076 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
217
2/4
✓ Branch 0 (21→22) taken 1076 times.
✗ Branch 1 (21→141) not taken.
✓ Branch 2 (22→23) taken 1076 times.
✗ Branch 3 (22→141) not taken.
1076 hasFieldsToDeAllocate |= fieldSymbol->getQualType().needsDeAllocation();
218
4/6
✓ Branch 0 (23→24) taken 1076 times.
✗ Branch 1 (23→141) not taken.
✓ Branch 2 (24→25) taken 1076 times.
✗ Branch 3 (24→141) not taken.
✓ Branch 4 (25→26) taken 131 times.
✓ Branch 5 (25→40) taken 945 times.
1076 if (fieldSymbol->getQualType().is(TY_STRUCT)) {
219
2/4
✓ Branch 0 (26→27) taken 131 times.
✗ Branch 1 (26→141) not taken.
✓ Branch 2 (27→28) taken 131 times.
✗ Branch 3 (27→141) not taken.
131 Scope *fieldScope = fieldSymbol->getQualType().getBodyScope();
220 // Lookup dtor function
221
1/2
✓ Branch 0 (28→29) taken 131 times.
✗ Branch 1 (28→141) not taken.
131 const QualType &thisType = fieldSymbol->getQualType();
222
2/4
✓ Branch 0 (33→34) taken 131 times.
✗ Branch 1 (33→101) not taken.
✓ Branch 2 (34→35) taken 131 times.
✗ Branch 3 (34→99) not taken.
393 const Function *dtorFct = FunctionManager::match(this, fieldScope, DTOR_FUNCTION_NAME, thisType, {}, {}, true, node);
223 131 hasFieldsToDestruct |= dtorFct != nullptr;
224
1/2
✓ Branch 0 (39→40) taken 131 times.
✗ Branch 1 (39→141) not taken.
131 requestRevisitIfRequired(dtorFct);
225 }
226 }
227
228 // If we don't have any fields, that require us to do anything in the dtor, we can skip it
229
4/4
✓ Branch 0 (42→43) taken 437 times.
✓ Branch 1 (42→45) taken 42 times.
✓ Branch 2 (43→44) taken 404 times.
✓ Branch 3 (43→45) taken 33 times.
479 if (!hasFieldsToDeAllocate && !hasFieldsToDestruct)
230 404 return;
231
232 // Create the default dtor function
233
1/2
✓ Branch 0 (45→46) taken 75 times.
✗ Branch 1 (45→141) not taken.
75 const std::string entryName = Function::getSymbolTableEntryNameDefaultDtor(node->codeLoc);
234
2/4
✓ Branch 0 (49→50) taken 75 times.
✗ Branch 1 (49→113) not taken.
✓ Branch 2 (50→51) taken 75 times.
✗ Branch 3 (50→111) not taken.
225 createDefaultStructMethod(spiceStruct, entryName, DTOR_FUNCTION_NAME, {});
235
236 // Request memory runtime if we have fields, that are allocated on the heap
237 // The string runtime does not use it, but allocates manually to avoid circular dependencies
238
6/8
✓ Branch 0 (54→55) taken 42 times.
✓ Branch 1 (54→60) taken 33 times.
✓ Branch 2 (55→56) taken 42 times.
✗ Branch 3 (55→139) not taken.
✓ Branch 4 (58→59) taken 42 times.
✗ Branch 5 (58→60) not taken.
✓ Branch 6 (61→62) taken 42 times.
✓ Branch 7 (61→88) taken 33 times.
117 if (hasFieldsToDeAllocate && !sourceFile->isStringRT()) {
239
1/2
✓ Branch 0 (62→63) taken 42 times.
✗ Branch 1 (62→138) not taken.
42 const SourceFile *memoryRT = sourceFile->requestRuntimeModule(MEMORY_RT);
240
1/2
✗ Branch 0 (63→64) not taken.
✓ Branch 1 (63→65) taken 42 times.
42 assert(memoryRT != nullptr);
241 42 Scope *matchScope = memoryRT->globalScope.get();
242 // Set dealloc function to used
243
1/2
✓ Branch 0 (66→67) taken 42 times.
✗ Branch 1 (66→138) not taken.
42 const QualType thisType(TY_DYN);
244
3/6
✓ Branch 0 (67→68) taken 42 times.
✗ Branch 1 (67→120) not taken.
✓ Branch 2 (68→69) taken 42 times.
✗ Branch 3 (68→120) not taken.
✓ Branch 4 (69→70) taken 42 times.
✗ Branch 5 (69→120) not taken.
42 QualType bytePtrRefType = QualType(TY_BYTE).toPtr(node).toRef(node);
245
1/2
✓ Branch 0 (70→71) taken 42 times.
✗ Branch 1 (70→138) not taken.
42 bytePtrRefType.makeHeap();
246
1/2
✓ Branch 0 (74→75) taken 42 times.
✗ Branch 1 (74→122) not taken.
84 const ArgList args = {{bytePtrRefType, false /* we always have the field as storage */}};
247
2/4
✓ Branch 0 (79→80) taken 42 times.
✗ Branch 1 (79→129) not taken.
✓ Branch 2 (80→81) taken 42 times.
✗ Branch 3 (80→127) not taken.
126 Function *deallocFct = FunctionManager::match(this, matchScope, FCT_NAME_DEALLOC, thisType, args, {}, true, node);
248
1/2
✗ Branch 0 (84→85) not taken.
✓ Branch 1 (84→86) taken 42 times.
42 assert(deallocFct != nullptr);
249 42 deallocFct->used = true;
250 42 }
251
2/2
✓ Branch 0 (91→92) taken 75 times.
✓ Branch 1 (91→94) taken 505 times.
580 }
252
253 /**
254 * Prepare the generation of the ctor body preamble. This preamble is used to initialize the VTable, construct or initialize
255 * fields.
256 */
257 1198 void TypeChecker::createCtorBodyPreamble(const Scope *bodyScope) {
258 // Retrieve struct scope
259 1198 Scope *structScope = bodyScope->parent;
260
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 1198 times.
1198 assert(structScope != nullptr);
261
262 1198 const size_t fieldCount = structScope->getFieldCount();
263
2/2
✓ Branch 0 (49→6) taken 3099 times.
✓ Branch 1 (49→50) taken 1198 times.
4297 for (size_t i = 0; i < fieldCount; i++) {
264
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 3099 times.
3099 SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
265
3/6
✓ Branch 0 (11→12) taken 3099 times.
✗ Branch 1 (11→15) not taken.
✓ Branch 2 (12→13) taken 3099 times.
✗ Branch 3 (12→64) not taken.
✓ Branch 4 (13→14) taken 3099 times.
✗ Branch 5 (13→15) not taken.
3099 assert(fieldSymbol != nullptr && fieldSymbol->isField());
266
2/2
✓ Branch 0 (16→17) taken 180 times.
✓ Branch 1 (16→18) taken 2919 times.
3099 if (fieldSymbol->isImplicitField)
267 180 continue;
268
1/2
✓ Branch 0 (18→19) taken 2919 times.
✗ Branch 1 (18→64) not taken.
2919 QualType fieldType = fieldSymbol->getQualType();
269
3/4
✓ Branch 0 (19→20) taken 2919 times.
✗ Branch 1 (19→64) not taken.
✓ Branch 2 (20→21) taken 421 times.
✓ Branch 3 (20→22) taken 2498 times.
2919 if (fieldType.hasAnyGenericParts())
270
1/2
✓ Branch 0 (21→22) taken 421 times.
✗ Branch 1 (21→64) not taken.
421 TypeMatcher::substantiateTypeWithTypeMapping(fieldType, typeMapping, fieldSymbol->declNode);
271
272
3/4
✓ Branch 0 (22→23) taken 2919 times.
✗ Branch 1 (22→64) not taken.
✓ Branch 2 (23→24) taken 398 times.
✓ Branch 3 (23→47) taken 2521 times.
2919 if (fieldType.is(TY_STRUCT)) {
273
1/2
✓ Branch 0 (24→25) taken 398 times.
✗ Branch 1 (24→26) not taken.
398 const auto fieldNode = spice_pointer_cast<const FieldNode *>(fieldSymbol->declNode);
274 // Match ctor function, create the concrete manifestation and set it to used
275
1/2
✓ Branch 0 (31→32) taken 398 times.
✗ Branch 1 (31→64) not taken.
398 Scope *matchScope = fieldType.getBodyScope();
276 const Function *spiceFunc =
277
2/4
✓ Branch 0 (36→37) taken 398 times.
✗ Branch 1 (36→53) not taken.
✓ Branch 2 (37→38) taken 398 times.
✗ Branch 3 (37→51) not taken.
1194 FunctionManager::match(this, matchScope, CTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
278
2/2
✓ Branch 0 (42→43) taken 358 times.
✓ Branch 1 (42→47) taken 40 times.
398 if (spiceFunc != nullptr)
279
3/6
✓ Branch 0 (43→44) taken 358 times.
✗ Branch 1 (43→63) not taken.
✓ Branch 2 (44→45) taken 358 times.
✗ Branch 3 (44→63) not taken.
✓ Branch 4 (45→46) taken 358 times.
✗ Branch 5 (45→63) not taken.
358 fieldSymbol->updateType(fieldType.getWithBodyScope(spiceFunc->thisType.getBodyScope()), true);
280 }
281 }
282 1198 }
283
284 /**
285 * Prepare the generation of the copy ctor body preamble. This preamble is used to initialize the VTable, construct or initialize
286 * fields.
287 */
288 133 void TypeChecker::createCopyCtorBodyPreamble(const Scope *bodyScope) {
289 // Retrieve struct scope
290 133 Scope *structScope = bodyScope->parent;
291
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 133 times.
133 assert(structScope != nullptr);
292
293 133 const size_t fieldCount = structScope->getFieldCount();
294
2/2
✓ Branch 0 (55→6) taken 317 times.
✓ Branch 1 (55→56) taken 133 times.
450 for (size_t i = 0; i < fieldCount; i++) {
295
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 317 times.
317 SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
296
3/6
✓ Branch 0 (11→12) taken 317 times.
✗ Branch 1 (11→15) not taken.
✓ Branch 2 (12→13) taken 317 times.
✗ Branch 3 (12→76) not taken.
✓ Branch 4 (13→14) taken 317 times.
✗ Branch 5 (13→15) not taken.
317 assert(fieldSymbol != nullptr && fieldSymbol->isField());
297
2/2
✓ Branch 0 (16→17) taken 28 times.
✓ Branch 1 (16→18) taken 289 times.
317 if (fieldSymbol->isImplicitField)
298 28 continue;
299
300
1/2
✓ Branch 0 (18→19) taken 289 times.
✗ Branch 1 (18→76) not taken.
289 QualType fieldType = fieldSymbol->getQualType();
301
2/4
✓ Branch 0 (19→20) taken 289 times.
✗ Branch 1 (19→76) not taken.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→22) taken 289 times.
289 if (fieldType.hasAnyGenericParts())
302 TypeMatcher::substantiateTypeWithTypeMapping(fieldType, typeMapping, fieldSymbol->declNode);
303
304
3/4
✓ Branch 0 (22→23) taken 289 times.
✗ Branch 1 (22→76) not taken.
✓ Branch 2 (23→24) taken 137 times.
✓ Branch 3 (23→53) taken 152 times.
289 if (fieldType.is(TY_STRUCT)) {
305
1/2
✓ Branch 0 (24→25) taken 137 times.
✗ Branch 1 (24→26) not taken.
137 const auto fieldNode = spice_pointer_cast<const FieldNode *>(fieldSymbol->declNode);
306 // Match ctor function, create the concrete manifestation and set it to used
307
1/2
✓ Branch 0 (31→32) taken 137 times.
✗ Branch 1 (31→75) not taken.
137 Scope *matchScope = fieldType.getBodyScope();
308
2/4
✓ Branch 0 (32→33) taken 137 times.
✗ Branch 1 (32→61) not taken.
✓ Branch 2 (36→37) taken 137 times.
✗ Branch 3 (36→57) not taken.
274 const ArgList args = {{fieldType.toConstRef(fieldNode), false /* we always have the field as storage */}};
309 const Function *copyCtorFct =
310
2/4
✓ Branch 0 (41→42) taken 137 times.
✗ Branch 1 (41→65) not taken.
✓ Branch 2 (42→43) taken 137 times.
✗ Branch 3 (42→63) not taken.
411 FunctionManager::match(this, matchScope, CTOR_FUNCTION_NAME, fieldType, args, {}, false, fieldNode);
311
2/2
✓ Branch 0 (46→47) taken 126 times.
✓ Branch 1 (46→51) taken 11 times.
137 if (copyCtorFct != nullptr)
312
3/6
✓ Branch 0 (47→48) taken 126 times.
✗ Branch 1 (47→72) not taken.
✓ Branch 2 (48→49) taken 126 times.
✗ Branch 3 (48→72) not taken.
✓ Branch 4 (49→50) taken 126 times.
✗ Branch 5 (49→72) not taken.
126 fieldSymbol->updateType(fieldType.getWithBodyScope(copyCtorFct->thisType.getBodyScope()), true);
313 137 }
314 }
315 133 }
316
317 /**
318 * Prepare the generation of the dtor body preamble. This preamble is used to destruct all fields and to free all heap fields.
319 */
320 183 void TypeChecker::createDtorBodyPreamble(const Scope *bodyScope) {
321 // Retrieve struct scope
322 183 Scope *structScope = bodyScope->parent;
323
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 183 times.
183 assert(structScope != nullptr);
324
325 183 const size_t fieldCount = structScope->getFieldCount();
326
2/2
✓ Branch 0 (45→6) taken 702 times.
✓ Branch 1 (45→46) taken 183 times.
885 for (size_t i = 0; i < fieldCount; i++) {
327
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 702 times.
702 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
328
3/6
✓ Branch 0 (11→12) taken 702 times.
✗ Branch 1 (11→15) not taken.
✓ Branch 2 (12→13) taken 702 times.
✗ Branch 3 (12→59) not taken.
✓ Branch 4 (13→14) taken 702 times.
✗ Branch 5 (13→15) not taken.
702 assert(fieldSymbol != nullptr && fieldSymbol->isField());
329
2/2
✓ Branch 0 (16→17) taken 100 times.
✓ Branch 1 (16→18) taken 602 times.
702 if (fieldSymbol->isImplicitField)
330 100 continue;
331
1/2
✓ Branch 0 (18→19) taken 602 times.
✗ Branch 1 (18→59) not taken.
602 QualType fieldType = fieldSymbol->getQualType();
332
2/4
✓ Branch 0 (19→20) taken 602 times.
✗ Branch 1 (19→59) not taken.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→22) taken 602 times.
602 if (fieldType.hasAnyGenericParts())
333 TypeMatcher::substantiateTypeWithTypeMapping(fieldType, typeMapping, fieldSymbol->declNode);
334
335
3/4
✓ Branch 0 (22→23) taken 602 times.
✗ Branch 1 (22→59) not taken.
✓ Branch 2 (23→24) taken 176 times.
✓ Branch 3 (23→43) taken 426 times.
602 if (fieldType.is(TY_STRUCT)) {
336
1/2
✓ Branch 0 (24→25) taken 176 times.
✗ Branch 1 (24→26) not taken.
176 const auto fieldNode = spice_pointer_cast<const FieldNode *>(fieldSymbol->declNode);
337 // Match ctor function, create the concrete manifestation and set it to used
338
1/2
✓ Branch 0 (31→32) taken 176 times.
✗ Branch 1 (31→59) not taken.
176 Scope *matchScope = fieldType.getBodyScope();
339
2/4
✓ Branch 0 (36→37) taken 176 times.
✗ Branch 1 (36→49) not taken.
✓ Branch 2 (37→38) taken 176 times.
✗ Branch 3 (37→47) not taken.
528 FunctionManager::match(this, matchScope, DTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
340 }
341 }
342 183 }
343
344 /**
345 * Prepare the generation of a call to a method of a given struct
346 *
347 * @param entry Symbol entry to use as 'this' pointer for the method call
348 * @param methodName Name of the method to call
349 * @param args Provided arguments by the caller
350 * @param node AST node
351 */
352 1897 Function *TypeChecker::implicitlyCallStructMethod(const SymbolTableEntry *entry, const std::string &methodName,
353 const ArgList &args, const ASTNode *node) {
354
3/6
✓ Branch 0 (2→3) taken 1897 times.
✗ Branch 1 (2→9) not taken.
✓ Branch 2 (3→4) taken 1897 times.
✗ Branch 3 (3→9) not taken.
✓ Branch 4 (4→5) taken 1897 times.
✗ Branch 5 (4→9) not taken.
1897 const QualType thisType = entry->getQualType().removeReferenceWrapper().toNonConst();
355
1/2
✓ Branch 0 (5→6) taken 1897 times.
✗ Branch 1 (5→10) not taken.
3794 return implicitlyCallStructMethod(thisType, methodName, args, node);
356 }
357
358 /**
359 * Prepare the generation of a call to a method of a given struct
360 *
361 * @param thisType Struct type to call the method on
362 * @param methodName Name of the method to call
363 * @param args Provided arguments by the caller
364 * @param node AST node
365 */
366 2142 Function *TypeChecker::implicitlyCallStructMethod(QualType thisType, const std::string &methodName, const ArgList &args,
367 const ASTNode *node) {
368
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 2142 times.
2142 assert(thisType.is(TY_STRUCT));
369 2142 Scope *matchScope = thisType.getBodyScope();
370
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 2142 times.
2142 assert(matchScope->type == ScopeType::STRUCT);
371
372 // Search for dtor
373
2/2
✓ Branch 0 (9→10) taken 1446 times.
✓ Branch 1 (9→12) taken 696 times.
2142 if (matchScope->isImportedBy(rootScope))
374
1/2
✓ Branch 0 (10→11) taken 1446 times.
✗ Branch 1 (10→18) not taken.
1446 thisType = mapLocalTypeToImportedScopeType(matchScope, thisType);
375
1/2
✓ Branch 0 (13→14) taken 2142 times.
✗ Branch 1 (13→19) not taken.
2142 return FunctionManager::match(this, matchScope, methodName, thisType, args, {}, true, node);
376 }
377
378 /**
379 * Prepare the generation of a call to the copy ctor of a given struct
380 *
381 * @param entry Symbol entry to use as 'this' pointer for the copy ctor call
382 * @param node Current AST node
383 */
384 5 Function *TypeChecker::implicitlyCallStructCopyCtor(const SymbolTableEntry *entry, const ASTNode *node) {
385
2/4
✓ Branch 0 (2→3) taken 5 times.
✗ Branch 1 (2→7) not taken.
✓ Branch 2 (5→6) taken 5 times.
✗ Branch 3 (5→7) not taken.
5 assert(entry != nullptr && entry->getQualType().is(TY_STRUCT));
386 5 return implicitlyCallStructCopyCtor(entry->getQualType(), node);
387 }
388
389 /**
390 * Prepare the generation of a call to the copy ctor of a given struct
391 *
392 * @param thisType Struct type to call the copy ctor on
393 * @param node Current AST node
394 */
395 245 Function *TypeChecker::implicitlyCallStructCopyCtor(const QualType &thisType, const ASTNode *node) {
396
2/4
✓ Branch 0 (2→3) taken 245 times.
✗ Branch 1 (2→19) not taken.
✓ Branch 2 (3→4) taken 245 times.
✗ Branch 3 (3→19) not taken.
245 const QualType argType = thisType.removeReferenceWrapper().toConstRef(node);
397
1/2
✓ Branch 0 (7→8) taken 245 times.
✗ Branch 1 (7→20) not taken.
735 const ArgList args = {{argType, false /* we always have an entry here */}};
398
2/4
✓ Branch 0 (11→12) taken 245 times.
✗ Branch 1 (11→27) not taken.
✓ Branch 2 (12→13) taken 245 times.
✗ Branch 3 (12→25) not taken.
490 return implicitlyCallStructMethod(thisType, CTOR_FUNCTION_NAME, args, node);
399 245 }
400
401 /**
402 * Prepare the generation of a call to the dtor of a given struct
403 *
404 * @param entry Symbol entry to use as 'this' pointer for the dtor call
405 * @param node StmtLstNode for the current scope
406 */
407 1897 void TypeChecker::implicitlyCallStructDtor(SymbolTableEntry *entry, StmtLstNode *node) {
408 // Add the dtor to the stmt list node to call it later in codegen
409
4/6
✓ Branch 0 (5→6) taken 1897 times.
✗ Branch 1 (5→16) not taken.
✓ Branch 2 (6→7) taken 1897 times.
✗ Branch 3 (6→14) not taken.
✓ Branch 4 (10→11) taken 958 times.
✓ Branch 5 (10→13) taken 939 times.
5691 if (Function *dtor = implicitlyCallStructMethod(entry, DTOR_FUNCTION_NAME, {}, node))
410
2/4
✓ Branch 0 (11→12) taken 958 times.
✗ Branch 1 (11→23) not taken.
✓ Branch 2 (12→13) taken 958 times.
✗ Branch 3 (12→23) not taken.
958 node->resourcesToCleanup.at(manIdx).dtorFunctionsToCall.emplace_back(entry, dtor);
411 1897 }
412
413 /**
414 * Prepare the generation of a call to the deallocate function for a heap-allocated variable
415 *
416 * @param node Current AST node for error messages
417 */
418 3 void TypeChecker::implicitlyCallDeallocate(const ASTNode *node) {
419
1/2
✓ Branch 0 (2→3) taken 3 times.
✗ Branch 1 (2→46) not taken.
3 const SourceFile *memoryRT = sourceFile->requestRuntimeModule(MEMORY_RT);
420
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 3 times.
3 assert(memoryRT != nullptr);
421 3 Scope *matchScope = memoryRT->globalScope.get();
422 // Set dealloc function to used
423
1/2
✓ Branch 0 (6→7) taken 3 times.
✗ Branch 1 (6→46) not taken.
3 const QualType thisType(TY_DYN);
424
3/6
✓ Branch 0 (7→8) taken 3 times.
✗ Branch 1 (7→28) not taken.
✓ Branch 2 (8→9) taken 3 times.
✗ Branch 3 (8→28) not taken.
✓ Branch 4 (9→10) taken 3 times.
✗ Branch 5 (9→28) not taken.
3 QualType bytePtrRefType = QualType(TY_BYTE).toPtr(node).toRef(node);
425
1/2
✓ Branch 0 (10→11) taken 3 times.
✗ Branch 1 (10→46) not taken.
3 bytePtrRefType.makeHeap();
426
1/2
✓ Branch 0 (14→15) taken 3 times.
✗ Branch 1 (14→30) not taken.
6 const ArgList args = {{bytePtrRefType, false /* we always have the field as storage */}};
427
2/4
✓ Branch 0 (19→20) taken 3 times.
✗ Branch 1 (19→37) not taken.
✓ Branch 2 (20→21) taken 3 times.
✗ Branch 3 (20→35) not taken.
9 Function *deallocFct = FunctionManager::match(this, matchScope, FCT_NAME_DEALLOC, thisType, args, {}, true, node);
428
1/2
✗ Branch 0 (24→25) not taken.
✓ Branch 1 (24→26) taken 3 times.
3 assert(deallocFct != nullptr);
429 3 deallocFct->used = true;
430 3 }
431
432 /**
433 * Consider calls to destructors for the given scope
434 *
435 * @param node StmtLstNode for the current scope
436 */
437 16706 void TypeChecker::doScopeCleanup(StmtLstNode *node) {
438 // Get all variables, that are approved for de-allocation
439
1/2
✓ Branch 0 (2→3) taken 16706 times.
✗ Branch 1 (2→61) not taken.
16706 std::vector<SymbolTableEntry *> vars = currentScope->getVarsGoingOutOfScope();
440 // Sort by reverse declaration order
441
2/2
✓ Branch 0 (2→3) taken 210 times.
✓ Branch 1 (2→4) taken 5940 times.
12300 auto comp = [](const SymbolTableEntry *a, const SymbolTableEntry *b) { return a->declNode->codeLoc > b->declNode->codeLoc; };
442
1/2
✓ Branch 0 (3→4) taken 16706 times.
✗ Branch 1 (3→59) not taken.
16706 std::ranges::sort(vars, comp);
443 // Call dtor for each variable. We call the dtor in reverse declaration order
444
2/2
✓ Branch 0 (54→6) taken 7779 times.
✓ Branch 1 (54→55) taken 16706 times.
24485 for (SymbolTableEntry *var : vars) {
445 // Check if we have a heap-allocated pointer
446
10/14
✓ Branch 0 (7→8) taken 7779 times.
✗ Branch 1 (7→57) not taken.
✓ Branch 2 (8→9) taken 7779 times.
✗ Branch 3 (8→57) not taken.
✓ Branch 4 (9→10) taken 989 times.
✓ Branch 5 (9→14) taken 6790 times.
✓ Branch 6 (10→11) taken 989 times.
✗ Branch 7 (10→57) not taken.
✓ Branch 8 (11→12) taken 989 times.
✗ Branch 9 (11→57) not taken.
✓ Branch 10 (12→13) taken 955 times.
✓ Branch 11 (12→14) taken 34 times.
✓ Branch 12 (15→16) taken 955 times.
✓ Branch 13 (15→35) taken 6824 times.
7779 if (var->getQualType().isHeap() && var->getQualType().isOneOf({TY_PTR, TY_STRING, TY_FUNCTION, TY_PROCEDURE})) {
447 // The memory runtime is ignored, because it manually allocates to avoid circular dependencies.
448 // Same goes for the string runtime.
449
8/10
✓ Branch 0 (16→17) taken 955 times.
✗ Branch 1 (16→58) not taken.
✓ Branch 2 (19→20) taken 839 times.
✓ Branch 3 (19→24) taken 116 times.
✓ Branch 4 (20→21) taken 839 times.
✗ Branch 5 (20→58) not taken.
✓ Branch 6 (23→24) taken 810 times.
✓ Branch 7 (23→25) taken 29 times.
✓ Branch 8 (26→27) taken 926 times.
✓ Branch 9 (26→28) taken 29 times.
2749 if (sourceFile->isMemoryRT() || sourceFile->isStringRT())
450 926 continue;
451 // If the local variable currently does not have the ownership, we must not deallocate its memory
452
3/4
✓ Branch 0 (29→30) taken 29 times.
✗ Branch 1 (29→58) not taken.
✓ Branch 2 (30→31) taken 26 times.
✓ Branch 3 (30→32) taken 3 times.
29 if (!var->getLifecycle().isInOwningState())
453 26 continue;
454
455
1/2
✓ Branch 0 (32→33) taken 3 times.
✗ Branch 1 (32→58) not taken.
3 implicitlyCallDeallocate(node); // Required to request the memory runtime
456
2/4
✓ Branch 0 (33→34) taken 3 times.
✗ Branch 1 (33→58) not taken.
✓ Branch 2 (34→35) taken 3 times.
✗ Branch 3 (34→58) not taken.
3 node->resourcesToCleanup.at(manIdx).heapVarsToFree.push_back(var);
457 }
458 // Only generate dtor call for structs and if not omitted
459
8/10
✓ Branch 0 (35→36) taken 6827 times.
✗ Branch 1 (35→58) not taken.
✓ Branch 2 (36→37) taken 6827 times.
✗ Branch 3 (36→58) not taken.
✓ Branch 4 (37→38) taken 1992 times.
✓ Branch 5 (37→39) taken 4835 times.
✓ Branch 6 (38→39) taken 95 times.
✓ Branch 7 (38→40) taken 1897 times.
✓ Branch 8 (41→42) taken 4930 times.
✓ Branch 9 (41→43) taken 1897 times.
6827 if (!var->getQualType().is(TY_STRUCT) || var->omitDtorCall)
460 4930 continue;
461 // Variable must be either initialized or a struct field
462
3/8
✓ Branch 0 (44→45) taken 1897 times.
✗ Branch 1 (44→58) not taken.
✗ Branch 2 (45→46) not taken.
✓ Branch 3 (45→48) taken 1897 times.
✗ Branch 4 (46→47) not taken.
✗ Branch 5 (46→48) not taken.
✗ Branch 6 (49→50) not taken.
✓ Branch 7 (49→51) taken 1897 times.
1897 if (!var->getLifecycle().isInitialized() && var->scope->type != ScopeType::STRUCT)
463 continue;
464 // Call dtor
465
1/2
✓ Branch 0 (51→52) taken 1897 times.
✗ Branch 1 (51→58) not taken.
1897 implicitlyCallStructDtor(var, node);
466 }
467 16706 }
468
469 } // namespace spice::compiler
470