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 42480 Function::Function(std::string name, SymbolTableEntry *entry, const QualType &thisType, const QualType &returnType,
13 ParamList paramList, std::vector<GenericType> templateTypes, ASTNode *declNode)
14 127440 : name(std::move(name)), thisType(thisType), returnType(returnType), paramList(std::move(paramList)),
15 84960 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 235633 QualTypeList Function::getParamTypes() const {
23 235633 QualTypeList newParamTypes;
24
2/2
✓ Branch 16 → 4 taken 357891 times.
✓ Branch 16 → 17 taken 235633 times.
829157 for (const auto &[qualType, isOptional] : paramList)
25
1/2
✓ Branch 6 → 7 taken 357891 times.
✗ Branch 6 → 19 not taken.
357891 newParamTypes.push_back(qualType);
26 235633 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 173930 std::string Function::getSignature(bool withThisType /*=true*/, bool withTemplateTypes /*=true*/, bool withTypeAliases /*=true*/,
42 bool withSize /*=false*/) const {
43 173930 QualTypeList concreteTemplateTypes;
44
2/2
✓ Branch 2 → 3 taken 173928 times.
✓ Branch 2 → 34 taken 2 times.
173930 if (withTemplateTypes) {
45
1/2
✓ Branch 4 → 5 taken 173928 times.
✗ Branch 4 → 40 not taken.
173928 concreteTemplateTypes.reserve(templateTypes.size());
46
2/2
✓ Branch 32 → 7 taken 107818 times.
✓ Branch 32 → 33 taken 173928 times.
455674 for (const GenericType &genericType : templateTypes) {
47
7/8
✓ Branch 9 → 10 taken 107818 times.
✗ Branch 9 → 39 not taken.
✓ Branch 10 → 11 taken 106620 times.
✓ Branch 10 → 14 taken 1198 times.
✓ Branch 12 → 13 taken 63996 times.
✓ Branch 12 → 14 taken 42624 times.
✓ Branch 15 → 16 taken 63996 times.
✓ Branch 15 → 22 taken 43822 times.
107818 if (genericType.is(TY_GENERIC) && !typeMapping.empty()) {
48
1/2
✓ Branch 16 → 17 taken 63996 times.
✗ Branch 16 → 39 not taken.
63996 const std::string &subType = genericType.getSubType();
49
2/4
✓ Branch 17 → 18 taken 63996 times.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 63996 times.
63996 assert(typeMapping.contains(subType));
50
2/4
✓ Branch 20 → 21 taken 63996 times.
✗ Branch 20 → 39 not taken.
✓ Branch 21 → 23 taken 63996 times.
✗ Branch 21 → 39 not taken.
63996 concreteTemplateTypes.push_back(typeMapping.at(subType));
51 } else {
52
1/2
✓ Branch 22 → 23 taken 43822 times.
✗ Branch 22 → 39 not taken.
43822 concreteTemplateTypes.push_back(genericType);
53 }
54 }
55 }
56
57 173930 return getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, true, withThisType, true, withTypeAliases,
58
1/2
✓ Branch 34 → 35 taken 173930 times.
✗ Branch 34 → 40 not taken.
347860 withSize);
59 173930 }
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 173942 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 173942 times.
✗ Branch 2 → 66 not taken.
173942 std::stringstream signature;
81
82 // Build return type string
83
2/2
✓ Branch 3 → 4 taken 173930 times.
✓ Branch 3 → 10 taken 12 times.
173942 if (withReturnType) {
84
3/4
✓ Branch 4 → 5 taken 173930 times.
✗ Branch 4 → 64 not taken.
✓ Branch 5 → 6 taken 74860 times.
✓ Branch 5 → 7 taken 99070 times.
173930 if (returnType.is(TY_DYN)) {
85
1/2
✓ Branch 6 → 10 taken 74860 times.
✗ Branch 6 → 64 not taken.
74860 signature << "p ";
86 } else {
87
1/2
✓ Branch 7 → 8 taken 99070 times.
✗ Branch 7 → 64 not taken.
99070 signature << "f<";
88
1/2
✓ Branch 8 → 9 taken 99070 times.
✗ Branch 8 → 64 not taken.
99070 returnType.getName(signature, withSize, ignorePublic, withTypeAliases);
89
1/2
✓ Branch 9 → 10 taken 99070 times.
✗ Branch 9 → 64 not taken.
99070 signature << "> ";
90 }
91 }
92
93 // Build this type string
94
7/8
✓ Branch 10 → 11 taken 70426 times.
✓ Branch 10 → 14 taken 103516 times.
✓ Branch 11 → 12 taken 70426 times.
✗ Branch 11 → 64 not taken.
✓ Branch 12 → 13 taken 46934 times.
✓ Branch 12 → 14 taken 23492 times.
✓ Branch 15 → 16 taken 46934 times.
✓ Branch 15 → 33 taken 127008 times.
173942 if (withThisType && !thisType.is(TY_DYN)) {
95
3/6
✓ Branch 16 → 17 taken 46934 times.
✗ Branch 16 → 63 not taken.
✓ Branch 17 → 18 taken 46934 times.
✗ Branch 17 → 63 not taken.
✓ Branch 18 → 19 taken 46934 times.
✗ Branch 18 → 63 not taken.
46934 signature << thisType.getBase().getSubType();
96
1/2
✓ Branch 19 → 20 taken 46934 times.
✗ Branch 19 → 64 not taken.
46934 const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes();
97
2/2
✓ Branch 21 → 22 taken 25771 times.
✓ Branch 21 → 32 taken 21163 times.
46934 if (!thisTemplateTypes.empty()) {
98
1/2
✓ Branch 22 → 23 taken 25771 times.
✗ Branch 22 → 64 not taken.
25771 signature << "<";
99
2/2
✓ Branch 30 → 24 taken 32033 times.
✓ Branch 30 → 31 taken 25771 times.
57804 for (size_t i = 0; i < thisTemplateTypes.size(); i++) {
100
2/2
✓ Branch 24 → 25 taken 6262 times.
✓ Branch 24 → 26 taken 25771 times.
32033 if (i > 0)
101
1/2
✓ Branch 25 → 26 taken 6262 times.
✗ Branch 25 → 64 not taken.
6262 signature << ",";
102
2/4
✓ Branch 26 → 27 taken 32033 times.
✗ Branch 26 → 64 not taken.
✓ Branch 27 → 28 taken 32033 times.
✗ Branch 27 → 64 not taken.
32033 thisTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
103 }
104
1/2
✓ Branch 31 → 32 taken 25771 times.
✗ Branch 31 → 64 not taken.
25771 signature << ">";
105 }
106
1/2
✓ Branch 32 → 33 taken 46934 times.
✗ Branch 32 → 64 not taken.
46934 signature << MEMBER_ACCESS_TOKEN;
107 }
108
109 // Name
110
1/2
✓ Branch 33 → 34 taken 173942 times.
✗ Branch 33 → 64 not taken.
173942 signature << name;
111
112 // Build template type string
113
2/2
✓ Branch 35 → 36 taken 85554 times.
✓ Branch 35 → 46 taken 88388 times.
173942 if (!concreteTemplateTypes.empty()) {
114
1/2
✓ Branch 36 → 37 taken 85554 times.
✗ Branch 36 → 64 not taken.
85554 signature << "<";
115
2/2
✓ Branch 44 → 38 taken 107818 times.
✓ Branch 44 → 45 taken 85554 times.
193372 for (size_t i = 0; i < concreteTemplateTypes.size(); i++) {
116
2/2
✓ Branch 38 → 39 taken 22264 times.
✓ Branch 38 → 40 taken 85554 times.
107818 if (i > 0)
117
1/2
✓ Branch 39 → 40 taken 22264 times.
✗ Branch 39 → 64 not taken.
22264 signature << ",";
118
2/4
✓ Branch 40 → 41 taken 107818 times.
✗ Branch 40 → 64 not taken.
✓ Branch 41 → 42 taken 107818 times.
✗ Branch 41 → 64 not taken.
107818 concreteTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases);
119 }
120
1/2
✓ Branch 45 → 46 taken 85554 times.
✗ Branch 45 → 64 not taken.
85554 signature << ">";
121 }
122
123 // Parameter type string
124
1/2
✓ Branch 46 → 47 taken 173942 times.
✗ Branch 46 → 64 not taken.
173942 signature << "(";
125
2/2
✓ Branch 56 → 48 taken 178412 times.
✓ Branch 56 → 57 taken 173942 times.
352354 for (size_t i = 0; i < paramList.size(); i++) {
126
1/2
✓ Branch 48 → 49 taken 178412 times.
✗ Branch 48 → 64 not taken.
178412 const auto &[qualType, isOptional] = paramList.at(i);
127
2/2
✓ Branch 49 → 50 taken 59693 times.
✓ Branch 49 → 51 taken 118719 times.
178412 if (i > 0)
128
1/2
✓ Branch 50 → 51 taken 59693 times.
✗ Branch 50 → 64 not taken.
59693 signature << ",";
129
1/2
✓ Branch 51 → 52 taken 178412 times.
✗ Branch 51 → 64 not taken.
178412 qualType.getName(signature, withSize, ignorePublic, withTypeAliases);
130
1/2
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 178412 times.
178412 if (isOptional)
131 signature << "?";
132 }
133
1/2
✓ Branch 57 → 58 taken 173942 times.
✗ Branch 57 → 64 not taken.
173942 signature << ")";
134
135
1/2
✓ Branch 58 → 59 taken 173942 times.
✗ Branch 58 → 64 not taken.
347884 return signature.str();
136 173942 }
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 103516 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 123536 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 123535 times.
123536 if (!predefinedMangledName.empty())
153 1 return predefinedMangledName;
154 // Use function name if mangling is disabled
155
2/2
✓ Branch 5 → 6 taken 9573 times.
✓ Branch 5 → 7 taken 113962 times.
123535 if (!mangleFunctionName)
156 9573 return name;
157 // Use normal name mangling
158 113962 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 67074 std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) {
169
3/6
✓ Branch 2 → 3 taken 67074 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 67074 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 67074 times.
✗ Branch 4 → 10 not taken.
134148 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 165 std::string Function::getSymbolTableEntryNameDefaultCtor(const CodeLoc &structCodeLoc) {
179
5/10
✓ Branch 2 → 3 taken 165 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 165 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 165 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 165 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 165 times.
✗ Branch 8 → 17 not taken.
660 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 2012 std::string Function::getSymbolTableEntryNameDefaultCopyCtor(const CodeLoc &structCodeLoc) {
189
5/10
✓ Branch 2 → 3 taken 2012 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 2012 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 2012 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 2012 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 2012 times.
✗ Branch 8 → 17 not taken.
8048 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 1716 std::string Function::getSymbolTableEntryNameDefaultDtor(const CodeLoc &structCodeLoc) {
209
5/10
✓ Branch 2 → 3 taken 1716 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 1716 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 1716 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 1716 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 1716 times.
✗ Branch 8 → 17 not taken.
6864 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 5437958 bool Function::hasSubstantiatedParams() const {
219 13170200 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 456728 bool Function::hasSubstantiatedGenerics() const {
229 747098 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 287212 times.
✓ Branch 3 → 7 taken 3158 times.
✓ Branch 6 → 7 taken 121374 times.
✓ Branch 6 → 8 taken 165838 times.
290370 return !genericType.is(TY_GENERIC) || typeMapping.contains(genericType.getSubType());
235 456728 };
236
1/2
✓ Branch 2 → 3 taken 456728 times.
✗ Branch 2 → 6 not taken.
913456 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 456728 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 290890 times.
✓ Branch 5 → 7 taken 165838 times.
456728 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 4626179 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 257 const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; }
260
261 } // namespace spice::compiler
262