GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.6% 80 / 0 / 82
Functions: 100.0% 17 / 0 / 17
Branches: 62.1% 108 / 0 / 174

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 14338 Function::Function(std::string name, SymbolTableEntry *entry, const QualType &thisType, const QualType &returnType,
13 14338 ParamList paramList, std::vector<GenericType> templateTypes, ASTNode *declNode)
14 14338 : name(std::move(name)), thisType(thisType), returnType(returnType), paramList(std::move(paramList)),
15 14338 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 61177 QualTypeList Function::getParamTypes() const {
23 61177 QualTypeList newParamTypes;
24
2/2
✓ Branch 8 → 4 taken 106222 times.
✓ Branch 8 → 9 taken 61177 times.
167399 for (const auto &[qualType, isOptional] : paramList)
25
1/2
✓ Branch 5 → 6 taken 106222 times.
✗ Branch 5 → 11 not taken.
106222 newParamTypes.push_back(qualType);
26 61177 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 * @return String representation as function signature
39 */
40 53403 std::string Function::getSignature(bool withThisType /*=true*/, bool withTemplateTypes /*=true*/,
41 bool withTypeAliases /*=true*/) const {
42 53403 QualTypeList concreteTemplateTypes;
43
2/2
✓ Branch 2 → 3 taken 53401 times.
✓ Branch 2 → 27 taken 2 times.
53403 if (withTemplateTypes) {
44
1/2
✓ Branch 4 → 5 taken 53401 times.
✗ Branch 4 → 33 not taken.
53401 concreteTemplateTypes.reserve(templateTypes.size());
45
2/2
✓ Branch 25 → 7 taken 32622 times.
✓ Branch 25 → 26 taken 53401 times.
86023 for (const GenericType &genericType : templateTypes) {
46
7/8
✓ Branch 8 → 9 taken 32622 times.
✗ Branch 8 → 32 not taken.
✓ Branch 9 → 10 taken 32610 times.
✓ Branch 9 → 13 taken 12 times.
✓ Branch 11 → 12 taken 17470 times.
✓ Branch 11 → 13 taken 15140 times.
✓ Branch 14 → 15 taken 17470 times.
✓ Branch 14 → 22 taken 15152 times.
32622 if (genericType.is(TY_GENERIC) && !typeMapping.empty()) {
47
3/6
✓ Branch 15 → 16 taken 17470 times.
✗ Branch 15 → 32 not taken.
✓ Branch 16 → 17 taken 17470 times.
✗ Branch 16 → 32 not taken.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 17470 times.
17470 assert(typeMapping.contains(genericType.getSubType()));
48
3/6
✓ Branch 19 → 20 taken 17470 times.
✗ Branch 19 → 32 not taken.
✓ Branch 20 → 21 taken 17470 times.
✗ Branch 20 → 32 not taken.
✓ Branch 21 → 23 taken 17470 times.
✗ Branch 21 → 32 not taken.
17470 concreteTemplateTypes.push_back(typeMapping.at(genericType.getSubType()));
49 } else {
50
1/2
✓ Branch 22 → 23 taken 15152 times.
✗ Branch 22 → 32 not taken.
15152 concreteTemplateTypes.push_back(genericType);
51 }
52 }
53 }
54
55
1/2
✓ Branch 27 → 28 taken 53403 times.
✗ Branch 27 → 33 not taken.
106806 return getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, true, withThisType, true, withTypeAliases);
56 53403 }
57
58 /**
59 * Get a string representation of the current function.
60 *
61 * @param name Function name
62 * @param thisType This symbol type
63 * @param returnType Return symbol type
64 * @param paramList Param symbol types
65 * @param concreteTemplateTypes Concrete template symbol types
66 * @param withReturnType Include return type in signature
67 * @param withThisType Include 'this' type in signature
68 * @param ignorePublic Not include public modifiers in signature
69 * @param withTypeAliases Print type aliases as is and not decompose them
70 * @return Function signature
71 */
72 53415 std::string Function::getSignature(const std::string &name, const QualType &thisType, const QualType &returnType,
73 const ParamList &paramList, const QualTypeList &concreteTemplateTypes,
74 bool withReturnType /*=true*/, bool withThisType /*=true*/, bool ignorePublic /*=false*/,
75 bool withTypeAliases /*=true*/) {
76
1/2
✓ Branch 2 → 3 taken 53415 times.
✗ Branch 2 → 81 not taken.
53415 std::stringstream signature;
77
78 // Build return type string
79
2/2
✓ Branch 3 → 4 taken 53403 times.
✓ Branch 3 → 10 taken 12 times.
53415 if (withReturnType) {
80
3/4
✓ Branch 4 → 5 taken 53403 times.
✗ Branch 4 → 79 not taken.
✓ Branch 5 → 6 taken 21557 times.
✓ Branch 5 → 7 taken 31846 times.
53403 if (returnType.is(TY_DYN)) {
81
1/2
✓ Branch 6 → 10 taken 21557 times.
✗ Branch 6 → 79 not taken.
21557 signature << "p ";
82 } else {
83
1/2
✓ Branch 7 → 8 taken 31846 times.
✗ Branch 7 → 79 not taken.
31846 signature << "f<";
84
1/2
✓ Branch 8 → 9 taken 31846 times.
✗ Branch 8 → 79 not taken.
31846 returnType.getName(signature, false, ignorePublic, withTypeAliases);
85
1/2
✓ Branch 9 → 10 taken 31846 times.
✗ Branch 9 → 79 not taken.
31846 signature << "> ";
86 }
87 }
88
89 // Build this type string
90
7/8
✓ Branch 10 → 11 taken 21358 times.
✓ Branch 10 → 14 taken 32057 times.
✓ Branch 11 → 12 taken 21358 times.
✗ Branch 11 → 79 not taken.
✓ Branch 12 → 13 taken 11788 times.
✓ Branch 12 → 14 taken 9570 times.
✓ Branch 15 → 16 taken 11788 times.
✓ Branch 15 → 35 taken 41627 times.
53415 if (withThisType && !thisType.is(TY_DYN)) {
91
3/6
✓ Branch 16 → 17 taken 11788 times.
✗ Branch 16 → 69 not taken.
✓ Branch 17 → 18 taken 11788 times.
✗ Branch 17 → 69 not taken.
✓ Branch 18 → 19 taken 11788 times.
✗ Branch 18 → 69 not taken.
11788 signature << thisType.getBase().getSubType();
92
1/2
✓ Branch 19 → 20 taken 11788 times.
✗ Branch 19 → 79 not taken.
11788 const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes();
93
2/2
✓ Branch 21 → 22 taken 5493 times.
✓ Branch 21 → 34 taken 6295 times.
11788 if (!thisTemplateTypes.empty()) {
94
1/2
✓ Branch 22 → 23 taken 5493 times.
✗ Branch 22 → 79 not taken.
5493 signature << "<";
95
2/2
✓ Branch 32 → 24 taken 7018 times.
✓ Branch 32 → 33 taken 5493 times.
12511 for (size_t i = 0; i < thisTemplateTypes.size(); i++) {
96
2/2
✓ Branch 24 → 25 taken 1525 times.
✓ Branch 24 → 26 taken 5493 times.
7018 if (i > 0)
97
1/2
✓ Branch 25 → 26 taken 1525 times.
✗ Branch 25 → 79 not taken.
1525 signature << ",";
98
3/6
✓ Branch 26 → 27 taken 7018 times.
✗ Branch 26 → 72 not taken.
✓ Branch 27 → 28 taken 7018 times.
✗ Branch 27 → 72 not taken.
✓ Branch 28 → 29 taken 7018 times.
✗ Branch 28 → 70 not taken.
7018 signature << thisTemplateTypes.at(i).getName(false, ignorePublic, withTypeAliases);
99 }
100
1/2
✓ Branch 33 → 34 taken 5493 times.
✗ Branch 33 → 79 not taken.
5493 signature << ">";
101 }
102
1/2
✓ Branch 34 → 35 taken 11788 times.
✗ Branch 34 → 79 not taken.
11788 signature << MEMBER_ACCESS_TOKEN;
103 }
104
105 // Name
106
1/2
✓ Branch 35 → 36 taken 53415 times.
✗ Branch 35 → 79 not taken.
53415 signature << name;
107
108 // Build template type string
109
2/2
✓ Branch 37 → 38 taken 23885 times.
✓ Branch 37 → 50 taken 29530 times.
53415 if (!concreteTemplateTypes.empty()) {
110
1/2
✓ Branch 38 → 39 taken 23885 times.
✗ Branch 38 → 79 not taken.
23885 signature << "<";
111
2/2
✓ Branch 48 → 40 taken 32622 times.
✓ Branch 48 → 49 taken 23885 times.
56507 for (size_t i = 0; i < concreteTemplateTypes.size(); i++) {
112
2/2
✓ Branch 40 → 41 taken 8737 times.
✓ Branch 40 → 42 taken 23885 times.
32622 if (i > 0)
113
1/2
✓ Branch 41 → 42 taken 8737 times.
✗ Branch 41 → 79 not taken.
8737 signature << ",";
114
3/6
✓ Branch 42 → 43 taken 32622 times.
✗ Branch 42 → 75 not taken.
✓ Branch 43 → 44 taken 32622 times.
✗ Branch 43 → 75 not taken.
✓ Branch 44 → 45 taken 32622 times.
✗ Branch 44 → 73 not taken.
32622 signature << concreteTemplateTypes.at(i).getName(false, ignorePublic, withTypeAliases);
115 }
116
1/2
✓ Branch 49 → 50 taken 23885 times.
✗ Branch 49 → 79 not taken.
23885 signature << ">";
117 }
118
119 // Parameter type string
120
1/2
✓ Branch 50 → 51 taken 53415 times.
✗ Branch 50 → 79 not taken.
53415 signature << "(";
121
2/2
✓ Branch 62 → 52 taken 68601 times.
✓ Branch 62 → 63 taken 53415 times.
122016 for (size_t i = 0; i < paramList.size(); i++) {
122
1/2
✓ Branch 52 → 53 taken 68601 times.
✗ Branch 52 → 79 not taken.
68601 const auto &[qualType, isOptional] = paramList.at(i);
123
2/2
✓ Branch 53 → 54 taken 28637 times.
✓ Branch 53 → 55 taken 39964 times.
68601 if (i > 0)
124
1/2
✓ Branch 54 → 55 taken 28637 times.
✗ Branch 54 → 79 not taken.
28637 signature << ",";
125
2/4
✓ Branch 55 → 56 taken 68601 times.
✗ Branch 55 → 78 not taken.
✓ Branch 56 → 57 taken 68601 times.
✗ Branch 56 → 76 not taken.
68601 signature << qualType.getName(false, ignorePublic, withTypeAliases);
126
1/2
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 60 taken 68601 times.
68601 if (isOptional)
127 signature << "?";
128 }
129
1/2
✓ Branch 63 → 64 taken 53415 times.
✗ Branch 63 → 79 not taken.
53415 signature << ")";
130
131
1/2
✓ Branch 64 → 65 taken 53415 times.
✗ Branch 64 → 79 not taken.
106830 return signature.str();
132 53415 }
133
134 32057 std::string Function::getScopeName() const { return getSignature(false, true, false); }
135
136 33844 std::string Function::getMangledName() const {
137 // Use predefined mangled name if available
138
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 33843 times.
33844 if (!predefinedMangledName.empty())
139 1 return predefinedMangledName;
140 // Use function name if mangling is disabled
141
2/2
✓ Branch 5 → 6 taken 3286 times.
✓ Branch 5 → 7 taken 30557 times.
33843 if (!mangleFunctionName)
142 3286 return name;
143 // Use normal name mangling
144 30557 return NameMangling::mangleFunction(*this);
145 }
146
147 24773 std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) {
148
3/6
✓ Branch 2 → 3 taken 24773 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 24773 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 24773 times.
✗ Branch 4 → 10 not taken.
24773 return functionName + ":" + codeLoc.toString();
149 }
150
151 68 std::string Function::getSymbolTableEntryNameDefaultCtor(const CodeLoc &structCodeLoc) {
152
5/10
✓ Branch 2 → 3 taken 68 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 68 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 68 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 68 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 68 times.
✗ Branch 8 → 17 not taken.
204 return "default_" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
153 }
154
155 195 std::string Function::getSymbolTableEntryNameDefaultCopyCtor(const CodeLoc &structCodeLoc) {
156
5/10
✓ Branch 2 → 3 taken 195 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 195 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 195 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 195 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 195 times.
✗ Branch 8 → 17 not taken.
585 return "default_copy" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
157 }
158
159 104 std::string Function::getSymbolTableEntryNameDefaultDtor(const CodeLoc &structCodeLoc) {
160
5/10
✓ Branch 2 → 3 taken 104 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 104 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 104 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 104 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 104 times.
✗ Branch 8 → 17 not taken.
312 return "default_" + std::string(DTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString();
161 }
162
163 /**
164 * Checks if a function contains optional parameters.
165 * This would imply that the function is not substantiated by its optional parameters yet.
166 *
167 * @return Substantiated params or not
168 */
169 1158177 bool Function::hasSubstantiatedParams() const {
170 2890068 return std::ranges::none_of(paramList, [](const Param &param) { return param.isOptional; });
171 }
172
173 /**
174 * Checks if a function contains template types.
175 * This would imply that the function is not substantiated by its generic types yet.
176 *
177 * @return Substantiated generics or not
178 */
179 137599 bool Function::hasSubstantiatedGenerics() const {
180 73984 const auto predicate = [this](const GenericType &genericType) { return typeMapping.contains(genericType.getSubType()); };
181
1/2
✓ Branch 2 → 3 taken 137599 times.
✗ Branch 2 → 6 not taken.
275198 return std::ranges::all_of(templateTypes, predicate);
182 }
183
184 /**
185 * Checks if a function contains optional parameters or has generic types present.
186 * This would imply that the function is not fully substantiated yet.
187 *
188 * @return Fully substantiated or not
189 */
190
3/4
✓ Branch 3 → 4 taken 137599 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 89218 times.
✓ Branch 5 → 7 taken 48381 times.
137599 bool Function::isFullySubstantiated() const { return hasSubstantiatedParams() && hasSubstantiatedGenerics(); }
191
192 /**
193 * Returns, if this function is a substantiation of a generic one.
194 *
195 * @return Generic substantiation or not
196 */
197 914650 bool Function::isGenericSubstantiation() const { return genericPreset != nullptr; }
198
199 /**
200 * Retrieve the declaration code location of this function
201 *
202 * @return Declaration code location
203 */
204 4501 const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; }
205
206 } // namespace spice::compiler
207