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 2587 std::any TypeChecker::visitMainFctDef(MainFctDefNode *node) {
11
2/2
✓ Branch 2 → 3 taken 1212 times.
✓ Branch 2 → 4 taken 1375 times.
2587 if (typeCheckerMode == TC_MODE_PRE)
12 1212 return visitMainFctDefPrepare(node);
13 else
14 1375 return visitMainFctDefCheck(node);
15 }
16
17 159306 std::any TypeChecker::visitFctDef(FctDefNode *node) {
18
2/2
✓ Branch 2 → 3 taken 50384 times.
✓ Branch 2 → 4 taken 108922 times.
159306 if (typeCheckerMode == TC_MODE_PRE)
19 50384 return visitFctDefPrepare(node);
20 else
21 108922 return visitFctDefCheck(node);
22 }
23
24 98161 std::any TypeChecker::visitProcDef(ProcDefNode *node) {
25
2/2
✓ Branch 2 → 3 taken 30340 times.
✓ Branch 2 → 4 taken 67821 times.
98161 if (typeCheckerMode == TC_MODE_PRE)
26 30340 return visitProcDefPrepare(node);
27 else
28 67821 return visitProcDefCheck(node);
29 }
30
31 22797 std::any TypeChecker::visitStructDef(StructDefNode *node) {
32
2/2
✓ Branch 2 → 3 taken 7663 times.
✓ Branch 2 → 4 taken 15134 times.
22797 if (typeCheckerMode == TC_MODE_PRE)
33 7663 return visitStructDefPrepare(node);
34 else
35 15134 return visitStructDefCheck(node);
36 }
37
38 1805 std::any TypeChecker::visitInterfaceDef(InterfaceDefNode *node) {
39
2/2
✓ Branch 2 → 3 taken 817 times.
✓ Branch 2 → 4 taken 988 times.
1805 if (typeCheckerMode == TC_MODE_PRE)
40 817 return visitInterfaceDefPrepare(node);
41
1/2
✓ Branch 4 → 5 taken 988 times.
✗ Branch 4 → 8 not taken.
1976 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 3635 std::any TypeChecker::visitEnumDef(EnumDefNode *node) {
95
2/2
✓ Branch 2 → 3 taken 1246 times.
✓ Branch 2 → 4 taken 2389 times.
3635 if (typeCheckerMode == TC_MODE_PRE)
96 1246 return visitEnumDefPrepare(node);
97
1/2
✓ Branch 4 → 5 taken 2389 times.
✗ Branch 4 → 8 not taken.
4778 return nullptr;
98 }
99
100 14913 std::any TypeChecker::visitGenericTypeDef(GenericTypeDefNode *node) {
101
2/2
✓ Branch 2 → 3 taken 4689 times.
✓ Branch 2 → 4 taken 10224 times.
14913 if (typeCheckerMode == TC_MODE_PRE)
102 4689 return visitGenericTypeDefPrepare(node);
103
1/2
✓ Branch 4 → 5 taken 10224 times.
✗ Branch 4 → 8 not taken.
20448 return nullptr;
104 }
105
106 1993 std::any TypeChecker::visitAliasDef(AliasDefNode *node) {
107
2/2
✓ Branch 2 → 3 taken 707 times.
✓ Branch 2 → 4 taken 1286 times.
1993 if (typeCheckerMode == TC_MODE_PRE)
108 707 return visitAliasDefPrepare(node);
109
1/2
✓ Branch 4 → 5 taken 1286 times.
✗ Branch 4 → 8 not taken.
2572 return nullptr;
110 }
111
112 16811 std::any TypeChecker::visitGlobalVarDef(GlobalVarDefNode *node) {
113
2/2
✓ Branch 2 → 3 taken 6311 times.
✓ Branch 2 → 4 taken 10500 times.
16811 if (typeCheckerMode == TC_MODE_PRE)
114 6311 return visitGlobalVarDefPrepare(node);
115
1/2
✓ Branch 4 → 5 taken 10500 times.
✗ Branch 4 → 8 not taken.
21000 return nullptr;
116 }
117
118 29424 std::any TypeChecker::visitExtDecl(ExtDeclNode *node) {
119
2/2
✓ Branch 2 → 3 taken 9211 times.
✓ Branch 2 → 4 taken 20213 times.
29424 if (typeCheckerMode == TC_MODE_PRE)
120 9211 return visitExtDeclPrepare(node);
121
1/2
✓ Branch 4 → 5 taken 20213 times.
✗ Branch 4 → 8 not taken.
40426 return nullptr;
122 }
123
124 17697 std::any TypeChecker::visitImportDef(ImportDefNode *node) {
125
2/2
✓ Branch 2 → 3 taken 6068 times.
✓ Branch 2 → 4 taken 11629 times.
17697 if (typeCheckerMode == TC_MODE_PRE)
126 6068 return visitImportDefPrepare(node);
127
1/2
✓ Branch 4 → 5 taken 11629 times.
✗ Branch 4 → 8 not taken.
23258 return nullptr;
128 }
129
130 } // namespace spice::compiler
131