GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeCheckerImplicit.cpp
Date: 2025-03-05 01:50:32
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 300 void TypeChecker::createDefaultStructMethod(const Struct &spiceStruct, const std::string &entryName, const std::string &name,
26 const ParamList &params) const {
27 300 Scope *structScope = spiceStruct.scope;
28 300 ASTNode *node = spiceStruct.declNode;
29 300 const SymbolTableEntry *structEntry = spiceStruct.entry;
30
1/2
✓ Branch 0 (2→3) taken 300 times.
✗ Branch 1 (2→68) not taken.
300 const QualType &structType = structEntry->getQualType();
31
3/6
✓ Branch 0 (3→4) taken 300 times.
✗ Branch 1 (3→44) not taken.
✓ Branch 2 (4→5) taken 300 times.
✗ Branch 3 (4→44) not taken.
✓ Branch 4 (5→6) taken 300 times.
✗ Branch 5 (5→42) not taken.
300 const std::string fqFctName = structType.getSubType() + MEMBER_ACCESS_TOKEN + name;
32
33 // Procedure type
34
1/2
✓ Branch 0 (7→8) taken 300 times.
✗ Branch 1 (7→66) not taken.
300 QualType procedureType(TY_PROCEDURE);
35
1/2
✓ Branch 0 (8→9) taken 300 times.
✗ Branch 1 (8→66) not taken.
300 procedureType.makePublic(); // Always public
36
37 // Insert symbol for function into the symbol table
38
1/2
✓ Branch 0 (9→10) taken 300 times.
✗ Branch 1 (9→66) not taken.
300 SymbolTableEntry *procEntry = structScope->insert(entryName, structEntry->declNode);
39
1/2
✓ Branch 0 (12→13) taken 300 times.
✗ Branch 1 (12→66) not taken.
300 procEntry->updateType(procedureType, true);
40
41 // Add to external name registry
42
1/2
✓ Branch 0 (13→14) taken 300 times.
✗ Branch 1 (13→66) not taken.
300 sourceFile->addNameRegistryEntry(fqFctName, TY_PROCEDURE, procEntry, structScope, true);
43
44 // Create the default method
45
1/2
✓ Branch 0 (14→15) taken 300 times.
✗ Branch 1 (14→66) not taken.
300 const std::vector<GenericType> templateTypes = spiceStruct.templateTypes;
46
1/2
✓ Branch 0 (15→16) taken 300 times.
✗ Branch 1 (15→64) not taken.
300 const QualType returnType(TY_DYN);
47
3/6
✓ Branch 0 (16→17) taken 300 times.
✗ Branch 1 (16→51) not taken.
✓ Branch 2 (17→18) taken 300 times.
✗ Branch 3 (17→48) not taken.
✓ Branch 4 (18→19) taken 300 times.
✗ Branch 5 (18→45) not taken.
300 Function defaultMethod(name, procEntry, structType, returnType, params, templateTypes, structEntry->declNode);
48 300 defaultMethod.implicitDefault = true;
49
50 // Create function scope
51
2/4
✓ Branch 0 (23→24) taken 300 times.
✗ Branch 1 (23→54) not taken.
✓ Branch 2 (24→25) taken 300 times.
✗ Branch 3 (24→52) not taken.
300 Scope *procScope = structScope->createChildScope(defaultMethod.getSignature(false), ScopeType::FUNC_PROC_BODY, &node->codeLoc);
52 300 defaultMethod.bodyScope = procScope;
53
54 // Create 'this' symbol in the function scope
55
1/2
✓ Branch 0 (28→29) taken 300 times.
✗ Branch 1 (28→57) not taken.
900 SymbolTableEntry *thisEntry = procScope->insert(THIS_VARIABLE_NAME, node);
56
2/4
✓ Branch 0 (34→35) taken 300 times.
✗ Branch 1 (34→61) not taken.
✓ Branch 2 (35→36) taken 300 times.
✗ Branch 3 (35→61) not taken.
300 thisEntry->updateType(structType.toPtr(node), true);
57 300 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 300 times.
✗ Branch 1 (36→62) not taken.
✓ Branch 2 (37→38) taken 300 times.
✗ Branch 3 (37→62) not taken.
300 FunctionManager::insert(structScope, defaultMethod, structEntry->declNode->getFctManifestations(name));
61 300 }
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 600 void TypeChecker::createDefaultCtorIfRequired(const Struct &spiceStruct, Scope *structScope) {
73
1/2
✓ Branch 0 (2→3) taken 600 times.
✗ Branch 1 (2→4) not taken.
600 const auto node = spice_pointer_cast<StructDefNode *>(spiceStruct.declNode);
74
2/4
✓ Branch 0 (9→10) taken 600 times.
✗ Branch 1 (9→12) not taken.
✓ Branch 2 (10→11) taken 600 times.
✗ Branch 3 (10→12) not taken.
600 assert(structScope != nullptr && structScope->type == ScopeType::STRUCT);
75
76 // Abort if the struct already has a user-defined constructor
77 600 const SymbolTableEntry *structEntry = spiceStruct.entry;
78
1/2
✓ Branch 0 (13→14) taken 600 times.
✗ Branch 1 (13→128) not taken.
600 const QualType &structType = structEntry->getQualType();
79
3/6
✓ Branch 0 (14→15) taken 600 times.
✗ Branch 1 (14→101) not taken.
✓ Branch 2 (15→16) taken 600 times.
✗ Branch 3 (15→101) not taken.
✓ Branch 4 (16→17) taken 600 times.
✗ Branch 5 (16→99) not taken.
600 const std::string fqFctName = structType.getSubType() + MEMBER_ACCESS_TOKEN + CTOR_FUNCTION_NAME;
80
3/4
✓ Branch 0 (18→19) taken 600 times.
✗ Branch 1 (18→126) not taken.
✓ Branch 2 (19→20) taken 456 times.
✓ Branch 3 (19→21) taken 144 times.
600 if (sourceFile->getNameRegistryEntry(fqFctName))
81 456 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 144 times.
✗ Branch 1 (21→126) not taken.
144 const size_t fieldCount = structScope->getFieldCount();
85 144 bool hasFieldsWithDefaultValue = false;
86 144 bool hasFieldsToConstruct = false;
87
2/2
✓ Branch 0 (77→23) taken 310 times.
✓ Branch 1 (77→78) taken 138 times.
448 for (size_t i = 0; i < fieldCount; i++) {
88
1/2
✗ Branch 0 (23→24) not taken.
✓ Branch 1 (23→25) taken 310 times.
310 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
89
1/2
✗ Branch 0 (28→29) not taken.
✓ Branch 1 (28→30) taken 310 times.
310 assert(fieldSymbol != nullptr);
90
1/2
✓ Branch 0 (30→31) taken 310 times.
✗ Branch 1 (30→114) not taken.
310 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 310 times.
✗ Branch 1 (31→114) not taken.
✓ Branch 2 (32→33) taken 5 times.
✓ Branch 3 (32→34) taken 305 times.
310 if (thisType.isRef())
94 6 return;
95
96
3/4
✓ Branch 0 (34→35) taken 305 times.
✗ Branch 1 (34→36) not taken.
✓ Branch 2 (37→38) taken 284 times.
✓ Branch 3 (37→39) taken 21 times.
305 if (const auto fieldNode = dynamic_cast<FieldNode *>(fieldSymbol->declNode)) {
97 284 hasFieldsWithDefaultValue |= fieldNode->defaultValue != nullptr;
98 } else {
99
2/4
✓ Branch 0 (39→40) taken 21 times.
✗ Branch 1 (39→41) not taken.
✗ Branch 2 (42→43) not taken.
✓ Branch 3 (42→44) taken 21 times.
21 assert(dynamic_cast<DataTypeNode *>(fieldSymbol->declNode) != nullptr);
100 }
101
102
1/2
✓ Branch 0 (44→45) taken 305 times.
✗ Branch 1 (44→114) not taken.
305 const QualType fieldType = fieldSymbol->getQualType();
103
3/4
✓ Branch 0 (45→46) taken 305 times.
✗ Branch 1 (45→114) not taken.
✓ Branch 2 (46→47) taken 24 times.
✓ Branch 3 (46→75) taken 281 times.
305 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 30 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.
138 if (!hasFieldsWithDefaultValue && !hasFieldsToConstruct && !node->emitVTable)
120 91 return;
121
122 // Create the default ctor function
123
1/2
✓ Branch 0 (82→83) taken 47 times.
✗ Branch 1 (82→126) not taken.
47 const std::string entryName = Function::getSymbolTableEntryNameDefaultCtor(node->codeLoc);
124
2/4
✓ Branch 0 (86→87) taken 47 times.
✗ Branch 1 (86→117) not taken.
✓ Branch 2 (87→88) taken 47 times.
✗ Branch 3 (87→115) not taken.
141 createDefaultStructMethod(spiceStruct, entryName, CTOR_FUNCTION_NAME, {});
125
2/2
✓ Branch 0 (94→95) taken 47 times.
✓ Branch 1 (94→97) taken 553 times.
600 }
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 600 void TypeChecker::createDefaultCopyCtorIfRequired(const Struct &spiceStruct, Scope *structScope) {
138
1/2
✓ Branch 0 (2→3) taken 600 times.
✗ Branch 1 (2→4) not taken.
600 const auto node = spice_pointer_cast<const StructDefNode *>(spiceStruct.declNode);
139
2/4
✓ Branch 0 (9→10) taken 600 times.
✗ Branch 1 (9→12) not taken.
✓ Branch 2 (10→11) taken 600 times.
✗ Branch 3 (10→12) not taken.
600 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 600 times.
✗ Branch 1 (13→153) not taken.
600 const QualType structType = spiceStruct.entry->getQualType();
143
2/4
✓ Branch 0 (14→15) taken 600 times.
✗ Branch 1 (14→111) not taken.
✓ Branch 2 (18→19) taken 600 times.
✗ Branch 3 (18→107) not taken.
1800 const ArgList lookupArgs = {{structType.toConstRef(node), true}};
144
2/4
✓ Branch 0 (22→23) taken 600 times.
✗ Branch 1 (22→115) not taken.
✓ Branch 2 (23→24) taken 600 times.
✗ Branch 3 (23→113) not taken.
600 const Function *copyCtor = FunctionManager::lookup(structScope, CTOR_FUNCTION_NAME, structType, lookupArgs, true);
145
2/2
✓ Branch 0 (26→27) taken 114 times.
✓ Branch 1 (26→28) taken 486 times.
600 if (copyCtor != nullptr)
146 114 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 486 times.
✗ Branch 1 (28→151) not taken.
486 const size_t fieldCount = structScope->getFieldCount();
153 486 bool copyCtorRequired = false;
154
2/2
✓ Branch 0 (82→30) taken 1029 times.
✓ Branch 1 (82→83) taken 478 times.
1507 for (size_t i = 0; i < fieldCount; i++) {
155
1/2
✗ Branch 0 (30→31) not taken.
✓ Branch 1 (30→32) taken 1029 times.
1029 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
156
1/2
✓ Branch 0 (35→36) taken 1029 times.
✗ Branch 1 (35→151) not taken.
1029 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 1029 times.
✗ Branch 1 (36→151) not taken.
✓ Branch 2 (37→38) taken 138 times.
✓ Branch 3 (37→75) taken 891 times.
1029 if (fieldType.is(TY_STRUCT)) {
160
1/2
✓ Branch 0 (38→39) taken 138 times.
✗ Branch 1 (38→136) not taken.
138 Scope *bodyScope = fieldType.getBodyScope();
161
1/2
✓ Branch 0 (39→40) taken 138 times.
✗ Branch 1 (39→136) not taken.
138 const Struct *fieldStruct = fieldType.getStruct(node);
162 // Check if we are required to call a ctor
163
1/2
✓ Branch 0 (40→41) taken 138 times.
✗ Branch 1 (40→42) not taken.
138 const auto structDeclNode = spice_pointer_cast<StructDefNode *>(fieldStruct->declNode);
164
5/6
✓ Branch 0 (47→48) taken 138 times.
✗ Branch 1 (47→136) not taken.
✓ Branch 2 (48→49) taken 132 times.
✓ Branch 3 (48→50) taken 6 times.
✓ Branch 4 (49→50) taken 31 times.
✓ Branch 5 (49→51) taken 101 times.
138 const bool isCtorCallRequired = bodyScope->hasRefFields() || structDeclNode->emitVTable;
165 // Lookup copy ctor function
166
2/4
✓ Branch 0 (52→53) taken 138 times.
✗ Branch 1 (52→123) not taken.
✓ Branch 2 (56→57) taken 138 times.
✗ Branch 3 (56→119) not taken.
276 const ArgList args = {{fieldType.toConstRef(node), false /* we always have the field as storage */}};
167
2/4
✓ Branch 0 (61→62) taken 138 times.
✗ Branch 1 (61→127) not taken.
✓ Branch 2 (62→63) taken 138 times.
✗ Branch 3 (62→125) not taken.
414 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 70 times.
✓ Branch 1 (66→69) taken 68 times.
✓ Branch 2 (67→68) taken 8 times.
✓ Branch 3 (67→69) taken 62 times.
138 if (!ctorFct && isCtorCallRequired)
170 8 return;
171 130 copyCtorRequired |= ctorFct != nullptr;
172
2/2
✓ Branch 0 (71→72) taken 130 times.
✓ Branch 1 (71→74) taken 8 times.
138 }
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 1021 times.
✗ Branch 1 (75→151) not taken.
✓ Branch 2 (76→77) taken 22 times.
✓ Branch 3 (76→81) taken 999 times.
1021 if (fieldType.isHeap()) {
176
2/4
✓ Branch 0 (77→78) taken 22 times.
✗ Branch 1 (77→151) not taken.
✗ Branch 2 (78→79) not taken.
✓ Branch 3 (78→80) taken 22 times.
22 assert(fieldType.isPtr());
177 22 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 417 times.
✓ Branch 1 (83→86) taken 61 times.
✓ Branch 2 (84→85) taken 307 times.
✓ Branch 3 (84→86) taken 110 times.
478 if (!copyCtorRequired && !node->emitVTable)
183 307 return;
184
185 // Create the default copy ctor function
186
1/2
✓ Branch 0 (86→87) taken 171 times.
✗ Branch 1 (86→151) not taken.
171 const std::string entryName = Function::getSymbolTableEntryNameDefaultCopyCtor(node->codeLoc);
187
2/4
✓ Branch 0 (87→88) taken 171 times.
✗ Branch 1 (87→140) not taken.
✓ Branch 2 (90→91) taken 171 times.
✗ Branch 3 (90→137) not taken.
513 const ParamList paramTypes = {{structType.toConstRef(node), false}};
188
2/4
✓ Branch 0 (94→95) taken 171 times.
✗ Branch 1 (94→143) not taken.
✓ Branch 2 (95→96) taken 171 times.
✗ Branch 3 (95→141) not taken.
171 createDefaultStructMethod(spiceStruct, entryName, CTOR_FUNCTION_NAME, paramTypes);
189
2/2
✓ Branch 0 (102→103) taken 171 times.
✓ Branch 1 (102→105) taken 429 times.
600 }
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 600 void TypeChecker::createDefaultDtorIfRequired(const Struct &spiceStruct, Scope *structScope) {
201 600 const ASTNode *node = spiceStruct.declNode;
202
2/4
✓ Branch 0 (2→3) taken 600 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 600 times.
✗ Branch 3 (3→5) not taken.
600 assert(structScope != nullptr && structScope->type == ScopeType::STRUCT);
203
204 // Abort if the struct already has a user-defined destructor
205 600 const SymbolTableEntry *structEntry = spiceStruct.entry;
206
1/2
✓ Branch 0 (6→7) taken 600 times.
✗ Branch 1 (6→143) not taken.
600 const QualType &structType = structEntry->getQualType();
207
3/6
✓ Branch 0 (7→8) taken 600 times.
✗ Branch 1 (7→98) not taken.
✓ Branch 2 (8→9) taken 600 times.
✗ Branch 3 (8→98) not taken.
✓ Branch 4 (9→10) taken 600 times.
✗ Branch 5 (9→96) not taken.
600 const std::string fqFctName = structType.getSubType() + MEMBER_ACCESS_TOKEN + DTOR_FUNCTION_NAME;
208
3/4
✓ Branch 0 (11→12) taken 600 times.
✗ Branch 1 (11→141) not taken.
✓ Branch 2 (12→13) taken 103 times.
✓ Branch 3 (12→14) taken 497 times.
600 if (sourceFile->getNameRegistryEntry(fqFctName))
209 103 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 497 times.
✗ Branch 1 (14→141) not taken.
497 const size_t fieldCount = structScope->getFieldCount();
213 497 bool hasFieldsToDeAllocate = false;
214 497 bool hasFieldsToDestruct = false;
215
2/2
✓ Branch 0 (41→16) taken 1119 times.
✓ Branch 1 (41→42) taken 497 times.
1616 for (size_t i = 0; i < fieldCount; i++) {
216
1/2
✗ Branch 0 (16→17) not taken.
✓ Branch 1 (16→18) taken 1119 times.
1119 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
217
2/4
✓ Branch 0 (21→22) taken 1119 times.
✗ Branch 1 (21→141) not taken.
✓ Branch 2 (22→23) taken 1119 times.
✗ Branch 3 (22→141) not taken.
1119 hasFieldsToDeAllocate |= fieldSymbol->getQualType().needsDeAllocation();
218
4/6
✓ Branch 0 (23→24) taken 1119 times.
✗ Branch 1 (23→141) not taken.
✓ Branch 2 (24→25) taken 1119 times.
✗ Branch 3 (24→141) not taken.
✓ Branch 4 (25→26) taken 138 times.
✓ Branch 5 (25→40) taken 981 times.
1119 if (fieldSymbol->getQualType().is(TY_STRUCT)) {
219
2/4
✓ Branch 0 (26→27) taken 138 times.
✗ Branch 1 (26→141) not taken.
✓ Branch 2 (27→28) taken 138 times.
✗ Branch 3 (27→141) not taken.
138 Scope *fieldScope = fieldSymbol->getQualType().getBodyScope();
220 // Lookup dtor function
221
1/2
✓ Branch 0 (28→29) taken 138 times.
✗ Branch 1 (28→141) not taken.
138 const QualType &thisType = fieldSymbol->getQualType();
222
2/4
✓ Branch 0 (33→34) taken 138 times.
✗ Branch 1 (33→101) not taken.
✓ Branch 2 (34→35) taken 138 times.
✗ Branch 3 (34→99) not taken.
414 const Function *dtorFct = FunctionManager::match(this, fieldScope, DTOR_FUNCTION_NAME, thisType, {}, {}, true, node);
223 138 hasFieldsToDestruct |= dtorFct != nullptr;
224
1/2
✓ Branch 0 (39→40) taken 138 times.
✗ Branch 1 (39→141) not taken.
138 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 452 times.
✓ Branch 1 (42→45) taken 45 times.
✓ Branch 2 (43→44) taken 415 times.
✓ Branch 3 (43→45) taken 37 times.
497 if (!hasFieldsToDeAllocate && !hasFieldsToDestruct)
230 415 return;
231
232 // Create the default dtor function
233
1/2
✓ Branch 0 (45→46) taken 82 times.
✗ Branch 1 (45→141) not taken.
82 const std::string entryName = Function::getSymbolTableEntryNameDefaultDtor(node->codeLoc);
234
2/4
✓ Branch 0 (49→50) taken 82 times.
✗ Branch 1 (49→113) not taken.
✓ Branch 2 (50→51) taken 82 times.
✗ Branch 3 (50→111) not taken.
246 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 45 times.
✓ Branch 1 (54→60) taken 37 times.
✓ Branch 2 (55→56) taken 45 times.
✗ Branch 3 (55→139) not taken.
✓ Branch 4 (58→59) taken 45 times.
✗ Branch 5 (58→60) not taken.
✓ Branch 6 (61→62) taken 45 times.
✓ Branch 7 (61→88) taken 37 times.
127 if (hasFieldsToDeAllocate && !sourceFile->isStringRT()) {
239
1/2
✓ Branch 0 (62→63) taken 45 times.
✗ Branch 1 (62→138) not taken.
45 const SourceFile *memoryRT = sourceFile->requestRuntimeModule(MEMORY_RT);
240
1/2
✗ Branch 0 (63→64) not taken.
✓ Branch 1 (63→65) taken 45 times.
45 assert(memoryRT != nullptr);
241 45 Scope *matchScope = memoryRT->globalScope.get();
242 // Set dealloc function to used
243
1/2
✓ Branch 0 (66→67) taken 45 times.
✗ Branch 1 (66→138) not taken.
45 const QualType thisType(TY_DYN);
244
3/6
✓ Branch 0 (67→68) taken 45 times.
✗ Branch 1 (67→120) not taken.
✓ Branch 2 (68→69) taken 45 times.
✗ Branch 3 (68→120) not taken.
✓ Branch 4 (69→70) taken 45 times.
✗ Branch 5 (69→120) not taken.
45 QualType bytePtrRefType = QualType(TY_BYTE).toPtr(node).toRef(node);
245
1/2
✓ Branch 0 (70→71) taken 45 times.
✗ Branch 1 (70→138) not taken.
45 bytePtrRefType.makeHeap();
246
1/2
✓ Branch 0 (74→75) taken 45 times.
✗ Branch 1 (74→122) not taken.
90 const ArgList args = {{bytePtrRefType, false /* we always have the field as storage */}};
247
2/4
✓ Branch 0 (79→80) taken 45 times.
✗ Branch 1 (79→129) not taken.
✓ Branch 2 (80→81) taken 45 times.
✗ Branch 3 (80→127) not taken.
135 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 45 times.
45 assert(deallocFct != nullptr);
249 45 deallocFct->used = true;
250 45 }
251
2/2
✓ Branch 0 (91→92) taken 82 times.
✓ Branch 1 (91→94) taken 518 times.
600 }
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 1229 void TypeChecker::createCtorBodyPreamble(const Scope *bodyScope) {
258 // Retrieve struct scope
259 1229 Scope *structScope = bodyScope->parent;
260
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 1229 times.
1229 assert(structScope != nullptr);
261
262 1229 const size_t fieldCount = structScope->getFieldCount();
263
2/2
✓ Branch 0 (49→6) taken 3123 times.
✓ Branch 1 (49→50) taken 1229 times.
4352 for (size_t i = 0; i < fieldCount; i++) {
264
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 3123 times.
3123 SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
265
3/6
✓ Branch 0 (11→12) taken 3123 times.
✗ Branch 1 (11→15) not taken.
✓ Branch 2 (12→13) taken 3123 times.
✗ Branch 3 (12→64) not taken.
✓ Branch 4 (13→14) taken 3123 times.
✗ Branch 5 (13→15) not taken.
3123 assert(fieldSymbol != nullptr && fieldSymbol->isField());
266
2/2
✓ Branch 0 (16→17) taken 194 times.
✓ Branch 1 (16→18) taken 2929 times.
3123 if (fieldSymbol->isImplicitField)
267 194 continue;
268
1/2
✓ Branch 0 (18→19) taken 2929 times.
✗ Branch 1 (18→64) not taken.
2929 QualType fieldType = fieldSymbol->getQualType();
269
3/4
✓ Branch 0 (19→20) taken 2929 times.
✗ Branch 1 (19→64) not taken.
✓ Branch 2 (20→21) taken 416 times.
✓ Branch 3 (20→22) taken 2513 times.
2929 if (fieldType.hasAnyGenericParts())
270
1/2
✓ Branch 0 (21→22) taken 416 times.
✗ Branch 1 (21→64) not taken.
416 TypeMatcher::substantiateTypeWithTypeMapping(fieldType, typeMapping, fieldSymbol->declNode);
271
272
3/4
✓ Branch 0 (22→23) taken 2929 times.
✗ Branch 1 (22→64) not taken.
✓ Branch 2 (23→24) taken 372 times.
✓ Branch 3 (23→47) taken 2557 times.
2929 if (fieldType.is(TY_STRUCT)) {
273
1/2
✓ Branch 0 (24→25) taken 372 times.
✗ Branch 1 (24→26) not taken.
372 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 372 times.
✗ Branch 1 (31→64) not taken.
372 Scope *matchScope = fieldType.getBodyScope();
276 const Function *spiceFunc =
277
2/4
✓ Branch 0 (36→37) taken 372 times.
✗ Branch 1 (36→53) not taken.
✓ Branch 2 (37→38) taken 372 times.
✗ Branch 3 (37→51) not taken.
1116 FunctionManager::match(this, matchScope, CTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
278
2/2
✓ Branch 0 (42→43) taken 330 times.
✓ Branch 1 (42→47) taken 42 times.
372 if (spiceFunc != nullptr)
279
3/6
✓ Branch 0 (43→44) taken 330 times.
✗ Branch 1 (43→63) not taken.
✓ Branch 2 (44→45) taken 330 times.
✗ Branch 3 (44→63) not taken.
✓ Branch 4 (45→46) taken 330 times.
✗ Branch 5 (45→63) not taken.
330 fieldSymbol->updateType(fieldType.getWithBodyScope(spiceFunc->thisType.getBodyScope()), true);
280 }
281 }
282 1229 }
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 131 void TypeChecker::createCopyCtorBodyPreamble(const Scope *bodyScope) {
289 // Retrieve struct scope
290 131 Scope *structScope = bodyScope->parent;
291
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 131 times.
131 assert(structScope != nullptr);
292
293 131 const size_t fieldCount = structScope->getFieldCount();
294
2/2
✓ Branch 0 (55→6) taken 280 times.
✓ Branch 1 (55→56) taken 131 times.
411 for (size_t i = 0; i < fieldCount; i++) {
295
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 280 times.
280 SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
296
3/6
✓ Branch 0 (11→12) taken 280 times.
✗ Branch 1 (11→15) not taken.
✓ Branch 2 (12→13) taken 280 times.
✗ Branch 3 (12→76) not taken.
✓ Branch 4 (13→14) taken 280 times.
✗ Branch 5 (13→15) not taken.
280 assert(fieldSymbol != nullptr && fieldSymbol->isField());
297
2/2
✓ Branch 0 (16→17) taken 31 times.
✓ Branch 1 (16→18) taken 249 times.
280 if (fieldSymbol->isImplicitField)
298 31 continue;
299
300
1/2
✓ Branch 0 (18→19) taken 249 times.
✗ Branch 1 (18→76) not taken.
249 QualType fieldType = fieldSymbol->getQualType();
301
2/4
✓ Branch 0 (19→20) taken 249 times.
✗ Branch 1 (19→76) not taken.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→22) taken 249 times.
249 if (fieldType.hasAnyGenericParts())
302 TypeMatcher::substantiateTypeWithTypeMapping(fieldType, typeMapping, fieldSymbol->declNode);
303
304
3/4
✓ Branch 0 (22→23) taken 249 times.
✗ Branch 1 (22→76) not taken.
✓ Branch 2 (23→24) taken 115 times.
✓ Branch 3 (23→53) taken 134 times.
249 if (fieldType.is(TY_STRUCT)) {
305
1/2
✓ Branch 0 (24→25) taken 115 times.
✗ Branch 1 (24→26) not taken.
115 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 115 times.
✗ Branch 1 (31→75) not taken.
115 Scope *matchScope = fieldType.getBodyScope();
308
2/4
✓ Branch 0 (32→33) taken 115 times.
✗ Branch 1 (32→61) not taken.
✓ Branch 2 (36→37) taken 115 times.
✗ Branch 3 (36→57) not taken.
230 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 115 times.
✗ Branch 1 (41→65) not taken.
✓ Branch 2 (42→43) taken 115 times.
✗ Branch 3 (42→63) not taken.
345 FunctionManager::match(this, matchScope, CTOR_FUNCTION_NAME, fieldType, args, {}, false, fieldNode);
311
2/2
✓ Branch 0 (46→47) taken 104 times.
✓ Branch 1 (46→51) taken 11 times.
115 if (copyCtorFct != nullptr)
312
3/6
✓ Branch 0 (47→48) taken 104 times.
✗ Branch 1 (47→72) not taken.
✓ Branch 2 (48→49) taken 104 times.
✗ Branch 3 (48→72) not taken.
✓ Branch 4 (49→50) taken 104 times.
✗ Branch 5 (49→72) not taken.
104 fieldSymbol->updateType(fieldType.getWithBodyScope(copyCtorFct->thisType.getBodyScope()), true);
313 115 }
314 }
315 131 }
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 181 void TypeChecker::createDtorBodyPreamble(const Scope *bodyScope) {
321 // Retrieve struct scope
322 181 Scope *structScope = bodyScope->parent;
323
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 181 times.
181 assert(structScope != nullptr);
324
325 181 const size_t fieldCount = structScope->getFieldCount();
326
2/2
✓ Branch 0 (45→6) taken 652 times.
✓ Branch 1 (45→46) taken 181 times.
833 for (size_t i = 0; i < fieldCount; i++) {
327
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 652 times.
652 const SymbolTableEntry *fieldSymbol = structScope->lookupField(i);
328
3/6
✓ Branch 0 (11→12) taken 652 times.
✗ Branch 1 (11→15) not taken.
✓ Branch 2 (12→13) taken 652 times.
✗ Branch 3 (12→59) not taken.
✓ Branch 4 (13→14) taken 652 times.
✗ Branch 5 (13→15) not taken.
652 assert(fieldSymbol != nullptr && fieldSymbol->isField());
329
2/2
✓ Branch 0 (16→17) taken 110 times.
✓ Branch 1 (16→18) taken 542 times.
652 if (fieldSymbol->isImplicitField)
330 110 continue;
331
1/2
✓ Branch 0 (18→19) taken 542 times.
✗ Branch 1 (18→59) not taken.
542 QualType fieldType = fieldSymbol->getQualType();
332
2/4
✓ Branch 0 (19→20) taken 542 times.
✗ Branch 1 (19→59) not taken.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→22) taken 542 times.
542 if (fieldType.hasAnyGenericParts())
333 TypeMatcher::substantiateTypeWithTypeMapping(fieldType, typeMapping, fieldSymbol->declNode);
334
335
3/4
✓ Branch 0 (22→23) taken 542 times.
✗ Branch 1 (22→59) not taken.
✓ Branch 2 (23→24) taken 140 times.
✓ Branch 3 (23→43) taken 402 times.
542 if (fieldType.is(TY_STRUCT)) {
336
1/2
✓ Branch 0 (24→25) taken 140 times.
✗ Branch 1 (24→26) not taken.
140 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 140 times.
✗ Branch 1 (31→59) not taken.
140 Scope *matchScope = fieldType.getBodyScope();
339
2/4
✓ Branch 0 (36→37) taken 140 times.
✗ Branch 1 (36→49) not taken.
✓ Branch 2 (37→38) taken 140 times.
✗ Branch 3 (37→47) not taken.
420 FunctionManager::match(this, matchScope, DTOR_FUNCTION_NAME, fieldType, {}, {}, false, fieldNode);
340 }
341 }
342 181 }
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 1263 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 1263 times.
✗ Branch 1 (2→9) not taken.
✓ Branch 2 (3→4) taken 1263 times.
✗ Branch 3 (3→9) not taken.
✓ Branch 4 (4→5) taken 1263 times.
✗ Branch 5 (4→9) not taken.
1263 const QualType thisType = entry->getQualType().removeReferenceWrapper().toNonConst();
355
1/2
✓ Branch 0 (5→6) taken 1263 times.
✗ Branch 1 (5→10) not taken.
2526 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 1473 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 1473 times.
1473 assert(thisType.is(TY_STRUCT));
369 1473 Scope *matchScope = thisType.getBodyScope();
370
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 1473 times.
1473 assert(matchScope->type == ScopeType::STRUCT);
371
372 // Search for dtor
373
2/2
✓ Branch 0 (9→10) taken 778 times.
✓ Branch 1 (9→12) taken 695 times.
1473 if (matchScope->isImportedBy(rootScope))
374
1/2
✓ Branch 0 (10→11) taken 778 times.
✗ Branch 1 (10→18) not taken.
778 thisType = mapLocalTypeToImportedScopeType(matchScope, thisType);
375
1/2
✓ Branch 0 (13→14) taken 1473 times.
✗ Branch 1 (13→19) not taken.
1473 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 210 Function *TypeChecker::implicitlyCallStructCopyCtor(const QualType &thisType, const ASTNode *node) {
396
2/4
✓ Branch 0 (2→3) taken 210 times.
✗ Branch 1 (2→19) not taken.
✓ Branch 2 (3→4) taken 210 times.
✗ Branch 3 (3→19) not taken.
210 const QualType argType = thisType.removeReferenceWrapper().toConstRef(node);
397
1/2
✓ Branch 0 (7→8) taken 210 times.
✗ Branch 1 (7→20) not taken.
630 const ArgList args = {{argType, false /* we always have an entry here */}};
398
2/4
✓ Branch 0 (11→12) taken 210 times.
✗ Branch 1 (11→27) not taken.
✓ Branch 2 (12→13) taken 210 times.
✗ Branch 3 (12→25) not taken.
420 return implicitlyCallStructMethod(thisType, CTOR_FUNCTION_NAME, args, node);
399 210 }
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 1263 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 1263 times.
✗ Branch 1 (5→16) not taken.
✓ Branch 2 (6→7) taken 1263 times.
✗ Branch 3 (6→14) not taken.
✓ Branch 4 (10→11) taken 939 times.
✓ Branch 5 (10→13) taken 324 times.
3789 if (Function *dtor = implicitlyCallStructMethod(entry, DTOR_FUNCTION_NAME, {}, node))
410
2/4
✓ Branch 0 (11→12) taken 939 times.
✗ Branch 1 (11→23) not taken.
✓ Branch 2 (12→13) taken 939 times.
✗ Branch 3 (12→23) not taken.
939 node->resourcesToCleanup.at(manIdx).dtorFunctionsToCall.emplace_back(entry, dtor);
411 1263 }
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 17224 void TypeChecker::doScopeCleanup(StmtLstNode *node) {
438 // Get all variables, that are approved for de-allocation
439
1/2
✓ Branch 0 (2→3) taken 17224 times.
✗ Branch 1 (2→61) not taken.
17224 std::vector<SymbolTableEntry *> vars = currentScope->getVarsGoingOutOfScope();
440 // Sort by reverse declaration order
441
2/2
✓ Branch 0 (2→3) taken 147 times.
✓ Branch 1 (2→4) taken 6094 times.
12482 auto comp = [](const SymbolTableEntry *a, const SymbolTableEntry *b) { return a->declNode->codeLoc > b->declNode->codeLoc; };
442
1/2
✓ Branch 0 (3→4) taken 17224 times.
✗ Branch 1 (3→59) not taken.
17224 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 7337 times.
✓ Branch 1 (54→55) taken 17224 times.
24561 for (SymbolTableEntry *var : vars) {
445 // Check if we have a heap-allocated pointer
446
10/14
✓ Branch 0 (7→8) taken 7337 times.
✗ Branch 1 (7→57) not taken.
✓ Branch 2 (8→9) taken 7337 times.
✗ Branch 3 (8→57) not taken.
✓ Branch 4 (9→10) taken 1008 times.
✓ Branch 5 (9→14) taken 6329 times.
✓ Branch 6 (10→11) taken 1008 times.
✗ Branch 7 (10→57) not taken.
✓ Branch 8 (11→12) taken 1008 times.
✗ Branch 9 (11→57) not taken.
✓ Branch 10 (12→13) taken 981 times.
✓ Branch 11 (12→14) taken 27 times.
✓ Branch 12 (15→16) taken 981 times.
✓ Branch 13 (15→35) taken 6356 times.
7337 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 981 times.
✗ Branch 1 (16→58) not taken.
✓ Branch 2 (19→20) taken 861 times.
✓ Branch 3 (19→24) taken 120 times.
✓ Branch 4 (20→21) taken 861 times.
✗ Branch 5 (20→58) not taken.
✓ Branch 6 (23→24) taken 830 times.
✓ Branch 7 (23→25) taken 31 times.
✓ Branch 8 (26→27) taken 950 times.
✓ Branch 9 (26→28) taken 31 times.
2823 if (sourceFile->isMemoryRT() || sourceFile->isStringRT())
450 950 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 31 times.
✗ Branch 1 (29→58) not taken.
✓ Branch 2 (30→31) taken 28 times.
✓ Branch 3 (30→32) taken 3 times.
31 if (!var->getLifecycle().isInOwningState())
453 28 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 6359 times.
✗ Branch 1 (35→58) not taken.
✓ Branch 2 (36→37) taken 6359 times.
✗ Branch 3 (36→58) not taken.
✓ Branch 4 (37→38) taken 1360 times.
✓ Branch 5 (37→39) taken 4999 times.
✓ Branch 6 (38→39) taken 97 times.
✓ Branch 7 (38→40) taken 1263 times.
✓ Branch 8 (41→42) taken 5096 times.
✓ Branch 9 (41→43) taken 1263 times.
6359 if (!var->getQualType().is(TY_STRUCT) || var->omitDtorCall)
460 5096 continue;
461 // Variable must be either initialized or a struct field
462
3/8
✓ Branch 0 (44→45) taken 1263 times.
✗ Branch 1 (44→58) not taken.
✗ Branch 2 (45→46) not taken.
✓ Branch 3 (45→48) taken 1263 times.
✗ Branch 4 (46→47) not taken.
✗ Branch 5 (46→48) not taken.
✗ Branch 6 (49→50) not taken.
✓ Branch 7 (49→51) taken 1263 times.
1263 if (!var->getLifecycle().isInitialized() && var->scope->type != ScopeType::STRUCT)
463 continue;
464 // Call dtor
465
1/2
✓ Branch 0 (51→52) taken 1263 times.
✗ Branch 1 (51→58) not taken.
1263 implicitlyCallStructDtor(var, node);
466 }
467 17224 }
468
469 } // namespace spice::compiler
470