GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.7% 85 / 0 / 87
Functions: 100.0% 18 / 0 / 18
Branches: 62.8% 113 / 0 / 180

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 109217 Function::Function(std::string name, SymbolTableEntry *entry, const QualType &thisType, const QualType &returnType,
13 ParamList paramList, std::vector<GenericType> templateTypes, ASTNode *declNode)
14 327651 : name(std::move(name)), thisType(thisType), returnType(returnType), paramList(std::move(paramList)),
15 218434 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 595295 QualTypeList Function::getParamTypes() const {
23 595295 QualTypeList newParamTypes;
24
2/2
✓ Branch 16 → 4 taken 952379 times.
✓ Branch 16 → 17 taken 595295 times.
2142969 for (const auto &[qualType, isOptional] : paramList)
25
1/2
✓ Branch 6 → 7 taken 952379 times.
✗ Branch 6 → 19 not taken.
952379 newParamTypes.push_back(qualType);
26 595295 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 406447 std::string Function::getSignature(bool withThisType /*=true*/, bool withTemplateTypes /*=true*/, bool withTypeAliases /*=true*/,
42 bool withSize /*=false*/) const {
43 406447 QualTypeList concreteTemplateTypes;
44
2/2
✓ Branch 2 → 3 taken 406443 times.
✓ Branch 2 → 34 taken 4 times.
406447 if (withTemplateTypes) {
45
1/2
✓ Branch 4 → 5 taken 406443 times.
✗ Branch 4 → 40 not taken.
406443 concreteTemplateTypes.reserve(templateTypes.size());
46
2/2
✓ Branch 32 → 7 taken 232798 times.
✓ Branch 32 → 33 taken 406443 times.
1045684 for (const GenericType &genericType : templateTypes) {
47
7/8
✓ Branch 9 → 10 taken 232798 times.
✗ Branch 9 → 39 not taken.
✓ Branch 10 → 11 taken 229736 times.
✓ Branch 10 → 14 taken 3062 times.
✓ Branch 12 → 13 taken 135728 times.
✓ Branch 12 → 14 taken 94008 times.
✓ Branch 15 → 16 taken 135728 times.
✓ Branch 15 → 22 taken 97070 times.
232798 if (genericType.is(TY_GENERIC) && !typeMapping.empty()) {
48
1/2
✓ Branch 16 → 17 taken 135728 times.
✗ Branch 16 → 39 not taken.
135728 const std::string &subType = genericType.getSubType();
49
2/4
✓ Branch 17 → 18 taken 135728 times.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 135728 times.
135728 assert(typeMapping.contains(subType));
50
2/4
✓ Branch 20 → 21 taken 135728 times.
✗ Branch 20 → 39 not taken.
✓ Branch 21 → 23 taken 135728 times.
✗ Branch 21 → 39 not taken.
135728 concreteTemplateTypes.push_back(typeMapping.at(subType));
51 } else {
52
1/2
✓ Branch 22 → 23 taken 97070 times.
✗ Branch 22 → 39 not taken.
97070 concreteTemplateTypes.push_back(genericType);
53 }
54 }
55 }
56
57 406447 return getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, true, withThisType, true, withTypeAliases,
58
1/2
✓ Branch 34 → 35 taken 406447 times.
✗ Branch 34 → 40 not taken.
812894 withSize);
59 406447 }
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 406471 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 406471 times.
✗ Branch 2 → 66 not taken.
406471 std::stringstream signature;
81
82 // Build return type string
83
2/2
✓ Branch 3 → 4 taken 406447 times.
✓ Branch 3 → 10 taken 24 times.
406471 if (withReturnType) {
84
3/4
✓ Branch 4 → 5 taken 406447 times.
✗ Branch 4 → 64 not taken.
✓ Branch 5 → 6 taken 171257 times.
✓ Branch 5 → 7 taken 235190 times.
406447 if (returnType.is(TY_DYN)) {
85
1/2
✓ Branch 6 → 10 taken 171257 times.
✗ Branch 6 → 64 not taken.
171257 signature << "p ";
86 } else {
87
1/2
✓ Branch 7 → 8 taken 235190 times.
✗ Branch 7 → 64 not taken.
235190 signature << "f<";
88
1/2
✓ Branch 8 → 9 taken 235190 times.
✗ Branch 8 → 64 not taken.
235190 returnType.getName(signature, withSize, ignorePublic, withTypeAliases);
89
1/2
✓ Branch 9 → 10 taken 235190 times.
✗ Branch 9 → 64 not taken.
235190 signature << "> ";
90 }
91 }
92
93 // Build this type string
94
7/8
✓ Branch 10 → 11 taken 163928 times.
✓ Branch 10 → 14 taken 242543 times.
✓ Branch 11 → 12 taken 163928 times.
✗ Branch 11 → 64 not taken.
✓ Branch 12 → 13 taken 105609 times.
✓ Branch 12 → 14 taken 58319 times.
✓ Branch 15 → 16 taken 105609 times.
✓ Branch 15 → 33 taken 300862 times.
406471 if (withThisType && !thisType.is(TY_DYN)) {
95
3/6
✓ Branch 16 → 17 taken 105609 times.
✗ Branch 16 → 63 not taken.
✓ Branch 17 → 18 taken 105609 times.
✗ Branch 17 → 63 not taken.
✓ Branch 18 → 19 taken 105609 times.
✗ Branch 18 → 63 not taken.
105609 signature << thisType.getBase().getSubType();
96
1/2
✓ Branch 19 → 20 taken 105609 times.
✗ Branch 19 → 64 not taken.
105609 const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes();
97
2/2
✓ Branch 21 → 22 taken 54685 times.
✓ Branch 21 → 32 taken 50924 times.
105609 if (!thisTemplateTypes.empty()) {
98
1/2
✓ Branch 22 → 23 taken 54685 times.
✗ Branch 22 → 64 not taken.
54685 signature << "<";
99
2/2
✓ Branch 30 → 24 taken 69248 times.
✓ Branch 30 → 31 taken 54685 times.
123933 for (size_t i = 0; i < thisTemplateTypes.size(); i++) {
100
2/2
✓ Branch 24 → 25 taken 14563 times.
✓ Branch 24 → 26 taken 54685 times.
69248 if (i > 0)
101
1/2
✓ Branch 25 → 26 taken 14563 times.
✗ Branch 25 → 64 not taken.
14563 signature << ",";
102
2/4
✓ Branch 26 → 27 taken 69248 times.
✗ Branch 26 → 64 not taken.
✓ Branch 27 → 28 taken 69248 times.
✗ Branch 27 → 64 not taken.
69248 thisTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
103 }
104
1/2
✓ Branch 31 → 32 taken 54685 times.
✗ Branch 31 → 64 not taken.
54685 signature << ">";
105 }
106
1/2
✓ Branch 32 → 33 taken 105609 times.
✗ Branch 32 → 64 not taken.
105609 signature << MEMBER_ACCESS_TOKEN;
107 }
108
109 // Name
110
1/2
✓ Branch 33 → 34 taken 406471 times.
✗ Branch 33 → 64 not taken.
406471 signature << name;
111
112 // Build template type string
113
2/2
✓ Branch 35 → 36 taken 183074 times.
✓ Branch 35 → 46 taken 223397 times.
406471 if (!concreteTemplateTypes.empty()) {
114
1/2
✓ Branch 36 → 37 taken 183074 times.
✗ Branch 36 → 64 not taken.
183074 signature << "<";
115
2/2
✓ Branch 44 → 38 taken 232798 times.
✓ Branch 44 → 45 taken 183074 times.
415872 for (size_t i = 0; i < concreteTemplateTypes.size(); i++) {
116
2/2
✓ Branch 38 → 39 taken 49724 times.
✓ Branch 38 → 40 taken 183074 times.
232798 if (i > 0)
117
1/2
✓ Branch 39 → 40 taken 49724 times.
✗ Branch 39 → 64 not taken.
49724 signature << ",";
118
2/4
✓ Branch 40 → 41 taken 232798 times.
✗ Branch 40 → 64 not taken.
✓ Branch 41 → 42 taken 232798 times.
✗ Branch 41 → 64 not taken.
232798 concreteTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
119 }
120
1/2
✓ Branch 45 → 46 taken 183074 times.
✗ Branch 45 → 64 not taken.
183074 signature << ">";
121 }
122
123 // Parameter type string
124
1/2
✓ Branch 46 → 47 taken 406471 times.
✗ Branch 46 → 64 not taken.
406471 signature << "(";
125
2/2
✓ Branch 56 → 48 taken 448826 times.
✓ Branch 56 → 57 taken 406471 times.
855297 for (size_t i = 0; i < paramList.size(); i++) {
126
1/2
✓ Branch 48 → 49 taken 448826 times.
✗ Branch 48 → 64 not taken.
448826 const auto &[qualType, isOptional] = paramList.at(i);
127
2/2
✓ Branch 49 → 50 taken 168993 times.
✓ Branch 49 → 51 taken 279833 times.
448826 if (i > 0)
128
1/2
✓ Branch 50 → 51 taken 168993 times.
✗ Branch 50 → 64 not taken.
168993 signature << ",";
129
1/2
✓ Branch 51 → 52 taken 448826 times.
✗ Branch 51 → 64 not taken.
448826 qualType.getName(signature, withSize, ignorePublic, withTypeAliases);
130
1/2
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 448826 times.
448826 if (isOptional)
131 signature << "?";
132 }
133
1/2
✓ Branch 57 → 58 taken 406471 times.
✗ Branch 57 → 64 not taken.
406471 signature << ")";
134
135
1/2
✓ Branch 58 → 59 taken 406471 times.
✗ Branch 58 → 64 not taken.
812942 return signature.str();
136 406471 }
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 242543 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 330442 std::string Function::getMangledName() const {
151 // Use predefined mangled name if available
152
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 330440 times.
330442 if (!predefinedMangledName.empty())
153 2 return predefinedMangledName;
154 // Use function name if mangling is disabled
155
2/2
✓ Branch 5 → 6 taken 27704 times.
✓ Branch 5 → 7 taken 302736 times.
330440 if (!mangleFunctionName)
156 27704 return name;
157 // Use normal name mangling
158 302736 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 163477 std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) {
169
3/6
✓ Branch 2 → 3 taken 163477 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 163477 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 163477 times.
✗ Branch 4 → 10 not taken.
326954 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 338 std::string Function::getSymbolTableEntryNameDefaultCtor(const CodeLoc &structCodeLoc) {
179
5/10
✓ Branch 2 → 3 taken 338 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 338 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 338 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 338 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 338 times.
✗ Branch 8 → 17 not taken.
1352 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 4215 std::string Function::getSymbolTableEntryNameDefaultCopyCtor(const CodeLoc &structCodeLoc) {
189
5/10
✓ Branch 2 → 3 taken 4215 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 4215 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 4215 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 4215 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 4215 times.
✗ Branch 8 → 17 not taken.
16860 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 20 std::string Function::getSymbolTableEntryNameDefaultMoveCtor(const CodeLoc &structCodeLoc) {
199
5/10
✓ Branch 2 → 3 taken 20 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 20 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 20 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 20 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 20 times.
✗ Branch 8 → 17 not taken.
80 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 3539 std::string Function::getSymbolTableEntryNameDefaultDtor(const CodeLoc &structCodeLoc) {
209
5/10
✓ Branch 2 → 3 taken 3539 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 3539 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 3539 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 3539 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 3539 times.
✗ Branch 8 → 17 not taken.
14156 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 13240179 bool Function::hasSubstantiatedParams() const {
219 32522266 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 1012960 bool Function::hasSubstantiatedGenerics() const {
229 1597660 const auto predicate = [this](const GenericType &genericType) {
230 // A template slot that is not generic (anymore) is already substantiated. This is the case for the default members
231 // of an already-concrete struct manifestation (e.g. HashEntry<int, String>::dtor()), whose template type list holds
232 // the concrete types instead of generic placeholders. Only generic types carry a sub type usable as a mapping key -
233 // getSubType() would assert on e.g. a primitive or a 'heap byte*'.
234
4/4
✓ Branch 3 → 4 taken 574530 times.
✓ Branch 3 → 7 taken 10170 times.
✓ Branch 6 → 7 taken 223190 times.
✓ Branch 6 → 8 taken 351340 times.
584700 return !genericType.is(TY_GENERIC) || typeMapping.contains(genericType.getSubType());
235 1012960 };
236
1/2
✓ Branch 2 → 3 taken 1012960 times.
✗ Branch 2 → 6 not taken.
2025920 return std::ranges::all_of(templateTypes, predicate);
237 }
238
239 /**
240 * Checks if a function contains optional parameters or has generic types present.
241 * This would imply that the function is not fully substantiated yet.
242 *
243 * @return Fully substantiated or not
244 */
245
3/4
✓ Branch 3 → 4 taken 1012960 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 661620 times.
✓ Branch 5 → 7 taken 351340 times.
1012960 bool Function::isFullySubstantiated() const { return hasSubstantiatedParams() && hasSubstantiatedGenerics(); }
246
247 /**
248 * Returns, if this function is a substantiation of a generic one.
249 *
250 * @return Generic substantiation or not
251 */
252 11434864 bool Function::isGenericSubstantiation() const { return genericPreset != nullptr; }
253
254 /**
255 * Retrieve the declaration code location of this function
256 *
257 * @return Declaration code location
258 */
259 44326 const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; }
260
261 } // namespace spice::compiler
262