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 75442 Function::Function(std::string name, SymbolTableEntry *entry, const QualType &thisType, const QualType &returnType,
13 ParamList paramList, std::vector<GenericType> templateTypes, ASTNode *declNode)
14 226326 : name(std::move(name)), thisType(thisType), returnType(returnType), paramList(std::move(paramList)),
15 150884 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 391003 QualTypeList Function::getParamTypes() const {
23 391003 QualTypeList newParamTypes;
24
2/2
✓ Branch 16 → 4 taken 679430 times.
✓ Branch 16 → 17 taken 391003 times.
1461436 for (const auto &[qualType, isOptional] : paramList)
25
1/2
✓ Branch 6 → 7 taken 679430 times.
✗ Branch 6 → 19 not taken.
679430 newParamTypes.push_back(qualType);
26 391003 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 282185 std::string Function::getSignature(bool withThisType /*=true*/, bool withTemplateTypes /*=true*/, bool withTypeAliases /*=true*/,
42 bool withSize /*=false*/) const {
43 282185 QualTypeList concreteTemplateTypes;
44
2/2
✓ Branch 2 → 3 taken 282181 times.
✓ Branch 2 → 34 taken 4 times.
282185 if (withTemplateTypes) {
45
1/2
✓ Branch 4 → 5 taken 282181 times.
✗ Branch 4 → 40 not taken.
282181 concreteTemplateTypes.reserve(templateTypes.size());
46
2/2
✓ Branch 32 → 7 taken 169479 times.
✓ Branch 32 → 33 taken 282181 times.
733841 for (const GenericType &genericType : templateTypes) {
47
7/8
✓ Branch 9 → 10 taken 169479 times.
✗ Branch 9 → 39 not taken.
✓ Branch 10 → 11 taken 167351 times.
✓ Branch 10 → 14 taken 2128 times.
✓ Branch 12 → 13 taken 92692 times.
✓ Branch 12 → 14 taken 74659 times.
✓ Branch 15 → 16 taken 92692 times.
✓ Branch 15 → 22 taken 76787 times.
169479 if (genericType.is(TY_GENERIC) && !typeMapping.empty()) {
48
1/2
✓ Branch 16 → 17 taken 92692 times.
✗ Branch 16 → 39 not taken.
92692 const std::string &subType = genericType.getSubType();
49
2/4
✓ Branch 17 → 18 taken 92692 times.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 92692 times.
92692 assert(typeMapping.contains(subType));
50
2/4
✓ Branch 20 → 21 taken 92692 times.
✗ Branch 20 → 39 not taken.
✓ Branch 21 → 23 taken 92692 times.
✗ Branch 21 → 39 not taken.
92692 concreteTemplateTypes.push_back(typeMapping.at(subType));
51 } else {
52
1/2
✓ Branch 22 → 23 taken 76787 times.
✗ Branch 22 → 39 not taken.
76787 concreteTemplateTypes.push_back(genericType);
53 }
54 }
55 }
56
57 282185 return getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, true, withThisType, true, withTypeAliases,
58
1/2
✓ Branch 34 → 35 taken 282185 times.
✗ Branch 34 → 40 not taken.
564370 withSize);
59 282185 }
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 282213 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 282213 times.
✗ Branch 2 → 66 not taken.
282213 std::stringstream signature;
81
82 // Build return type string
83
2/2
✓ Branch 3 → 4 taken 282185 times.
✓ Branch 3 → 10 taken 28 times.
282213 if (withReturnType) {
84
3/4
✓ Branch 4 → 5 taken 282185 times.
✗ Branch 4 → 64 not taken.
✓ Branch 5 → 6 taken 120335 times.
✓ Branch 5 → 7 taken 161850 times.
282185 if (returnType.is(TY_DYN)) {
85
1/2
✓ Branch 6 → 10 taken 120335 times.
✗ Branch 6 → 64 not taken.
120335 signature << "p ";
86 } else {
87
1/2
✓ Branch 7 → 8 taken 161850 times.
✗ Branch 7 → 64 not taken.
161850 signature << "f<";
88
1/2
✓ Branch 8 → 9 taken 161850 times.
✗ Branch 8 → 64 not taken.
161850 returnType.getName(signature, withSize, ignorePublic, withTypeAliases);
89
1/2
✓ Branch 9 → 10 taken 161850 times.
✗ Branch 9 → 64 not taken.
161850 signature << "> ";
90 }
91 }
92
93 // Build this type string
94
7/8
✓ Branch 10 → 11 taken 113244 times.
✓ Branch 10 → 14 taken 168969 times.
✓ Branch 11 → 12 taken 113244 times.
✗ Branch 11 → 64 not taken.
✓ Branch 12 → 13 taken 68972 times.
✓ Branch 12 → 14 taken 44272 times.
✓ Branch 15 → 16 taken 68972 times.
✓ Branch 15 → 33 taken 213241 times.
282213 if (withThisType && !thisType.is(TY_DYN)) {
95
3/6
✓ Branch 16 → 17 taken 68972 times.
✗ Branch 16 → 63 not taken.
✓ Branch 17 → 18 taken 68972 times.
✗ Branch 17 → 63 not taken.
✓ Branch 18 → 19 taken 68972 times.
✗ Branch 18 → 63 not taken.
68972 signature << thisType.getBase().getSubType();
96
1/2
✓ Branch 19 → 20 taken 68972 times.
✗ Branch 19 → 64 not taken.
68972 const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes();
97
2/2
✓ Branch 21 → 22 taken 39453 times.
✓ Branch 21 → 32 taken 29519 times.
68972 if (!thisTemplateTypes.empty()) {
98
1/2
✓ Branch 22 → 23 taken 39453 times.
✗ Branch 22 → 64 not taken.
39453 signature << "<";
99
2/2
✓ Branch 30 → 24 taken 48809 times.
✓ Branch 30 → 31 taken 39453 times.
88262 for (size_t i = 0; i < thisTemplateTypes.size(); i++) {
100
2/2
✓ Branch 24 → 25 taken 9356 times.
✓ Branch 24 → 26 taken 39453 times.
48809 if (i > 0)
101
1/2
✓ Branch 25 → 26 taken 9356 times.
✗ Branch 25 → 64 not taken.
9356 signature << ",";
102
2/4
✓ Branch 26 → 27 taken 48809 times.
✗ Branch 26 → 64 not taken.
✓ Branch 27 → 28 taken 48809 times.
✗ Branch 27 → 64 not taken.
48809 thisTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
103 }
104
1/2
✓ Branch 31 → 32 taken 39453 times.
✗ Branch 31 → 64 not taken.
39453 signature << ">";
105 }
106
1/2
✓ Branch 32 → 33 taken 68972 times.
✗ Branch 32 → 64 not taken.
68972 signature << MEMBER_ACCESS_TOKEN;
107 }
108
109 // Name
110
1/2
✓ Branch 33 → 34 taken 282213 times.
✗ Branch 33 → 64 not taken.
282213 signature << name;
111
112 // Build template type string
113
2/2
✓ Branch 35 → 36 taken 135407 times.
✓ Branch 35 → 46 taken 146806 times.
282213 if (!concreteTemplateTypes.empty()) {
114
1/2
✓ Branch 36 → 37 taken 135407 times.
✗ Branch 36 → 64 not taken.
135407 signature << "<";
115
2/2
✓ Branch 44 → 38 taken 169479 times.
✓ Branch 44 → 45 taken 135407 times.
304886 for (size_t i = 0; i < concreteTemplateTypes.size(); i++) {
116
2/2
✓ Branch 38 → 39 taken 34072 times.
✓ Branch 38 → 40 taken 135407 times.
169479 if (i > 0)
117
1/2
✓ Branch 39 → 40 taken 34072 times.
✗ Branch 39 → 64 not taken.
34072 signature << ",";
118
2/4
✓ Branch 40 → 41 taken 169479 times.
✗ Branch 40 → 64 not taken.
✓ Branch 41 → 42 taken 169479 times.
✗ Branch 41 → 64 not taken.
169479 concreteTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
119 }
120
1/2
✓ Branch 45 → 46 taken 135407 times.
✗ Branch 45 → 64 not taken.
135407 signature << ">";
121 }
122
123 // Parameter type string
124
1/2
✓ Branch 46 → 47 taken 282213 times.
✗ Branch 46 → 64 not taken.
282213 signature << "(";
125
2/2
✓ Branch 56 → 48 taken 337072 times.
✓ Branch 56 → 57 taken 282213 times.
619285 for (size_t i = 0; i < paramList.size(); i++) {
126
1/2
✓ Branch 48 → 49 taken 337072 times.
✗ Branch 48 → 64 not taken.
337072 const auto &[qualType, isOptional] = paramList.at(i);
127
2/2
✓ Branch 49 → 50 taken 138713 times.
✓ Branch 49 → 51 taken 198359 times.
337072 if (i > 0)
128
1/2
✓ Branch 50 → 51 taken 138713 times.
✗ Branch 50 → 64 not taken.
138713 signature << ",";
129
1/2
✓ Branch 51 → 52 taken 337072 times.
✗ Branch 51 → 64 not taken.
337072 qualType.getName(signature, withSize, ignorePublic, withTypeAliases);
130
1/2
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 337072 times.
337072 if (isOptional)
131 ✗ signature << "?";
132 }
133
1/2
✓ Branch 57 → 58 taken 282213 times.
✗ Branch 57 → 64 not taken.
282213 signature << ")";
134
135
1/2
✓ Branch 58 → 59 taken 282213 times.
✗ Branch 58 → 64 not taken.
564426 return signature.str();
136 282213 }
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 168969 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 227258 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 227256 times.
227258 if (!predefinedMangledName.empty())
153 2 return predefinedMangledName;
154 // Use function name if mangling is disabled
155
2/2
✓ Branch 5 → 6 taken 21266 times.
✓ Branch 5 → 7 taken 205990 times.
227256 if (!mangleFunctionName)
156 21266 return name;
157 // Use normal name mangling
158 205990 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 119782 std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) {
169
3/6
✓ Branch 2 → 3 taken 119782 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 119782 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 119782 times.
✗ Branch 4 → 10 not taken.
239564 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 246 std::string Function::getSymbolTableEntryNameDefaultCtor(const CodeLoc &structCodeLoc) {
179
5/10
✓ Branch 2 → 3 taken 246 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 246 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 246 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 246 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 246 times.
✗ Branch 8 → 17 not taken.
984 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 1290 std::string Function::getSymbolTableEntryNameDefaultCopyCtor(const CodeLoc &structCodeLoc) {
189
5/10
✓ Branch 2 → 3 taken 1290 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 1290 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 1290 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 1290 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 1290 times.
✗ Branch 8 → 17 not taken.
5160 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 740 std::string Function::getSymbolTableEntryNameDefaultDtor(const CodeLoc &structCodeLoc) {
209
5/10
✓ Branch 2 → 3 taken 740 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 740 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 740 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 740 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 740 times.
✗ Branch 8 → 17 not taken.
2960 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 7450192 bool Function::hasSubstantiatedParams() const {
219 19165975 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 596680 bool Function::hasSubstantiatedGenerics() const {
229 982365 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 379415 times.
✓ Branch 3 → 7 taken 6270 times.
✓ Branch 6 → 7 taken 150917 times.
✓ Branch 6 → 8 taken 228498 times.
385685 return !genericType.is(TY_GENERIC) || typeMapping.contains(genericType.getSubType());
235 596680 };
236
1/2
✓ Branch 2 → 3 taken 596680 times.
✗ Branch 2 → 6 not taken.
1193360 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 596680 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 368182 times.
✓ Branch 5 → 7 taken 228498 times.
596680 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 6423028 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 30609 const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; }
260
261 } // namespace spice::compiler
262