GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.6% 83 / 0 / 85
Functions: 100.0% 18 / 0 / 18
Branches: 61.9% 109 / 0 / 176

src/model/Function.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "Function.h"
4
5 #include <ast/ASTBuilder.h>
6 #include <ast/ASTNodes.h>
7 #include <irgenerator/NameMangling.h>
8 #include <symboltablebuilder/SymbolTableBuilder.h>
9
10 namespace spice::compiler {
11
12 36874 Function::Function(std::string name, SymbolTableEntry *entry, const QualType &thisType, const QualType &returnType,
13 ParamList paramList, std::vector<GenericType> templateTypes, ASTNode *declNode)
14 110622 : name(std::move(name)), thisType(thisType), returnType(returnType), paramList(std::move(paramList)),
15 73748 templateTypes(std::move(templateTypes)), entry(entry), declNode(declNode) {}
16
17 /**
18 * Retrieve the parameter types of the current function
19 *
20 * @return Vector of parameter types
21 */
22 171230 QualTypeList Function::getParamTypes() const {
23 171230 QualTypeList newParamTypes;
24
2/2
✓ Branch 16 → 4 taken 258534 times.
✓ Branch 16 → 17 taken 171230 times.
600994 for (const auto &[qualType, isOptional] : paramList)
25
1/2
✓ Branch 6 → 7 taken 258534 times.
✗ Branch 6 → 19 not taken.
258534 newParamTypes.push_back(qualType);
26 171230 return newParamTypes;
27 }
28
29 /**
30 * Get a string representation of the current function.
31 *
32 * Example:
33 * string Vector<double>.setData<double>(double)
34 *
35 * @param withThisType Include 'this' type in signature
36 * @param withTemplateTypes Include concrete template types in the signature
37 * @param withTypeAliases Print type aliases as is and not decompose them
38 * @param withSize Print array sizes
39 * @return String representation as function signature
40 */
41 151893 std::string Function::getSignature(bool withThisType /*=true*/, bool withTemplateTypes /*=true*/, bool withTypeAliases /*=true*/,
42 bool withSize /*=false*/) const {
43 151893 QualTypeList concreteTemplateTypes;
44
2/2
✓ Branch 2 → 3 taken 151891 times.
✓ Branch 2 → 34 taken 2 times.
151893 if (withTemplateTypes) {
45
1/2
✓ Branch 4 → 5 taken 151891 times.
✗ Branch 4 → 40 not taken.
151891 concreteTemplateTypes.reserve(templateTypes.size());
46
2/2
✓ Branch 32 → 7 taken 95415 times.
✓ Branch 32 → 33 taken 151891 times.
399197 for (const GenericType &genericType : templateTypes) {
47
7/8
✓ Branch 9 → 10 taken 95415 times.
✗ Branch 9 → 39 not taken.
✓ Branch 10 → 11 taken 95403 times.
✓ Branch 10 → 14 taken 12 times.
✓ Branch 12 → 13 taken 56622 times.
✓ Branch 12 → 14 taken 38781 times.
✓ Branch 15 → 16 taken 56622 times.
✓ Branch 15 → 22 taken 38793 times.
95415 if (genericType.is(TY_GENERIC) && !typeMapping.empty()) {
48
1/2
✓ Branch 16 → 17 taken 56622 times.
✗ Branch 16 → 39 not taken.
56622 const std::string &subType = genericType.getSubType();
49
2/4
✓ Branch 17 → 18 taken 56622 times.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 56622 times.
56622 assert(typeMapping.contains(subType));
50
2/4
✓ Branch 20 → 21 taken 56622 times.
✗ Branch 20 → 39 not taken.
✓ Branch 21 → 23 taken 56622 times.
✗ Branch 21 → 39 not taken.
56622 concreteTemplateTypes.push_back(typeMapping.at(subType));
51 } else {
52
1/2
✓ Branch 22 → 23 taken 38793 times.
✗ Branch 22 → 39 not taken.
38793 concreteTemplateTypes.push_back(genericType);
53 }
54 }
55 }
56
57 151893 return getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, true, withThisType, true, withTypeAliases,
58
1/2
✓ Branch 34 → 35 taken 151893 times.
✗ Branch 34 → 40 not taken.
303786 withSize);
59 151893 }
60
61 /**
62 * Get a string representation of the current function.
63 *
64 * @param name Function name
65 * @param thisType This symbol type
66 * @param returnType Return symbol type
67 * @param paramList Param symbol types
68 * @param concreteTemplateTypes Concrete template symbol types
69 * @param withReturnType Include return type in signature
70 * @param withThisType Include 'this' type in signature
71 * @param ignorePublic Not include public modifiers in signature
72 * @param withTypeAliases Print type aliases as is and not decompose them
73 * @param withSize Print array sizes
74 * @return Function signature
75 */
76 151905 std::string Function::getSignature(const std::string &name, const QualType &thisType, const QualType &returnType,
77 const ParamList &paramList, const QualTypeList &concreteTemplateTypes,
78 bool withReturnType /*=true*/, bool withThisType /*=true*/, bool ignorePublic /*=false*/,
79 bool withTypeAliases /*=true*/, bool withSize /*=false*/) {
80
1/2
✓ Branch 2 → 3 taken 151905 times.
✗ Branch 2 → 66 not taken.
151905 std::stringstream signature;
81
82 // Build return type string
83
2/2
✓ Branch 3 → 4 taken 151893 times.
✓ Branch 3 → 10 taken 12 times.
151905 if (withReturnType) {
84
3/4
✓ Branch 4 → 5 taken 151893 times.
✗ Branch 4 → 64 not taken.
✓ Branch 5 → 6 taken 63626 times.
✓ Branch 5 → 7 taken 88267 times.
151893 if (returnType.is(TY_DYN)) {
85
1/2
✓ Branch 6 → 10 taken 63626 times.
✗ Branch 6 → 64 not taken.
63626 signature << "p ";
86 } else {
87
1/2
✓ Branch 7 → 8 taken 88267 times.
✗ Branch 7 → 64 not taken.
88267 signature << "f<";
88
1/2
✓ Branch 8 → 9 taken 88267 times.
✗ Branch 8 → 64 not taken.
88267 returnType.getName(signature, withSize, ignorePublic, withTypeAliases);
89
1/2
✓ Branch 9 → 10 taken 88267 times.
✗ Branch 9 → 64 not taken.
88267 signature << "> ";
90 }
91 }
92
93 // Build this type string
94
7/8
✓ Branch 10 → 11 taken 61125 times.
✓ Branch 10 → 14 taken 90780 times.
✓ Branch 11 → 12 taken 61125 times.
✗ Branch 11 → 64 not taken.
✓ Branch 12 → 13 taken 41032 times.
✓ Branch 12 → 14 taken 20093 times.
✓ Branch 15 → 16 taken 41032 times.
✓ Branch 15 → 33 taken 110873 times.
151905 if (withThisType && !thisType.is(TY_DYN)) {
95
3/6
✓ Branch 16 → 17 taken 41032 times.
✗ Branch 16 → 63 not taken.
✓ Branch 17 → 18 taken 41032 times.
✗ Branch 17 → 63 not taken.
✓ Branch 18 → 19 taken 41032 times.
✗ Branch 18 → 63 not taken.
41032 signature << thisType.getBase().getSubType();
96
1/2
✓ Branch 19 → 20 taken 41032 times.
✗ Branch 19 → 64 not taken.
41032 const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes();
97
2/2
✓ Branch 21 → 22 taken 23064 times.
✓ Branch 21 → 32 taken 17968 times.
41032 if (!thisTemplateTypes.empty()) {
98
1/2
✓ Branch 22 → 23 taken 23064 times.
✗ Branch 22 → 64 not taken.
23064 signature << "<";
99
2/2
✓ Branch 30 → 24 taken 28728 times.
✓ Branch 30 → 31 taken 23064 times.
51792 for (size_t i = 0; i < thisTemplateTypes.size(); i++) {
100
2/2
✓ Branch 24 → 25 taken 5664 times.
✓ Branch 24 → 26 taken 23064 times.
28728 if (i > 0)
101
1/2
✓ Branch 25 → 26 taken 5664 times.
✗ Branch 25 → 64 not taken.
5664 signature << ",";
102
2/4
✓ Branch 26 → 27 taken 28728 times.
✗ Branch 26 → 64 not taken.
✓ Branch 27 → 28 taken 28728 times.
✗ Branch 27 → 64 not taken.
28728 thisTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
103 }
104
1/2
✓ Branch 31 → 32 taken 23064 times.
✗ Branch 31 → 64 not taken.
23064 signature << ">";
105 }
106
1/2
✓ Branch 32 → 33 taken 41032 times.
✗ Branch 32 → 64 not taken.
41032 signature << MEMBER_ACCESS_TOKEN;
107 }
108
109 // Name
110
1/2
✓ Branch 33 → 34 taken 151905 times.
✗ Branch 33 → 64 not taken.
151905 signature << name;
111
112 // Build template type string
113
2/2
✓ Branch 35 → 36 taken 74705 times.
✓ Branch 35 → 46 taken 77200 times.
151905 if (!concreteTemplateTypes.empty()) {
114
1/2
✓ Branch 36 → 37 taken 74705 times.
✗ Branch 36 → 64 not taken.
74705 signature << "<";
115
2/2
✓ Branch 44 → 38 taken 95415 times.
✓ Branch 44 → 45 taken 74705 times.
170120 for (size_t i = 0; i < concreteTemplateTypes.size(); i++) {
116
2/2
✓ Branch 38 → 39 taken 20710 times.
✓ Branch 38 → 40 taken 74705 times.
95415 if (i > 0)
117
1/2
✓ Branch 39 → 40 taken 20710 times.
✗ Branch 39 → 64 not taken.
20710 signature << ",";
118
2/4
✓ Branch 40 → 41 taken 95415 times.
✗ Branch 40 → 64 not taken.
✓ Branch 41 → 42 taken 95415 times.
✗ Branch 41 → 64 not taken.
95415 concreteTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
119 }
120
1/2
✓ Branch 45 → 46 taken 74705 times.
✗ Branch 45 → 64 not taken.
74705 signature << ">";
121 }
122
123 // Parameter type string
124
1/2
✓ Branch 46 → 47 taken 151905 times.
✗ Branch 46 → 64 not taken.
151905 signature << "(";
125
2/2
✓ Branch 56 → 48 taken 158271 times.
✓ Branch 56 → 57 taken 151905 times.
310176 for (size_t i = 0; i < paramList.size(); i++) {
126
1/2
✓ Branch 48 → 49 taken 158271 times.
✗ Branch 48 → 64 not taken.
158271 const auto &[qualType, isOptional] = paramList.at(i);
127
2/2
✓ Branch 49 → 50 taken 57222 times.
✓ Branch 49 → 51 taken 101049 times.
158271 if (i > 0)
128
1/2
✓ Branch 50 → 51 taken 57222 times.
✗ Branch 50 → 64 not taken.
57222 signature << ",";
129
1/2
✓ Branch 51 → 52 taken 158271 times.
✗ Branch 51 → 64 not taken.
158271 qualType.getName(signature, withSize, ignorePublic, withTypeAliases);
130
1/2
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 158271 times.
158271 if (isOptional)
131 signature << "?";
132 }
133
1/2
✓ Branch 57 → 58 taken 151905 times.
✗ Branch 57 → 64 not taken.
151905 signature << ")";
134
135
1/2
✓ Branch 58 → 59 taken 151905 times.
✗ Branch 58 → 64 not taken.
303810 return signature.str();
136 151905 }
137
138 /**
139 * Get the name of the scope, where members and the body of the function live
140 *
141 * @return Scope name
142 */
143 90780 std::string Function::getScopeName() const { return getSignature(false, true, false, true); }
144
145 /**
146 * Get the mangled name of the function
147 *
148 * @return Mangled name
149 */
150 105306 std::string Function::getMangledName() const {
151 // Use predefined mangled name if available
152
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 105305 times.
105306 if (!predefinedMangledName.empty())
153 1 return predefinedMangledName;
154 // Use function name if mangling is disabled
155
2/2
✓ Branch 5 → 6 taken 9013 times.
✓ Branch 5 → 7 taken 96292 times.
105305 if (!mangleFunctionName)
156 9013 return name;
157 // Use normal name mangling
158 96292 return NameMangling::mangleFunction(*this);
159 }
160
161 /**
162 * Get the name of the symbol table entry of the function
163 *
164 * @param functionName Function name
165 * @param codeLoc Code location
166 * @return Symbol table entry name
167 */
168 58527 std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) {
169
3/6
✓ Branch 2 → 3 taken 58527 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 58527 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 58527 times.
✗ Branch 4 → 10 not taken.
117054 return functionName + ":" + codeLoc.toString();
170 }
171
172 /**
173 * Get the name of the symbol table entry of the default constructor of a struct
174 *
175 * @param structCodeLoc Code location of the struct
176 * @return Symbol table entry name
177 */
178 174 std::string Function::getSymbolTableEntryNameDefaultCtor(const CodeLoc &structCodeLoc) {
179
5/10
✓ Branch 2 → 3 taken 174 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 174 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 174 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 174 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 174 times.
✗ Branch 8 → 17 not taken.
696 return "default_" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
180 }
181
182 /**
183 * Get the name of the symbol table entry of the default copy constructor of a struct
184 *
185 * @param structCodeLoc Code location of the struct
186 * @return Symbol table entry name
187 */
188 1606 std::string Function::getSymbolTableEntryNameDefaultCopyCtor(const CodeLoc &structCodeLoc) {
189
5/10
✓ Branch 2 → 3 taken 1606 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 1606 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 1606 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 1606 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 1606 times.
✗ Branch 8 → 17 not taken.
6424 return "default_copy" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
190 }
191
192 /**
193 * Get the name of the symbol table entry of the default move constructor of a struct
194 *
195 * @param structCodeLoc Code location of the struct
196 * @return Symbol table entry name
197 */
198 10 std::string Function::getSymbolTableEntryNameDefaultMoveCtor(const CodeLoc &structCodeLoc) {
199
5/10
✓ Branch 2 → 3 taken 10 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 10 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 10 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 10 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 10 times.
✗ Branch 8 → 17 not taken.
40 return "default_move" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
200 }
201
202 /**
203 * Get the name of the symbol table entry of the default destructor of a struct
204 *
205 * @param structCodeLoc Code location of the struct
206 * @return Symbol table entry name
207 */
208 1372 std::string Function::getSymbolTableEntryNameDefaultDtor(const CodeLoc &structCodeLoc) {
209
5/10
✓ Branch 2 → 3 taken 1372 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 1372 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 1372 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 1372 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 1372 times.
✗ Branch 8 → 17 not taken.
5488 return "default_" + std::string(DTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
210 }
211
212 /**
213 * Checks if a function contains optional parameters.
214 * This would imply that the function is not substantiated by its optional parameters yet.
215 *
216 * @return Substantiated params or not
217 */
218 4332917 bool Function::hasSubstantiatedParams() const {
219 10512181 return std::ranges::none_of(paramList, [](const Param &param) { return param.isOptional; });
220 }
221
222 /**
223 * Checks if a function contains template types.
224 * This would imply that the function is not substantiated by its generic types yet.
225 *
226 * @return Substantiated generics or not
227 */
228 368489 bool Function::hasSubstantiatedGenerics() const {
229 234319 const auto predicate = [this](const GenericType &genericType) { return typeMapping.contains(genericType.getSubType()); };
230
1/2
✓ Branch 2 → 3 taken 368489 times.
✗ Branch 2 → 6 not taken.
736978 return std::ranges::all_of(templateTypes, predicate);
231 }
232
233 /**
234 * Checks if a function contains optional parameters or has generic types present.
235 * This would imply that the function is not fully substantiated yet.
236 *
237 * @return Fully substantiated or not
238 */
239
3/4
✓ Branch 3 → 4 taken 368489 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 229463 times.
✓ Branch 5 → 7 taken 139026 times.
368489 bool Function::isFullySubstantiated() const { return hasSubstantiatedParams() && hasSubstantiatedGenerics(); }
240
241 /**
242 * Returns, if this function is a substantiation of a generic one.
243 *
244 * @return Generic substantiation or not
245 */
246 3676207 bool Function::isGenericSubstantiation() const { return genericPreset != nullptr; }
247
248 /**
249 * Retrieve the declaration code location of this function
250 *
251 * @return Declaration code location
252 */
253 242 const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; }
254
255 } // namespace spice::compiler
256