GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 90.7% 68 / 0 / 75
Functions: 100.0% 13 / 0 / 13
Branches: 62.0% 57 / 0 / 92

src/typechecker/TypeCheckerTopLevelDefinitions.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "TypeChecker.h"
4
5 #include <ast/ASTNodes.h>
6 #include <global/TypeRegistry.h>
7
8 namespace spice::compiler {
9
10 2613 std::any TypeChecker::visitMainFctDef(MainFctDefNode *node) {
11
2/2
✓ Branch 2 → 3 taken 1225 times.
✓ Branch 2 → 4 taken 1388 times.
2613 if (typeCheckerMode == TC_MODE_PRE)
12 1225 return visitMainFctDefPrepare(node);
13 else
14 1388 return visitMainFctDefCheck(node);
15 }
16
17 204124 std::any TypeChecker::visitFctDef(FctDefNode *node) {
18
2/2
✓ Branch 2 → 3 taken 65722 times.
✓ Branch 2 → 4 taken 138402 times.
204124 if (typeCheckerMode == TC_MODE_PRE)
19 65722 return visitFctDefPrepare(node);
20 else
21 138402 return visitFctDefCheck(node);
22 }
23
24 114221 std::any TypeChecker::visitProcDef(ProcDefNode *node) {
25
2/2
✓ Branch 2 → 3 taken 35747 times.
✓ Branch 2 → 4 taken 78474 times.
114221 if (typeCheckerMode == TC_MODE_PRE)
26 35747 return visitProcDefPrepare(node);
27 else
28 78474 return visitProcDefCheck(node);
29 }
30
31 28575 std::any TypeChecker::visitStructDef(StructDefNode *node) {
32
2/2
✓ Branch 2 → 3 taken 9653 times.
✓ Branch 2 → 4 taken 18922 times.
28575 if (typeCheckerMode == TC_MODE_PRE)
33 9653 return visitStructDefPrepare(node);
34 else
35 18922 return visitStructDefCheck(node);
36 }
37
38 2351 std::any TypeChecker::visitInterfaceDef(InterfaceDefNode *node) {
39
2/2
✓ Branch 2 → 3 taken 1015 times.
✓ Branch 2 → 4 taken 1336 times.
2351 if (typeCheckerMode == TC_MODE_PRE)
40 1015 return visitInterfaceDefPrepare(node);
41
1/2
✓ Branch 4 → 5 taken 1336 times.
✗ Branch 4 → 8 not taken.
2672 return nullptr;
42 }
43
44 184 std::any TypeChecker::visitUnionDef(UnionDefNode *node) {
45
2/2
✓ Branch 2 → 3 taken 74 times.
✓ Branch 2 → 4 taken 110 times.
184 if (typeCheckerMode == TC_MODE_PRE)
46 74 return visitUnionDefPrepare(node);
47 else
48 110 return visitUnionDefCheck(node);
49 }
50
51 /**
52 * Assign the opaque type to a struct, interface, enum or alias that is referenced before it has been prepared. This
53 * effectively acts as an implicit forward declaration and is what makes circular imports work: two types in mutually
54 * importing files can reference each other, so neither can be prepared strictly before the other. The full prepare pass
55 * (visitStructDefPrepare / visitInterfaceDefPrepare / visitEnumDefPrepare / visitAliasDefPrepare) assigns the identical
56 * interned type later and additionally fills in the body scope and manifestations.
57 *
58 * Only non-generic structs/interfaces can be pre-declared this way, since the opaque type carries no template types.
59 *
60 * @param entry Symbol table entry of the referenced struct, interface, enum or alias (its type must still be invalid)
61 */
62 2708 void TypeChecker::assignDeferredOpaqueType(SymbolTableEntry *entry) {
63
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2708 times.
2708 assert(entry->getQualType().is(TY_INVALID));
64 2708 ASTNode *declNode = entry->declNode;
65
3/4
✓ Branch 6 → 7 taken 2708 times.
✗ Branch 6 → 8 not taken.
✓ Branch 9 → 10 taken 2548 times.
✓ Branch 9 → 18 taken 160 times.
2708 if (const auto *structDef = dynamic_cast<StructDefNode *>(declNode)) {
66
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 2548 times.
2548 if (structDef->hasTemplateTypes)
67 ✗ return;
68 2548 const TypeChainElementData data = {.bodyScope = structDef->structScope};
69
1/2
✓ Branch 13 → 14 taken 2548 times.
✗ Branch 13 → 60 not taken.
2548 const Type *type = TypeRegistry::getOrInsert(TY_STRUCT, structDef->structName, structDef->typeId, data, {});
70
2/4
✓ Branch 15 → 16 taken 2548 times.
✗ Branch 15 → 63 not taken.
✓ Branch 16 → 17 taken 2548 times.
✗ Branch 16 → 63 not taken.
2548 entry->updateType(QualType(type, structDef->qualifiers), false);
71
3/4
✓ Branch 18 → 19 taken 160 times.
✗ Branch 18 → 20 not taken.
✓ Branch 21 → 22 taken 152 times.
✓ Branch 21 → 30 taken 8 times.
160 } else if (const auto *interfaceDef = dynamic_cast<InterfaceDefNode *>(declNode)) {
72
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 152 times.
152 if (interfaceDef->hasTemplateTypes)
73 ✗ return;
74 152 const TypeChainElementData data = {.bodyScope = interfaceDef->interfaceScope};
75
1/2
✓ Branch 25 → 26 taken 152 times.
✗ Branch 25 → 65 not taken.
152 const Type *type = TypeRegistry::getOrInsert(TY_INTERFACE, interfaceDef->interfaceName, interfaceDef->typeId, data, {});
76
2/4
✓ Branch 27 → 28 taken 152 times.
✗ Branch 27 → 68 not taken.
✓ Branch 28 → 29 taken 152 times.
✗ Branch 28 → 68 not taken.
152 entry->updateType(QualType(type, interfaceDef->qualifiers), false);
77
2/4
✓ Branch 30 → 31 taken 8 times.
✗ Branch 30 → 32 not taken.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 42 taken 8 times.
8 } else if (const auto *unionDef = dynamic_cast<UnionDefNode *>(declNode)) {
78 ✗ if (unionDef->hasTemplateTypes)
79 ✗ return;
80 ✗ const TypeChainElementData data = {.bodyScope = unionDef->unionScope};
81 ✗ const Type *type = TypeRegistry::getOrInsert(TY_UNION, unionDef->unionName, unionDef->typeId, data, {});
82 ✗ entry->updateType(QualType(type, unionDef->qualifiers), false);
83
3/4
✓ Branch 42 → 43 taken 8 times.
✗ Branch 42 → 44 not taken.
✓ Branch 45 → 46 taken 6 times.
✓ Branch 45 → 52 taken 2 times.
8 } else if (const auto *enumDef = dynamic_cast<EnumDefNode *>(declNode)) {
84 6 const TypeChainElementData data = {.bodyScope = enumDef->enumScope};
85
1/2
✓ Branch 47 → 48 taken 6 times.
✗ Branch 47 → 75 not taken.
6 const Type *type = TypeRegistry::getOrInsert(TY_ENUM, enumDef->enumName, enumDef->typeId, data, {});
86
2/4
✓ Branch 49 → 50 taken 6 times.
✗ Branch 49 → 78 not taken.
✓ Branch 50 → 51 taken 6 times.
✗ Branch 50 → 78 not taken.
6 entry->updateType(QualType(type, enumDef->qualifiers), false);
87
2/4
✓ Branch 52 → 53 taken 2 times.
✗ Branch 52 → 54 not taken.
✓ Branch 55 → 56 taken 2 times.
✗ Branch 55 → 59 not taken.
2 } else if (auto *aliasDef = dynamic_cast<AliasDefNode *>(declNode)) {
88 // An alias additionally needs its aliased type resolved, so prepare it fully on demand. visitAliasDefPrepare is
89 // idempotent: the real prepare pass for the alias's own file skips it once the type is no longer invalid.
90
1/2
✓ Branch 56 → 57 taken 2 times.
✗ Branch 56 → 80 not taken.
2 visitAliasDefPrepare(aliasDef);
91 }
92 }
93
94 5673 std::any TypeChecker::visitEnumDef(EnumDefNode *node) {
95
2/2
✓ Branch 2 → 3 taken 1964 times.
✓ Branch 2 → 4 taken 3709 times.
5673 if (typeCheckerMode == TC_MODE_PRE)
96 1964 return visitEnumDefPrepare(node);
97
1/2
✓ Branch 4 → 5 taken 3709 times.
✗ Branch 4 → 8 not taken.
7418 return nullptr;
98 }
99
100 16223 std::any TypeChecker::visitGenericTypeDef(GenericTypeDefNode *node) {
101
2/2
✓ Branch 2 → 3 taken 5137 times.
✓ Branch 2 → 4 taken 11086 times.
16223 if (typeCheckerMode == TC_MODE_PRE)
102 5137 return visitGenericTypeDefPrepare(node);
103
1/2
✓ Branch 4 → 5 taken 11086 times.
✗ Branch 4 → 8 not taken.
22172 return nullptr;
104 }
105
106 3377 std::any TypeChecker::visitAliasDef(AliasDefNode *node) {
107
2/2
✓ Branch 2 → 3 taken 1185 times.
✓ Branch 2 → 4 taken 2192 times.
3377 if (typeCheckerMode == TC_MODE_PRE)
108 1185 return visitAliasDefPrepare(node);
109
1/2
✓ Branch 4 → 5 taken 2192 times.
✗ Branch 4 → 8 not taken.
4384 return nullptr;
110 }
111
112 25863 std::any TypeChecker::visitGlobalVarDef(GlobalVarDefNode *node) {
113
2/2
✓ Branch 2 → 3 taken 10241 times.
✓ Branch 2 → 4 taken 15622 times.
25863 if (typeCheckerMode == TC_MODE_PRE)
114 10241 return visitGlobalVarDefPrepare(node);
115
1/2
✓ Branch 4 → 5 taken 15622 times.
✗ Branch 4 → 8 not taken.
31244 return nullptr;
116 }
117
118 38580 std::any TypeChecker::visitExtDecl(ExtDeclNode *node) {
119
2/2
✓ Branch 2 → 3 taken 12363 times.
✓ Branch 2 → 4 taken 26217 times.
38580 if (typeCheckerMode == TC_MODE_PRE)
120 12363 return visitExtDeclPrepare(node);
121
1/2
✓ Branch 4 → 5 taken 26217 times.
✗ Branch 4 → 8 not taken.
52434 return nullptr;
122 }
123
124 27357 std::any TypeChecker::visitImportDef(ImportDefNode *node) {
125
2/2
✓ Branch 2 → 3 taken 9466 times.
✓ Branch 2 → 4 taken 17891 times.
27357 if (typeCheckerMode == TC_MODE_PRE)
126 9466 return visitImportDefPrepare(node);
127
1/2
✓ Branch 4 → 5 taken 17891 times.
✗ Branch 4 → 8 not taken.
35782 return nullptr;
128 }
129
130 } // namespace spice::compiler
131