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 2501 std::any TypeChecker::visitMainFctDef(MainFctDefNode *node) {
11
2/2
✓ Branch 2 → 3 taken 1172 times.
✓ Branch 2 → 4 taken 1329 times.
2501 if (typeCheckerMode == TC_MODE_PRE)
12 1172 return visitMainFctDefPrepare(node);
13 else
14 1329 return visitMainFctDefCheck(node);
15 }
16
17 154472 std::any TypeChecker::visitFctDef(FctDefNode *node) {
18
2/2
✓ Branch 2 → 3 taken 48724 times.
✓ Branch 2 → 4 taken 105748 times.
154472 if (typeCheckerMode == TC_MODE_PRE)
19 48724 return visitFctDefPrepare(node);
20 else
21 105748 return visitFctDefCheck(node);
22 }
23
24 94899 std::any TypeChecker::visitProcDef(ProcDefNode *node) {
25
2/2
✓ Branch 2 → 3 taken 29248 times.
✓ Branch 2 → 4 taken 65651 times.
94899 if (typeCheckerMode == TC_MODE_PRE)
26 29248 return visitProcDefPrepare(node);
27 else
28 65651 return visitProcDefCheck(node);
29 }
30
31 22231 std::any TypeChecker::visitStructDef(StructDefNode *node) {
32
2/2
✓ Branch 2 → 3 taken 7457 times.
✓ Branch 2 → 4 taken 14774 times.
22231 if (typeCheckerMode == TC_MODE_PRE)
33 7457 return visitStructDefPrepare(node);
34 else
35 14774 return visitStructDefCheck(node);
36 }
37
38 1773 std::any TypeChecker::visitInterfaceDef(InterfaceDefNode *node) {
39
2/2
✓ Branch 2 → 3 taken 801 times.
✓ Branch 2 → 4 taken 972 times.
1773 if (typeCheckerMode == TC_MODE_PRE)
40 801 return visitInterfaceDefPrepare(node);
41
1/2
✓ Branch 4 → 5 taken 972 times.
✗ Branch 4 → 8 not taken.
1944 return nullptr;
42 }
43
44 154 std::any TypeChecker::visitUnionDef(UnionDefNode *node) {
45
2/2
✓ Branch 2 → 3 taken 64 times.
✓ Branch 2 → 4 taken 90 times.
154 if (typeCheckerMode == TC_MODE_PRE)
46 64 return visitUnionDefPrepare(node);
47 else
48 90 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 2046 void TypeChecker::assignDeferredOpaqueType(SymbolTableEntry *entry) {
63
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2046 times.
2046 assert(entry->getQualType().is(TY_INVALID));
64 2046 ASTNode *declNode = entry->declNode;
65
3/4
✓ Branch 6 → 7 taken 2046 times.
✗ Branch 6 → 8 not taken.
✓ Branch 9 → 10 taken 2012 times.
✓ Branch 9 → 18 taken 34 times.
2046 if (const auto *structDef = dynamic_cast<StructDefNode *>(declNode)) {
66
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 2012 times.
2012 if (structDef->hasTemplateTypes)
67 return;
68 2012 const TypeChainElementData data = {.bodyScope = structDef->structScope};
69
1/2
✓ Branch 13 → 14 taken 2012 times.
✗ Branch 13 → 60 not taken.
2012 const Type *type = TypeRegistry::getOrInsert(TY_STRUCT, structDef->structName, structDef->typeId, data, {});
70
2/4
✓ Branch 15 → 16 taken 2012 times.
✗ Branch 15 → 63 not taken.
✓ Branch 16 → 17 taken 2012 times.
✗ Branch 16 → 63 not taken.
2012 entry->updateType(QualType(type, structDef->qualifiers), false);
71
3/4
✓ Branch 18 → 19 taken 34 times.
✗ Branch 18 → 20 not taken.
✓ Branch 21 → 22 taken 30 times.
✓ Branch 21 → 30 taken 4 times.
34 } else if (const auto *interfaceDef = dynamic_cast<InterfaceDefNode *>(declNode)) {
72
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 30 times.
30 if (interfaceDef->hasTemplateTypes)
73 return;
74 30 const TypeChainElementData data = {.bodyScope = interfaceDef->interfaceScope};
75
1/2
✓ Branch 25 → 26 taken 30 times.
✗ Branch 25 → 65 not taken.
30 const Type *type = TypeRegistry::getOrInsert(TY_INTERFACE, interfaceDef->interfaceName, interfaceDef->typeId, data, {});
76
2/4
✓ Branch 27 → 28 taken 30 times.
✗ Branch 27 → 68 not taken.
✓ Branch 28 → 29 taken 30 times.
✗ Branch 28 → 68 not taken.
30 entry->updateType(QualType(type, interfaceDef->qualifiers), false);
77
2/4
✓ Branch 30 → 31 taken 4 times.
✗ Branch 30 → 32 not taken.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 42 taken 4 times.
4 } 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 4 times.
✗ Branch 42 → 44 not taken.
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 52 taken 2 times.
4 } else if (const auto *enumDef = dynamic_cast<EnumDefNode *>(declNode)) {
84 2 const TypeChainElementData data = {.bodyScope = enumDef->enumScope};
85
1/2
✓ Branch 47 → 48 taken 2 times.
✗ Branch 47 → 75 not taken.
2 const Type *type = TypeRegistry::getOrInsert(TY_ENUM, enumDef->enumName, enumDef->typeId, data, {});
86
2/4
✓ Branch 49 → 50 taken 2 times.
✗ Branch 49 → 78 not taken.
✓ Branch 50 → 51 taken 2 times.
✗ Branch 50 → 78 not taken.
2 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 3575 std::any TypeChecker::visitEnumDef(EnumDefNode *node) {
95
2/2
✓ Branch 2 → 3 taken 1226 times.
✓ Branch 2 → 4 taken 2349 times.
3575 if (typeCheckerMode == TC_MODE_PRE)
96 1226 return visitEnumDefPrepare(node);
97
1/2
✓ Branch 4 → 5 taken 2349 times.
✗ Branch 4 → 8 not taken.
4698 return nullptr;
98 }
99
100 14349 std::any TypeChecker::visitGenericTypeDef(GenericTypeDefNode *node) {
101
2/2
✓ Branch 2 → 3 taken 4495 times.
✓ Branch 2 → 4 taken 9854 times.
14349 if (typeCheckerMode == TC_MODE_PRE)
102 4495 return visitGenericTypeDefPrepare(node);
103
1/2
✓ Branch 4 → 5 taken 9854 times.
✗ Branch 4 → 8 not taken.
19708 return nullptr;
104 }
105
106 1985 std::any TypeChecker::visitAliasDef(AliasDefNode *node) {
107
2/2
✓ Branch 2 → 3 taken 703 times.
✓ Branch 2 → 4 taken 1282 times.
1985 if (typeCheckerMode == TC_MODE_PRE)
108 703 return visitAliasDefPrepare(node);
109
1/2
✓ Branch 4 → 5 taken 1282 times.
✗ Branch 4 → 8 not taken.
2564 return nullptr;
110 }
111
112 15857 std::any TypeChecker::visitGlobalVarDef(GlobalVarDefNode *node) {
113
2/2
✓ Branch 2 → 3 taken 5935 times.
✓ Branch 2 → 4 taken 9922 times.
15857 if (typeCheckerMode == TC_MODE_PRE)
114 5935 return visitGlobalVarDefPrepare(node);
115
1/2
✓ Branch 4 → 5 taken 9922 times.
✗ Branch 4 → 8 not taken.
19844 return nullptr;
116 }
117
118 28504 std::any TypeChecker::visitExtDecl(ExtDeclNode *node) {
119
2/2
✓ Branch 2 → 3 taken 8883 times.
✓ Branch 2 → 4 taken 19621 times.
28504 if (typeCheckerMode == TC_MODE_PRE)
120 8883 return visitExtDeclPrepare(node);
121
1/2
✓ Branch 4 → 5 taken 19621 times.
✗ Branch 4 → 8 not taken.
39242 return nullptr;
122 }
123
124 17221 std::any TypeChecker::visitImportDef(ImportDefNode *node) {
125
2/2
✓ Branch 2 → 3 taken 5892 times.
✓ Branch 2 → 4 taken 11329 times.
17221 if (typeCheckerMode == TC_MODE_PRE)
126 5892 return visitImportDefPrepare(node);
127
1/2
✓ Branch 4 → 5 taken 11329 times.
✗ Branch 4 → 8 not taken.
22658 return nullptr;
128 }
129
130 } // namespace spice::compiler
131