GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 2 / 0 / 2
Functions: 100.0% 2 / 0 / 2
Branches: -% 0 / 0 / 0

src/typechecker/TypeChecker.h
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include <CompilerPass.h>
6 #include <ast/ASTVisitor.h>
7 #include <typechecker/OpRuleManager.h>
8
9 namespace spice::compiler {
10
11 // Forward declarations
12 class LambdaBaseNode;
13 class ExprNode;
14 class CompilerWarning;
15 struct Param;
16 struct NamedParam;
17 using ParamList = std::vector<Param>;
18 using NamedParamList = std::vector<NamedParam>;
19 using Arg = std::pair</*type=*/QualType, /*isTemporary=*/bool>;
20 using ArgList = std::vector<Arg>;
21
22 enum TypeCheckerMode : bool {
23 TC_MODE_PRE,
24 TC_MODE_POST,
25 };
26
27 /**
28 * Global switch that tells StructManager whether a freshly substantiated struct manifestation may still be given its
29 * compiler-generated default members (ctor, copy ctor, move ctor, dtor).
30 *
31 * Creating those mutates the symbol table and registers new functions, which is only valid while the middle end runs.
32 * The back end reaches StructManager::match as well - through QualType::getStruct, on multiple threads - but by then
33 * every manifestation exists already, so those calls never take the creation path anyway. The switch makes that an
34 * invariant instead of an assumption.
35 */
36 inline bool structDefaultMembersDecidable = false;
37
38 /**
39 * RAII marker for the section of the compiler in which struct manifestations are still allowed to receive their
40 * compiler-generated default members, i.e. the middle end.
41 */
42 class DefaultMemberCreationSection final {
43 public:
44 // Constructors
45 1273 DefaultMemberCreationSection() { structDefaultMembersDecidable = true; }
46
47 // Prevent copy
48 DefaultMemberCreationSection(const DefaultMemberCreationSection &) = delete;
49 DefaultMemberCreationSection &operator=(const DefaultMemberCreationSection &) = delete;
50
51 // Destructor
52 1273 ~DefaultMemberCreationSection() { structDefaultMembersDecidable = false; }
53 };
54
55 /**
56 * Jobs:
57 * - Ensure that all actual types match the expected types
58 * - Perform type inference
59 */
60 class TypeChecker final : CompilerPass, public ASTVisitor {
61 public:
62 // Constructors
63 TypeChecker(GlobalResourceManager &resourceManager, SourceFile *sourceFile, TypeCheckerMode typeCheckerMode);
64
65 // Friend classes
66 friend class OpRuleManager;
67 friend class FunctionManager;
68 friend class StructManager;
69
70 // Visitor methods
71 // Top level definitions
72 std::any visitEntry(EntryNode *node) override;
73 std::any visitMainFctDef(MainFctDefNode *node) override;
74 std::any visitMainFctDefPrepare(MainFctDefNode *node);
75 std::any visitMainFctDefCheck(MainFctDefNode *node);
76 std::any visitFctDef(FctDefNode *node) override;
77 std::any visitFctDefPrepare(FctDefNode *node);
78 std::any visitFctDefCheck(FctDefNode *node);
79 std::any visitProcDef(ProcDefNode *node) override;
80 std::any visitProcDefPrepare(ProcDefNode *node);
81 std::any visitProcDefCheck(ProcDefNode *node);
82 std::any visitStructDef(StructDefNode *node) override;
83 std::any visitStructDefPrepare(StructDefNode *node);
84 std::any visitStructDefCheck(StructDefNode *node);
85 std::any visitInterfaceDef(InterfaceDefNode *node) override;
86 std::any visitInterfaceDefPrepare(InterfaceDefNode *node);
87 void assignDeferredOpaqueType(SymbolTableEntry *entry);
88 std::any visitUnionDef(UnionDefNode *node) override;
89 std::any visitUnionDefPrepare(UnionDefNode *node);
90 std::any visitUnionDefCheck(UnionDefNode *node);
91 std::any visitEnumDef(EnumDefNode *node) override;
92 std::any visitEnumDefPrepare(EnumDefNode *node);
93 std::any visitGenericTypeDef(GenericTypeDefNode *node) override;
94 std::any visitGenericTypeDefPrepare(GenericTypeDefNode *node);
95 std::any visitAliasDef(AliasDefNode *node) override;
96 std::any visitAliasDefPrepare(AliasDefNode *node);
97 std::any visitGlobalVarDef(GlobalVarDefNode *node) override;
98 std::any visitGlobalVarDefPrepare(GlobalVarDefNode *node);
99 std::any visitExtDecl(ExtDeclNode *node) override;
100 std::any visitExtDeclPrepare(ExtDeclNode *node);
101 std::any visitImportDef(ImportDefNode *node) override;
102 std::any visitImportDefPrepare(ImportDefNode *node);
103 // Control structures
104 std::any visitUnsafeBlock(UnsafeBlockNode *node) override;
105 std::any visitForLoop(ForLoopNode *node) override;
106 std::any visitForeachLoop(ForeachLoopNode *node) override;
107 std::any visitWhileLoop(WhileLoopNode *node) override;
108 std::any visitDoWhileLoop(DoWhileLoopNode *node) override;
109 std::any visitIfStmt(IfStmtNode *node) override;
110 std::any visitElseStmt(ElseStmtNode *node) override;
111 std::any visitSwitchStmt(SwitchStmtNode *node) override;
112 std::any visitCaseBranch(CaseBranchNode *node) override;
113 std::any visitDefaultBranch(DefaultBranchNode *node) override;
114 std::any visitAssertStmt(AssertStmtNode *node) override;
115 std::any visitAnonymousBlockStmt(AnonymousBlockStmtNode *node) override;
116 // Statements
117 std::any visitStmtLst(StmtLstNode *node) override;
118 std::any visitParamLst(ParamLstNode *node) override;
119 std::any visitField(FieldNode *node) override;
120 std::any visitSignature(SignatureNode *node) override;
121 std::any visitDeclStmt(DeclStmtNode *node) override;
122 std::any visitCaseConstant(CaseConstantNode *node) override;
123 std::any visitReturnStmt(ReturnStmtNode *node) override;
124 std::any visitBreakStmt(BreakStmtNode *node) override;
125 std::any visitContinueStmt(ContinueStmtNode *node) override;
126 std::any visitFallthroughStmt(FallthroughStmtNode *node) override;
127 // Expressions
128 std::any visitAssignExpr(AssignExprNode *node) override;
129 std::any visitTernaryExpr(TernaryExprNode *node) override;
130 std::any visitLogicalOrExpr(LogicalOrExprNode *node) override;
131 std::any visitLogicalAndExpr(LogicalAndExprNode *node) override;
132 std::any visitBitwiseOrExpr(BitwiseOrExprNode *node) override;
133 std::any visitBitwiseXorExpr(BitwiseXorExprNode *node) override;
134 std::any visitBitwiseAndExpr(BitwiseAndExprNode *node) override;
135 std::any visitEqualityExpr(EqualityExprNode *node) override;
136 std::any visitRelationalExpr(RelationalExprNode *node) override;
137 std::any visitShiftExpr(ShiftExprNode *node) override;
138 std::any visitAdditiveExpr(AdditiveExprNode *node) override;
139 std::any visitMultiplicativeExpr(MultiplicativeExprNode *node) override;
140 std::any visitCastExpr(CastExprNode *node) override;
141 std::any visitPrefixUnaryExpr(PrefixUnaryExprNode *node) override;
142 std::any visitPostfixUnaryExpr(PostfixUnaryExprNode *node) override;
143 std::any visitAtomicExpr(AtomicExprNode *node) override;
144 // Values and types
145 std::any visitValue(ValueNode *node) override;
146 std::any visitConstant(ConstantNode *node) override;
147 std::any visitFctCall(FctCallNode *node) override;
148 std::any visitArrayInitialization(ArrayInitializationNode *node) override;
149 std::any visitStructInstantiation(StructInstantiationNode *node) override;
150 std::any visitLambdaFunc(LambdaFuncNode *node) override;
151 std::any visitLambdaProc(LambdaProcNode *node) override;
152 std::any visitLambdaExpr(LambdaExprNode *node) override;
153 std::any visitDataType(DataTypeNode *node) override;
154 std::any visitBaseDataType(BaseDataTypeNode *node) override;
155 std::any visitCustomDataType(CustomDataTypeNode *node) override;
156 std::any visitFunctionDataType(FunctionDataTypeNode *node) override;
157
158 // Builtin function handlers
159 std::any visitBuiltinCall(FctCallNode *node) const;
160 std::any visitBuiltinPrintfCall(FctCallNode *node) const;
161 std::any visitBuiltinSizeOfCall(FctCallNode *node) const;
162 std::any visitBuiltinAlignOfCall(FctCallNode *node) const;
163 std::any visitBuiltinOffsetOfCall(FctCallNode *node) const;
164 std::any visitBuiltinTypeIdCall(FctCallNode *node) const;
165 std::any visitBuiltinTypeNameCall(FctCallNode *node) const;
166 std::any visitBuiltinLenCall(FctCallNode *node) const;
167 std::any visitBuiltinPanicCall(FctCallNode *node) const;
168 std::any visitBuiltinSyscallCall(FctCallNode *node) const;
169 std::any visitBuiltinIsSameCall(FctCallNode *node) const;
170 std::any visitBuiltinImplementsInterfaceCall(FctCallNode *node) const;
171 std::any visitBuiltinGetBuildVarCall(FctCallNode *node) const;
172 std::any visitBuiltinIsTriviallyConstructible(FctCallNode *node) const;
173 std::any visitBuiltinIsTriviallyCopyable(FctCallNode *node) const;
174 std::any visitBuiltinIsTriviallyDestructible(FctCallNode *node) const;
175 std::any visitBuiltinIsHeap(FctCallNode *node) const;
176 std::any visitBuiltinNewCall(FctCallNode *node) const;
177 std::any visitBuiltinPlacementNewCall(FctCallNode *node) const;
178 std::any visitBuiltinSourceFileCall(FctCallNode *node) const;
179 std::any visitBuiltinSourceLineCall(FctCallNode *node) const;
180 std::any visitBuiltinSourceColumnCall(FctCallNode *node) const;
181 std::any visitBuiltinErrTraceBufferCall(FctCallNode *node) const;
182 std::any visitBuiltinStdErrCall(FctCallNode *node) const;
183 std::any visitBuiltinFrameAddressCall(FctCallNode *node) const;
184
185 private:
186 // Private members
187 OpRuleManager opRuleManager = OpRuleManager(this);
188 const TypeCheckerMode typeCheckerMode;
189 std::vector<CompilerWarning> &warnings;
190 TypeMapping typeMapping;
191 bool typeCheckedMainFct = false;
192
193 // Private methods
194 bool visitOrdinaryFctCall(FctCallNode *node, std::string fqFunctionName) const;
195 bool visitFctPtrCall(const FctCallNode *node, const QualType &functionType) const;
196 bool visitMethodCall(FctCallNode *node, Scope *structScope) const;
197 bool checkAsyncLambdaCaptureRules(const LambdaBaseNode *node, const LambdaAttrNode *attrs) const;
198 [[nodiscard]] Function *matchCopyCtor(const QualType &thisType, const ASTNode *node) const;
199 [[nodiscard]] Function *matchMoveCtor(const QualType &thisType, const ASTNode *node) const;
200 [[nodiscard]] QualType mapLocalTypeToImportedScopeType(const Scope *targetScope, const QualType &symbolType) const;
201 [[nodiscard]] QualType mapImportedScopeTypeToLocalType(const Scope *sourceScope, const QualType &symbolType) const;
202 std::vector<const Function *> &getOpFctPointers(ASTNode *node) const;
203 static void requestRevisitIfRequired(const Function *fct);
204 void ensureLoadedRuntimeForTypeName(const std::string &typeName) const;
205 void ensureLoadedRuntimeForFunctionName(const std::string &functionName) const;
206 void softError(const ASTNode *node, SemanticErrorType errorType, const std::string &message) const;
207
208 // Implicit code generation
209 static void createImplicitDefaultMembers(Struct &spiceStruct, const ASTNode *node, bool withMoveCtor = true);
210 static void decideDefaultMembers(Struct &spiceStruct, bool withMoveCtor);
211 static void drainPendingImplicitDefaultMemberDecisions(GlobalResourceManager &resourceManager);
212 static void createDefaultStructMethod(const Struct &spiceStruct, const std::string &entryName, const std::string &name,
213 const ParamList &params);
214 static void createDefaultCtorIfRequired(const Struct &spiceStruct, Scope *structScope);
215 static void createDefaultCopyCtorIfRequired(const Struct &spiceStruct, Scope *structScope);
216 static void createDefaultMoveCtorIfRequired(const Struct &spiceStruct, Scope *structScope);
217 static void createDefaultDtorIfRequired(const Struct &spiceStruct, Scope *structScope);
218 void createCtorBodyPreamble(const Scope *bodyScope) const;
219 void createCopyCtorBodyPreamble(const Scope *bodyScope) const;
220 void createMoveCtorBodyPreamble(const Scope *bodyScope) const;
221 void createDtorBodyPreamble(const Scope *bodyScope, const ASTNode *node) const;
222 Function *implicitlyCallStructMethod(const SymbolTableEntry *entry, const std::string &methodName, const ArgList &args,
223 const ASTNode *node) const;
224 Function *implicitlyCallStructMethod(QualType thisType, const std::string &methodName, const ArgList &args,
225 const ASTNode *node) const;
226 Function *implicitlyCallStructCopyCtor(const SymbolTableEntry *entry, const ASTNode *node) const;
227 Function *implicitlyCallStructCopyCtor(const QualType &thisType, const ASTNode *node) const;
228 Function *implicitlyCallStructMoveCtor(const SymbolTableEntry *entry, const ASTNode *node) const;
229 Function *implicitlyCallStructMoveCtor(const QualType &thisType, const ASTNode *node) const;
230 void implicitlyCallStructDtor(SymbolTableEntry *entry, StmtLstNode *node) const;
231 void implicitlyCallDeallocate(const ASTNode *node) const;
232 void sortByReverseDeclarationOrder(std::vector<SymbolTableEntry *> &vars) const;
233 void doScopeCleanup(StmtLstNode *node) const;
234 void doExprScopeCleanup(const ExprNode *node) const;
235 ExprResult visitInExprScope(ExprNode *expr);
236 bool isCopyCtorCall(const FctCallNode *node, const QualType &thisType) const;
237 };
238
239 } // namespace spice::compiler
240