1
2
3
4
5
6 #include <cmajor/symbols/FunctionSymbol.hpp>
7 #include <cmajor/symbols/ModuleCache.hpp>
8 #include <cmajor/symbols/TypeSymbol.hpp>
9 #include <cmajor/symbols/VariableSymbol.hpp>
10 #include <cmajor/symbols/ClassTypeSymbol.hpp>
11 #include <cmajor/symbols/ClassTemplateSpecializationSymbol.hpp>
12 #include <cmajor/symbols/SymbolTable.hpp>
13 #include <cmajor/symbols/SymbolWriter.hpp>
14 #include <cmajor/symbols/SymbolReader.hpp>
15 #include <cmajor/symbols/Module.hpp>
16 #include <cmajor/symbols/Exception.hpp>
17 #include <cmajor/symbols/TemplateSymbol.hpp>
18 #include <cmajor/symbols/GlobalFlags.hpp>
19 #include <cmajor/symbols/SymbolCollector.hpp>
20 #include <soulng/util/TextUtils.hpp>
21 #include <soulng/util/Unicode.hpp>
22 #include <soulng/util/Sha1.hpp>
23 #include <boost/uuid/uuid_generators.hpp>
24 #include <sstream>
25
26 namespace cmajor { namespace symbols {
27
28 AccessCheckFunction hasAccess;
29
30 void SetAccessCheckFunction(AccessCheckFunction accessCheckFunc)
31 {
32 hasAccess = accessCheckFunc;
33 }
34
35 AccessCheckFunction GetAccessCheckFunction()
36 {
37 if (!hasAccess)
38 {
39 throw std::runtime_error("access check functio not set");
40 }
41 return hasAccess;
42 }
43
44 bool FunctionSymbolsEqual::operator()(FunctionSymbol* left, FunctionSymbol* right) const
45 {
46 if (left->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol && right->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
47 {
48 ClassTemplateSpecializationSymbol* leftSpecialization = static_cast<ClassTemplateSpecializationSymbol*>(left->Parent());
49 ClassTemplateSpecializationSymbol* rightSpecialization = static_cast<ClassTemplateSpecializationSymbol*>(right->Parent());
50 if (TypesEqual(leftSpecialization, rightSpecialization))
51 {
52 int leftIndex = left->GetIndex();
53 int rightIndex = right->GetIndex();
54 if (leftIndex == -1 || rightIndex == -1)
55 {
56 return left == right;
57 }
58 else
59 {
60 return leftIndex == rightIndex;
61 }
62 }
63 }
64 else if (left->IsTemplateSpecialization() && right->IsTemplateSpecialization())
65 {
66 if (left->FunctionTemplate() == right->FunctionTemplate())
67 {
68 int n = left->TemplateArgumentTypes().size();
69 if (right->TemplateArgumentTypes().size() == n)
70 {
71 bool equal = true;
72 for (int i = 0; i < n; ++i)
73 {
74 if (!TypesEqual(left->TemplateArgumentTypes()[i], right->TemplateArgumentTypes()[i]))
75 {
76 equal = false;
77 break;
78 }
79 }
80 return equal;
81 }
82 }
83 }
84 else if (GetGlobalFlag(GlobalFlags::release) && !left->IsGeneratedFunction() && left->IsInline() && !right->IsGeneratedFunction() && right->IsInline())
85 {
86 return left->FunctionId() == right->FunctionId();
87 }
88 return left == right;
89 }
90
91 size_t FunctionSymbolHash::operator()(FunctionSymbol* fun) const
92 {
93 if (fun->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
94 {
95 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(fun->Parent());
96 return boost::hash<boost::uuids::uuid>()(specialization->TypeId()) ^ fun->GetIndex();
97 }
98 else if (fun->IsTemplateSpecialization())
99 {
100 size_t hashValue = boost::hash<boost::uuids::uuid>()(fun->FunctionTemplate()->FunctionId());
101 int n = fun->TemplateArgumentTypes().size();
102 for (int i = 0; i < n; ++i)
103 {
104 hashValue ^= boost::hash<boost::uuids::uuid>()(fun->TemplateArgumentTypes()[i]->TypeId());
105 }
106 return hashValue;
107 }
108 else if (GetGlobalFlag(GlobalFlags::release) && !fun->IsGeneratedFunction() && fun->IsInline())
109 {
110 return boost::hash<boost::uuids::uuid>()(fun->FunctionId());
111 }
112 return std::hash<FunctionSymbol*>()(fun);
113 }
114
115 void ViableFunctionSet::Insert(FunctionSymbol* fun)
116 {
117 auto it = set.find(fun);
118 if (it != set.cend())
119 {
120 set.erase(it);
121 }
122 set.insert(fun);
123 }
124
125 using namespace soulng::unicode;
126
127 class OperatorMangleMap
128 {
129 public:
130 static OperatorMangleMap& Instance() { Assert(instance, "operator mangle map not initialized"); return *instance; }
131 static void Init();
132 static void Done();
133 std::u32string Mangle(const std::u32string& groupName);
134 private:
135 static std::unique_ptr<OperatorMangleMap> instance;
136 std::unordered_map<std::u32string, std::u32string> mangleMap;
137 OperatorMangleMap();
138 };
139
140 std::unique_ptr<OperatorMangleMap> OperatorMangleMap::instance;
141
142 void OperatorMangleMap::Init()
143 {
144 instance.reset(new OperatorMangleMap());
145 }
146
147 void OperatorMangleMap::Done()
148 {
149 instance.reset();
150 }
151
152 OperatorMangleMap::OperatorMangleMap()
153 {
154 mangleMap[U"operator<<"] = U"op_shl";
155 mangleMap[U"operator>>"] = U"op_shr";
156 mangleMap[U"operator=="] = U"op_eq";
157 mangleMap[U"operator="] = U"op_assign";
158 mangleMap[U"operator<"] = U"op_less";
159 mangleMap[U"operator->"] = U"op_arrow";
160 mangleMap[U"operator++"] = U"op_plusplus";
161 mangleMap[U"operator--"] = U"op_minusminus";
162 mangleMap[U"operator+"] = U"op_plus";
163 mangleMap[U"operator-"] = U"op_minus";
164 mangleMap[U"operator*"] = U"op_star";
165 mangleMap[U"operator/"] = U"op_div";
166 mangleMap[U"operator%"] = U"op_rem";
167 mangleMap[U"operator&"] = U"op_and";
168 mangleMap[U"operator|"] = U"op_or";
169 mangleMap[U"operator^"] = U"op_xor";
170 mangleMap[U"operator!"] = U"op_not";
171 mangleMap[U"operator~"] = U"op_cpl";
172 mangleMap[U"operator[]"] = U"op_index";
173 mangleMap[U"operator()"] = U"op_apply";
174 }
175
176 std::u32string OperatorMangleMap::Mangle(const std::u32string& groupName)
177 {
178 auto it = mangleMap.find(groupName);
179 if (it != mangleMap.cend())
180 {
181 return it->second;
182 }
183 else
184 {
185 return U"operator";
186 }
187 }
188
189 FunctionGroupSymbol::FunctionGroupSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) : Symbol(SymbolType::functionGroupSymbol, span_, sourceModuleId_, name_)
190 {
191 }
192
193 void FunctionGroupSymbol::ComputeMangledName()
194 {
195 std::u32string mangledName = ToUtf32(TypeString());
196 if (Name().find(U"operator") != std::u32string::npos)
197 {
198 mangledName.append(1, U'_').append(OperatorMangleMap::Instance().Mangle(Name()));
199 }
200 else if (Name().find(U'@') == std::u32string::npos)
201 {
202 mangledName.append(1, U'_').append(Name());
203 }
204 mangledName.append(1, U'_').append(ToUtf32(GetSha1MessageDigest(ToUtf8(FullNameWithSpecifiers()))));
205 SetMangledName(mangledName);
206 }
207
208 void FunctionGroupSymbol::AddFunction(FunctionSymbol* function)
209 {
210 if (function->IsProgramMain()) return;
211 Assert(function->GroupName() == Name(), "wrong function group");
212 if (function->IsVarArg())
213 {
214 varArgFunctions.push_back(function);
215 }
216 else
217 {
218 int arity = function->Arity();
219 std::std::vector<FunctionSymbol*>&functionList=arityFunctionListMap[arity];
220 functionList.push_back(function);
221 function->SetFunctionGroup(this);
222 }
223 }
224
225 void FunctionGroupSymbol::RemoveFunction(FunctionSymbol* function)
226 {
227 if (function->IsVarArg())
228 {
229 auto end = std::remove(varArgFunctions.begin(), varArgFunctions.end(), function);
230 varArgFunctions.erase(end, varArgFunctions.end());
231 }
232 else
233 {
234 int arity = function->Arity();
235 std::std::vector<FunctionSymbol*>&functionList=arityFunctionListMap[arity];
236 auto end = std::remove(functionList.begin(), functionList.end(), function);
237 functionList.erase(end, functionList.end());
238 }
239 }
240
241 bool FunctionGroupSymbol::IsEmpty() const
242 {
243 for (const auto& p : arityFunctionListMap)
244 {
245 if (!p.second.empty()) return false;
246 }
247 return true;
248 }
249
250 FunctionSymbol* FunctionGroupSymbol::GetFunction()
251 {
252 if (arityFunctionListMap.size() == 1)
253 {
254 std::std::vector<FunctionSymbol*>&functionList=arityFunctionListMap.begin()->second;
255 if (functionList.size() == 1)
256 {
257 return functionList[0];
258 }
259 }
260 return nullptr;
261 }
262
263 void FunctionGroupSymbol::CollectViableFunctions(int arity, ViableFunctionSet& viableFunctions, Module* module)
264 {
265 auto it = arityFunctionListMap.find(arity);
266 if (it != arityFunctionListMap.cend())
267 {
268 std::std::vector<FunctionSymbol*>&functionList=it->second;
269 for (FunctionSymbol* function : functionList)
270 {
271 viableFunctions.Insert(function);
272 }
273 }
274 for (FunctionSymbol* varArgFunction : varArgFunctions)
275 {
276 if (arity >= varArgFunction->Arity())
277 {
278 viableFunctions.Insert(varArgFunction);
279 }
280 }
281 }
282
283 bool FunctionGroupSymbol::HasProjectMembers() const
284 {
285 for (const auto& p : arityFunctionListMap)
286 {
287 for (FunctionSymbol* fun : p.second)
288 {
289 if (fun->IsTemplateSpecialization()) continue;
290 if (fun->IsProject())
291 {
292 return true;
293 }
294 }
295 }
296 return false;
297 }
298
299 void FunctionGroupSymbol::AppendChildElements(sngxml::dom::Element* element, TypeMap& typeMap) const
300 {
301 for (const auto& p : arityFunctionListMap)
302 {
303 for (FunctionSymbol* fun : p.second)
304 {
305 if (fun->IsTemplateSpecialization()) continue;
306 if (fun->IsProject())
307 {
308 std::unique_ptr<sngxml::dom::Element> functionElement = fun->ToDomElement(typeMap);
309 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(functionElement.release()));
310 }
311 }
312 }
313 }
314
315 void FunctionGroupSymbol::Check()
316 {
317 Symbol::Check();
318 for (const auto& p : arityFunctionListMap)
319 {
320 for (const auto& q : p.second)
321 {
322 if (!q)
323 {
324 throw SymbolCheckException("function group symbol contains empty function pointer", GetSpan(), SourceModuleId());
325 }
326 }
327 }
328 }
329
330 void FunctionGroupSymbol::CheckDuplicateFunctionSymbols()
331 {
332 for (const auto& p : arityFunctionListMap)
333 {
334 std::set<std::u32string> names;
335 for (const auto& functionSymbol : p.second)
336 {
337 if (!functionSymbol->IsFunctionTemplate() && !functionSymbol->IsTemplateSpecialization())
338 {
339 if (names.find(functionSymbol->FullName()) != names.cend())
340 {
341 throw Exception("function with identical name '" + ToUtf8(functionSymbol->FullName()) + "' already defined.", GetSpan(), SourceModuleId());
342 }
343 names.insert(functionSymbol->FullName());
344 }
345 }
346 }
347 }
348
349 std::string FunctionGroupSymbol::GetSymbolHelp() const
350 {
351 if (arityFunctionListMap.size() == 1)
352 {
353 const std::std::vector<FunctionSymbol*>&v=arityFunctionListMap.begin()->second;
354 if (v.size() == 1)
355 {
356 FunctionSymbol* fun = v.front();
357 return fun->GetSymbolHelp();
358 }
359 }
360 int n = 0;
361 for (const auto& p : arityFunctionListMap)
362 {
363 n = n + p.second.size();
364 }
365 std::string help = "(";
366 help.append(GetSymbolCategoryDescription()).append(") ").append(ToUtf8(FullName())).append(" (").append(std::to_string(n)).append(" overloads)");
367 return help;
368 }
369
370 bool FunctionGroupSymbol::IsValidCCFunctionGroup(FunctionSymbol* fromFunction) const
371 {
372 AccessCheckFunction canAccess = GetAccessCheckFunction();
373 if (!fromFunction) return false;
374 if (StartsWith(Name(), U"@")) return false;
375 if (StartsWith(Name(), U"operator")) return false;
376 for (const auto& p : arityFunctionListMap)
377 {
378 for (auto functionSymbol : p.second)
379 {
380 if (canAccess(fromFunction, functionSymbol)) return true;
381 }
382 }
383 return false;
384 }
385
386 std::string FunctionGroupSymbol::GetOverloadList() const
387 {
388 sngxml::dom::Document doc;
389 sngxml::dom::Element* root = new sngxml::dom::Element(U"overloadList");
390 doc.AppendChild(std::unique_ptr<sngxml::dom::Node>(root));
391 for (const auto& p : arityFunctionListMap)
392 {
393 for (auto functionSymbol : p.second)
394 {
395 sngxml::dom::Element* overloadElement = new sngxml::dom::Element(U"overload");
396 std::u32string overloadName = functionSymbol->FullName(true);
397 overloadElement->SetAttribute(U"name", overloadName);
398 root->AppendChild(std::unique_ptr<sngxml::dom::Node>(overloadElement));
399 }
400 }
401 std::stringstream s;
402 CodeFormatter formatter(s);
403 formatter.SetIndentSize(1);
404 doc.Write(formatter);
405 return s.str();
406 }
407
408 std::string FunctionSymbolFlagStr(FunctionSymbolFlags flags)
409 {
410 std::string s;
411 if ((flags & FunctionSymbolFlags::inline_) != FunctionSymbolFlags::none)
412 {
413 s.append("inline");
414 }
415 if ((flags & FunctionSymbolFlags::constExpr) != FunctionSymbolFlags::none)
416 {
417 if (!s.empty())
418 {
419 s.append(1, ' ');
420 }
421 s.append("constexpr");
422 }
423 if ((flags & FunctionSymbolFlags::cdecl_) != FunctionSymbolFlags::none)
424 {
425 if (!s.empty())
426 {
427 s.append(1, ' ');
428 }
429 s.append("cdecl");
430 }
431 if ((flags & FunctionSymbolFlags::suppress) != FunctionSymbolFlags::none)
432 {
433 if (!s.empty())
434 {
435 s.append(1, ' ');
436 }
437 s.append("suppress");
438 }
439 if ((flags & FunctionSymbolFlags::default_) != FunctionSymbolFlags::none)
440 {
441 if (!s.empty())
442 {
443 s.append(1, ' ');
444 }
445 s.append("default");
446 }
447 if ((flags & FunctionSymbolFlags::explicit_) != FunctionSymbolFlags::none)
448 {
449 if (!s.empty())
450 {
451 s.append(1, ' ');
452 }
453 s.append("explicit");
454 }
455 if ((flags & FunctionSymbolFlags::virtual_) != FunctionSymbolFlags::none)
456 {
457 if (!s.empty())
458 {
459 s.append(1, ' ');
460 }
461 s.append("virtual");
462 }
463 if ((flags & FunctionSymbolFlags::override_) != FunctionSymbolFlags::none)
464 {
465 if (!s.empty())
466 {
467 s.append(1, ' ');
468 }
469 s.append("override");
470 }
471 if ((flags & FunctionSymbolFlags::abstract_) != FunctionSymbolFlags::none)
472 {
473 if (!s.empty())
474 {
475 s.append(1, ' ');
476 }
477 s.append("abstract");
478 }
479 return s;
480 }
481
482 FunctionSymbol::FunctionSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
483 ContainerSymbol(SymbolType::functionSymbol, span_, sourceModuleId_, name_), functionTemplate(nullptr), master(nullptr),
484 functionId(boost::uuids::nil_uuid()), groupName(), parameters(), localVariables(),
485 returnType(), flags(FunctionSymbolFlags::none), index(-1), vmtIndex(-1), imtIndex(-1),
486 nextTemporaryIndex(0), functionGroup(nullptr), isProgramMain(false), unwindInfoVar(nullptr),
487 conversionSourceType(nullptr), conversionTargetType(nullptr)
488 {
489 }
490
491 FunctionSymbol::FunctionSymbol(SymbolType symbolType_, const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
492 ContainerSymbol(symbolType_, span_, sourceModuleId_, name_), functionTemplate(nullptr), master(nullptr),
493 functionId(boost::uuids::nil_uuid()), groupName(), parameters(), localVariables(),
494 returnType(), flags(FunctionSymbolFlags::none), index(-1), vmtIndex(-1), imtIndex(-1),
495 nextTemporaryIndex(0), functionGroup(nullptr), isProgramMain(false), unwindInfoVar(nullptr),
496 conversionSourceType(nullptr), conversionTargetType(nullptr)
497 {
498 }
499
500 void FunctionSymbol::Write(SymbolWriter& writer)
501 {
502 ContainerSymbol::Write(writer);
503 Assert(!functionId.is_nil(), "function id not initialized");
504 writer.GetBinaryWriter().Write(functionId);
505 writer.GetBinaryWriter().Write(index);
506 writer.GetBinaryWriter().Write(groupName);
507 writer.GetBinaryWriter().Write(static_cast<uint32_t>(flags));
508 boost::uuids::uuid functionTemplateId = boost::uuids::nil_uuid();
509 if (functionTemplate)
510 {
511 functionTemplateId = functionTemplate->FunctionId();
512 }
513 writer.GetBinaryWriter().Write(functionTemplateId);
514 if (IsFunctionTemplate() || (GetGlobalFlag(GlobalFlags::release) && IsInline()) || IsConstExpr())
515 {
516 usingNodes.Write(writer.GetAstWriter());
517 Node* node = GetRootModuleForCurrentThread()->GetSymbolTable().GetNode(this);
518 writer.GetAstWriter().Write(node);
519 }
520 boost::uuids::uuid returnTypeId = boost::uuids::nil_uuid();
521 if (returnType)
522 {
523 returnTypeId = returnType->TypeId();
524 }
525 writer.GetBinaryWriter().Write(returnTypeId);
526 writer.GetBinaryWriter().Write(vmtIndex);
527 writer.GetBinaryWriter().Write(imtIndex);
528 bool hasReturnParam = returnParam != nullptr;
529 writer.GetBinaryWriter().Write(hasReturnParam);
530 if (hasReturnParam)
531 {
532 writer.Write(returnParam.get());
533 }
534 if (constraint)
535 {
536 writer.GetBinaryWriter().Write(true);
537 writer.GetAstWriter().Write(constraint.get());
538 }
539 else
540 {
541 writer.GetBinaryWriter().Write(false);
542 }
543 uint32_t n = templateArgumentTypes.size();
544 writer.GetBinaryWriter().WriteULEB128UInt(n);
545 for (uint32_t i = 0; i < n; ++i)
546 {
547 TypeSymbol* templateArgumentType = templateArgumentTypes[i];
548 writer.GetBinaryWriter().Write(templateArgumentType->TypeId());
549 }
550 if (IsConversion())
551 {
552 writer.GetBinaryWriter().Write(conversionSourceType->TypeId());
553 writer.GetBinaryWriter().Write(conversionTargetType->TypeId());
554 }
555 }
556
557 void FunctionSymbol::Read(SymbolReader& reader)
558 {
559 ContainerSymbol::Read(reader);
560 reader.GetBinaryReader().ReadUuid(functionId);
561 index = reader.GetBinaryReader().ReadInt();
562 reader.GetSymbolTable()->AddFunctionSymbolToFunctionIdMap(this);
563 groupName = reader.GetBinaryReader().ReadUtf32String();
564 flags = static_cast<FunctionSymbolFlags>(reader.GetBinaryReader().ReadUInt());
565 boost::uuids::uuid functionTemplateId;
566 reader.GetBinaryReader().ReadUuid(functionTemplateId);
567 if (!functionTemplateId.is_nil())
568 {
569 reader.GetSymbolTable()->EmplaceFunctionRequest(reader, this, functionTemplateId, 0);
570 }
571 if (IsFunctionTemplate() || (GetGlobalFlag(GlobalFlags::release) && IsInline()) || IsConstExpr())
572 {
573 usingNodes.Read(reader.GetAstReader());
574 Node* node = reader.GetAstReader().ReadNode();
575 FunctionNode* funNode = static_cast<FunctionNode*>(node);
576 functionNode.reset(funNode);
577 }
578 boost::uuids::uuid returnTypeId;
579 reader.GetBinaryReader().ReadUuid(returnTypeId);
580 if (!returnTypeId.is_nil())
581 {
582 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, returnTypeId, 0);
583 }
584 vmtIndex = reader.GetBinaryReader().ReadInt();
585 imtIndex = reader.GetBinaryReader().ReadInt();
586 bool hasReturnParam = reader.GetBinaryReader().ReadBool();
587 if (hasReturnParam)
588 {
589 returnParam.reset(reader.ReadParameterSymbol(this));
590 }
591 bool hasConstraint = reader.GetBinaryReader().ReadBool();
592 if (hasConstraint)
593 {
594 constraint.reset(reader.GetAstReader().ReadConstraintNode());
595 }
596 uint32_t n = reader.GetBinaryReader().ReadULEB128UInt();
597 templateArgumentTypes.resize(n);
598 for (uint32_t i = 0; i < n; ++i)
599 {
600 boost::uuids::uuid templateArgumentId;
601 reader.GetBinaryReader().ReadUuid(templateArgumentId);
602 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, templateArgumentId, -1 - i);
603 }
604 if (IsConversion())
605 {
606 boost::uuids::uuid conversionSourceTypeId;
607 reader.GetBinaryReader().ReadUuid(conversionSourceTypeId);
608 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, conversionSourceTypeId, 10000);
609 boost::uuids::uuid conversionTargetTypeId;
610 reader.GetBinaryReader().ReadUuid(conversionTargetTypeId);
611 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, conversionTargetTypeId, 10001);
612 reader.AddConversion(this);
613 }
614 }
615
616 void FunctionSymbol::EmplaceFunction(FunctionSymbol* functionSymbol, int index)
617 {
618 if (index == 0)
619 {
620 functionTemplate = functionSymbol;
621 }
622 else
623 {
624 Assert(false, "invalid emplace function index");
625 }
626 }
627
628 void FunctionSymbol::Accept(SymbolCollector* collector)
629 {
630 if (IsProject() && Access() == SymbolAccess::public_ && !IsGeneratedFunction())
631 {
632 collector->AddFunction(this);
633 }
634 }
635
636 void FunctionSymbol::EmplaceType(TypeSymbol* typeSymbol, int index)
637 {
638 if (index == 10000)
639 {
640 conversionSourceType = typeSymbol;
641 }
642 else if (index == 10001)
643 {
644 conversionTargetType = typeSymbol;
645 }
646 else if (index == 0)
647 {
648 returnType = typeSymbol;
649 }
650 else if (index < 0)
651 {
652 int templateArgumentIndex = -(index + 1);
653 if (templateArgumentIndex < 0 || templateArgumentIndex >= templateArgumentTypes.size())
654 {
655 throw Exception("invalid emplace template argument index '" + std::to_string(index) + "'", GetSpan(), SourceModuleId());
656 }
657 templateArgumentTypes[templateArgumentIndex] = typeSymbol;
658 }
659 else
660 {
661 throw Exception("invalid emplace type index '" + std::to_string(index) + "'", GetSpan(), SourceModuleId());
662 }
663 }
664
665 void FunctionSymbol::AddMember(Symbol* member)
666 {
667 ContainerSymbol::AddMember(member);
668 if (member->GetSymbolType() == SymbolType::templateParameterSymbol)
669 {
670 templateParameters.push_back(static_cast<TemplateParameterSymbol*>(member));
671 }
672 else if (member->GetSymbolType() == SymbolType::parameterSymbol)
673 {
674 parameters.push_back(static_cast<ParameterSymbol*>(member));
675 }
676 }
677
678 bool FunctionSymbol::IsExportSymbol() const
679 {
680 if (IsTemplateSpecialization() && Parent()->GetSymbolType() != SymbolType::classTemplateSpecializationSymbol) return false;
681 if (IsGeneratedFunction()) return false;
682 if (intrinsic) return false;
683 if (IsCopy()) return false;
684 return ContainerSymbol::IsExportSymbol();
685 }
686
687 void FunctionSymbol::ComputeName()
688 {
689 std::u32string name;
690 name.append(groupName);
691 name.append(1, U'(');
692 int n = parameters.size();
693 for (int i = 0; i < n; ++i)
694 {
695 if (i > 0)
696 {
697 name.append(U", ");
698 }
699 ParameterSymbol* parameter = parameters[i];
700 if (i == 0 && (groupName == U"@constructor" || groupName == U"operator=" || IsConstructorDestructorOrNonstaticMemberFunction()))
701 {
702 name.append(parameter->GetType()->RemovePointer(GetSpan(), SourceModuleId())->FullName());
703 }
704 else
705 {
706 name.append(parameter->GetType()->FullName());
707 }
708 name.append(1, U' ');
709 name.append(std::u32string(parameter->Name()));
710 }
711 name.append(1, U')');
712 SetName(name);
713 if (!IsBasicTypeOperation())
714 {
715 ComputeMangledName();
716 }
717 }
718
719 void FunctionSymbol::ComputeMangledName()
720 {
721 if (IsCDecl())
722 {
723 SetMangledName(GroupName());
724 return;
725 }
726 std::u32string mangledName = ToUtf32(TypeString());
727 if (groupName.find(U"operator") != std::u32string::npos)
728 {
729 mangledName.append(1, U'_').append(OperatorMangleMap::Instance().Mangle(GroupName()));
730 }
731 else if (groupName.find(U'@') == std::u32string::npos)
732 {
733 mangledName.append(1, U'_').append(GroupName());
734 }
735 SymbolType symbolType = GetSymbolType();
736 switch (symbolType)
737 {
738 case SymbolType::staticConstructorSymbol: case SymbolType::constructorSymbol: case SymbolType::destructorSymbol: case SymbolType::memberFunctionSymbol:
739 {
740 Symbol* parentClass = Parent();
741 mangledName.append(1, U'_').append(parentClass->SimpleName());
742 }
743 }
744 std::string templateArgumentString;
745 for (TypeSymbol* templateArgumentType : templateArgumentTypes)
746 {
747 templateArgumentString.append("_").append(ToUtf8(templateArgumentType->FullName()));
748 }
749 std::string constraintString;
750 if (Constraint())
751 {
752 constraintString = " " + Constraint()->ToString();
753 }
754 mangledName.append(1, U'_').append(ToUtf32(GetSha1MessageDigest(ToUtf8(FullNameWithSpecifiers()) + templateArgumentString + constraintString)));
755 SetMangledName(mangledName);
756 }
757
758 std::u32string FunctionSymbol::FullName(bool withParamNames) const
759 {
760 std::u32string fullName;
761 if (!Parent())
762 {
763 throw Exception("function symbol has no parent", GetSpan(), SourceModuleId());
764 }
765 std::u32string parentFullName = Parent()->FullName();
766 fullName.append(parentFullName);
767 if (!parentFullName.empty())
768 {
769 fullName.append(1, U'.');
770 }
771 if (groupName == U"@constructor")
772 {
773 fullName.append(Parent()->Name());
774 }
775 else if (groupName == U"@destructor")
776 {
777 fullName.append(U"~").append(Parent()->Name());
778 }
779 else
780 {
781 fullName.append(groupName);
782 }
783 fullName.append(1, U'(');
784 int n = parameters.size();
785 int startParamIndex = StartParamIndex();
786 for (int i = startParamIndex; i < n; ++i)
787 {
788 if (i > startParamIndex)
789 {
790 fullName.append(U", ");
791 }
792 ParameterSymbol* parameter = parameters[i];
793 fullName.append(parameter->GetType()->FullName());
794 if (withParamNames)
795 {
796 fullName.append(U" ").append(parameter->Name());
797 }
798 }
799 fullName.append(1, U')');
800 if (IsConst())
801 {
802 fullName.append(U" const");
803 }
804 return fullName;
805 }
806
807 std::u32string FunctionSymbol::FullName() const
808 {
809 return FullName(false);
810 }
811
812 std::u32string FunctionSymbol::FullNameWithSpecifiers() const
813 {
814 std::u32string fullNameWithSpecifiers = ToUtf32(SymbolFlagStr(GetStableSymbolFlags()));
815 std::u32string f = ToUtf32(FunctionSymbolFlagStr(flags));
816 if (!f.empty())
817 {
818 if (!fullNameWithSpecifiers.empty())
819 {
820 fullNameWithSpecifiers.append(1, U' ');
821 }
822 fullNameWithSpecifiers.append(f);
823 }
824 if (!fullNameWithSpecifiers.empty())
825 {
826 fullNameWithSpecifiers.append(1, U' ');
827 }
828 fullNameWithSpecifiers.append(FullName());
829 return fullNameWithSpecifiers;
830 }
831
832 std::u32string FunctionSymbol::DocName() const
833 {
834 std::u32string docName = groupName;
835 if (!templateParameters.empty())
836 {
837 docName.append(1, '<');
838 bool first = true;
839 for (TemplateParameterSymbol* templateParameter : templateParameters)
840 {
841 if (first)
842 {
843 first = false;
844 }
845 else
846 {
847 docName.append(U", ");
848 }
849 docName.append(templateParameter->DocName());
850 }
851 docName.append(1, '>');
852 }
853 docName.append(1, '(');
854 int n = parameters.size();
855 for (int i = 0; i < n; ++i)
856 {
857 if (i > 0)
858 {
859 docName.append(U", ");
860 }
861 ParameterSymbol* parameter = parameters[i];
862 if (parameter->GetType()->Ns() == Ns())
863 {
864 docName.append(parameter->GetType()->Name());
865 }
866 else
867 {
868 docName.append(parameter->GetType()->FullName());
869 }
870 docName.append(1, ' ').append(parameter->Name());
871 }
872 docName.append(1, ')');
873 return docName;
874 }
875
876 std::string FunctionSymbol::GetSpecifierStr() const
877 {
878 std::string specifierStr = SymbolFlagStr(GetStableSymbolFlags());
879 std::string f = FunctionSymbolFlagStr(flags);
880 if (!f.empty())
881 {
882 if (!specifierStr.empty())
883 {
884 specifierStr.append(1, ' ');
885 }
886 specifierStr.append(f);
887 }
888 return specifierStr;
889 }
890
891 std::string FunctionSymbol::Syntax() const
892 {
893 std::string syntax = GetSpecifierStr();
894 if (!syntax.empty())
895 {
896 syntax.append(1, ' ');
897 }
898 if (ReturnType())
899 {
900 syntax.append(ToUtf8(ReturnType()->DocName()));
901 syntax.append(1, ' ');
902 }
903 syntax.append(ToUtf8(DocName()));
904 syntax.append(1, ';');
905 return syntax;
906 }
907
908 void FunctionSymbol::SetConversionSourceType(TypeSymbol* conversionSourceType_)
909 {
910 conversionSourceType = conversionSourceType_;
911 }
912
913 void FunctionSymbol::SetConversionTargetType(TypeSymbol* conversionTargetType_)
914 {
915 conversionTargetType = conversionTargetType_;
916 }
917
918 void FunctionSymbol::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
919 {
920 if ((flags & OperationFlags::virtualCall) != OperationFlags::none)
921 {
922 GenerateVirtualCall(emitter, genObjects, flags, span, moduleId);
923 return;
924 }
925 int na = genObjects.size();
926 for (int i = 0; i < na; ++i)
927 {
928 GenObject* genObject = genObjects[i];
929 genObject->Load(emitter, flags & OperationFlags::functionCallFlags);
930 }
931 emitter.SetCurrentDebugLocation(span);
932 void* functionType = IrType(emitter);
933 void* callee = emitter.GetOrInsertFunction(ToUtf8(MangledName()), functionType, DontThrow());
934 std::vector<void*> args;
935 int n = parameters.size();
936 if (ReturnsClassInterfaceOrClassDelegateByValue())
937 {
938 ++n;
939 }
940 args.resize(n);
941 for (int i = 0; i < n; ++i)
942 {
943 void* arg = emitter.Stack().Pop();
944 args[n - i - 1] = arg;
945 }
946 void* handlerBlock = emitter.HandlerBlock();
947 void* cleanupBlock = emitter.CleanupBlock();
948 bool newCleanupNeeded = emitter.NewCleanupNeeded();
949 Pad* currentPad = emitter.CurrentPad();
950 std::vector<void*> bundles;
951 if (currentPad != nullptr)
952 {
953 bundles.push_back(currentPad->value);
954 }
955 if (ReturnType() && ReturnType()->GetSymbolType() != SymbolType::voidTypeSymbol && !ReturnsClassInterfaceOrClassDelegateByValue())
956 {
957 if (DontThrow() || GetSymbolType() == SymbolType::destructorSymbol || (!handlerBlock && !cleanupBlock && !newCleanupNeeded))
958 {
959 if (currentPad == nullptr)
960 {
961 emitter.Stack().Push(emitter.CreateCall(callee, args));
962 }
963 else
964 {
965 emitter.Stack().Push(emitter.CreateCallInst(callee, args, bundles, span));
966 }
967 }
968 else
969 {
970 void* nextBlock = nullptr;
971 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
972 {
973 nextBlock = emitter.CreateBasicBlock("next");
974 }
975 if (newCleanupNeeded)
976 {
977 emitter.CreateCleanup();
978 cleanupBlock = emitter.CleanupBlock();
979 }
980 void* unwindBlock = cleanupBlock;
981 if (unwindBlock == nullptr)
982 {
983 unwindBlock = handlerBlock;
984 Assert(unwindBlock, "no unwind block");
985 }
986 if (currentPad == nullptr)
987 {
988 emitter.Stack().Push(emitter.CreateInvoke(callee, nextBlock, unwindBlock, args));
989 }
990 else
991 {
992 emitter.Stack().Push(emitter.CreateInvokeInst(callee, nextBlock, unwindBlock, args, bundles, span));
993 }
994 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
995 {
996 emitter.SetCurrentBasicBlock(nextBlock);
997 }
998 }
999 }
1000 else
1001 {
1002 if (DontThrow() || GetSymbolType() == SymbolType::destructorSymbol || (!handlerBlock && !cleanupBlock && !newCleanupNeeded))
1003 {
1004 if (currentPad == nullptr)
1005 {
1006 emitter.CreateCall(callee, args);
1007 }
1008 else
1009 {
1010 emitter.CreateCallInst(callee, args, bundles, span);
1011 }
1012 }
1013 else
1014 {
1015 void* nextBlock = nullptr;
1016 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1017 {
1018 nextBlock = emitter.CreateBasicBlock("next");
1019 }
1020 if (newCleanupNeeded)
1021 {
1022 emitter.CreateCleanup();
1023 cleanupBlock = emitter.CleanupBlock();
1024 }
1025 void* unwindBlock = cleanupBlock;
1026 if (unwindBlock == nullptr)
1027 {
1028 unwindBlock = handlerBlock;
1029 Assert(unwindBlock, "no unwind block");
1030 }
1031 if (currentPad == nullptr)
1032 {
1033 emitter.CreateInvoke(callee, nextBlock, unwindBlock, args);
1034 }
1035 else
1036 {
1037 emitter.CreateInvokeInst(callee, nextBlock, unwindBlock, args, bundles, span);
1038 }
1039 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1040 {
1041 emitter.SetCurrentBasicBlock(nextBlock);
1042 }
1043 }
1044 }
1045 }
1046
1047 void FunctionSymbol::GenerateVirtualCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1048 {
1049 int na = genObjects.size();
1050 Assert(na > 0, "nonempty argument list expected");
1051 Assert(VmtIndex() != -1, "member function has invalid vmt index");
1052 GenObject* classPtrArg = genObjects[0];
1053 TypeSymbol* type = static_cast<TypeSymbol*>(classPtrArg->GetType());
1054 Assert(type, "type expected");
1055 Assert(type->BaseType()->IsClassTypeSymbol(), "class type pointer expected");
1056 ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type->BaseType());
1057 ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
1058 void* callee = nullptr;
1059 for (int i = 0; i < na; ++i)
1060 {
1061 GenObject* genObject = genObjects[i];
1062 genObject->Load(emitter, OperationFlags::none);
1063 if (i == 0)
1064 {
1065 emitter.Stack().Dup();
1066 void* thisPtr = emitter.Stack().Pop();
1067 if (classType != vmtPtrHolderClass)
1068 {
1069 thisPtr = emitter.CreateBitCast(thisPtr, vmtPtrHolderClass->AddPointer(GetSpan(), SourceModuleId())->IrType(emitter));
1070 }
1071 void* vmtPtr = emitter.GetVmtPtr(thisPtr, vmtPtrHolderClass->VmtPtrIndex(), classType->VmtPtrType(emitter));
1072 void* methodPtr = emitter.GetMethodPtr(vmtPtr, VmtIndex() + GetFunctionVmtIndexOffset());
1073 callee = emitter.CreateBitCast(methodPtr, emitter.GetIrTypeForPtrType(IrType(emitter)));
1074 }
1075 }
1076 std::vector<void*> args;
1077 int n = Parameters().size();
1078 if (ReturnsClassInterfaceOrClassDelegateByValue())
1079 {
1080 ++n;
1081 }
1082 args.resize(n);
1083 for (int i = 0; i < n; ++i)
1084 {
1085 void* arg = emitter.Stack().Pop();
1086 args[n - i - 1] = arg;
1087 }
1088 emitter.SetCurrentDebugLocation(span);
1089 void* handlerBlock = emitter.HandlerBlock();
1090 void* cleanupBlock = emitter.CleanupBlock();
1091 bool newCleanupNeeded = emitter.NewCleanupNeeded();
1092 std::vector<void*> bundles;
1093 Pad* currentPad = emitter.CurrentPad();
1094 if (currentPad != nullptr)
1095 {
1096 bundles.push_back(currentPad->value);
1097 }
1098 if (ReturnType() && !ReturnType()->IsVoidType() && !ReturnsClassInterfaceOrClassDelegateByValue())
1099 {
1100 if (DontThrow() || GetSymbolType() == SymbolType::destructorSymbol || (!handlerBlock && !cleanupBlock && !newCleanupNeeded))
1101 {
1102 if (currentPad == nullptr)
1103 {
1104 emitter.Stack().Push(emitter.CreateCall(callee, args));
1105 }
1106 else
1107 {
1108 emitter.Stack().Push(emitter.CreateCallInst(callee, args, bundles, span));
1109 }
1110 }
1111 else
1112 {
1113 void* nextBlock = nullptr;
1114 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1115 {
1116 nextBlock = emitter.CreateBasicBlock("next");
1117 }
1118 if (newCleanupNeeded)
1119 {
1120 emitter.CreateCleanup();
1121 cleanupBlock = emitter.CleanupBlock();
1122 }
1123 void* unwindBlock = cleanupBlock;
1124 if (unwindBlock == nullptr)
1125 {
1126 unwindBlock = handlerBlock;
1127 Assert(unwindBlock, "no unwind block");
1128 }
1129 if (currentPad == nullptr)
1130 {
1131 emitter.Stack().Push(emitter.CreateInvoke(callee, nextBlock, unwindBlock, args));
1132 }
1133 else
1134 {
1135 emitter.Stack().Push(emitter.CreateInvokeInst(callee, nextBlock, unwindBlock, args, bundles, span));
1136 }
1137 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1138 {
1139 emitter.SetCurrentBasicBlock(nextBlock);
1140 }
1141 }
1142 }
1143 else
1144 {
1145 if (DontThrow() || GetSymbolType() == SymbolType::destructorSymbol || (!handlerBlock && !cleanupBlock && !newCleanupNeeded))
1146 {
1147 if (currentPad == nullptr)
1148 {
1149 emitter.CreateCall(callee, args);
1150 }
1151 else
1152 {
1153 emitter.CreateCallInst(callee, args, bundles, span);
1154 }
1155 }
1156 else
1157 {
1158 void* nextBlock = nullptr;
1159 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1160 {
1161 nextBlock = emitter.CreateBasicBlock("next");
1162 }
1163 if (newCleanupNeeded)
1164 {
1165 emitter.CreateCleanup();
1166 cleanupBlock = emitter.CleanupBlock();
1167 }
1168 void* unwindBlock = cleanupBlock;
1169 if (unwindBlock == nullptr)
1170 {
1171 unwindBlock = handlerBlock;
1172 Assert(unwindBlock, "no unwind block");
1173 }
1174 if (currentPad == nullptr)
1175 {
1176 emitter.CreateInvoke(callee, nextBlock, unwindBlock, args);
1177 }
1178 else
1179 {
1180 emitter.CreateInvokeInst(callee, nextBlock, unwindBlock, args, bundles, span);
1181 }
1182 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1183 {
1184 emitter.SetCurrentBasicBlock(nextBlock);
1185 }
1186 }
1187 }
1188 }
1189
1190 std::std::unique_ptr<Value>FunctionSymbol::ConstructValue(conststd::std::vector<std::std::unique_ptr<Value>>&argumentValues, constSpan&span, constboost::uuids::uuid&moduleId, Value*receiver) const
1191 {
1192 return std::unique_ptr<Value>();
1193 }
1194
1195 std::std::unique_ptr<Value>FunctionSymbol::ConvertValue(conststd::std::unique_ptr<Value>&value) const
1196 {
1197 return std::unique_ptr<Value>();
1198 }
1199
1200 void FunctionSymbol::Dump(CodeFormatter& formatter)
1201 {
1202 formatter.WriteLine(ToUtf8(Name()));
1203 formatter.WriteLine("group name: " + ToUtf8(groupName));
1204 formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
1205 if (!MangledName().empty())
1206 {
1207 formatter.WriteLine("mangled name: " + ToUtf8(MangledName()));
1208 }
1209 if (constraint)
1210 {
1211 formatter.WriteLine("constraint: " + constraint->ToString());
1212 }
1213 if (IsConversion())
1214 {
1215 formatter.WriteLine("conversion:");
1216 formatter.IncIndent();
1217 std::string conversionTypeStr;
1218 if (GetConversionType() == ConversionType::implicit_)
1219 {
1220 conversionTypeStr = "implicit";
1221 }
1222 else if (GetConversionType() == ConversionType::explicit_)
1223 {
1224 conversionTypeStr = "explicit";
1225 }
1226 formatter.WriteLine("conversion type: " + conversionTypeStr);
1227 formatter.WriteLine("source type: " + ToUtf8(ConversionSourceType()->FullName()));
1228 formatter.WriteLine("target type: " + ToUtf8(ConversionTargetType()->FullName()));
1229 formatter.WriteLine("distance: " + std::to_string(ConversionDistance()));
1230 formatter.DecIndent();
1231 }
1232 }
1233
1234 bool FunctionSymbol::IsDefaultConstructor() const
1235 {
1236 return parameters.size() == 1 && groupName == U"@constructor" && parameters[0]->GetType()->PointerCount() == 1 && parameters[0]->GetType()->RemovePointer(GetSpan(), SourceModuleId())->IsClassTypeSymbol();
1237 }
1238
1239 bool FunctionSymbol::IsCopyConstructor() const
1240 {
1241 return parameters.size() == 2 && groupName == U"@constructor" &&
1242 parameters[0]->GetType()->PointerCount() == 1 &&
1243 parameters[0]->GetType()->RemovePointer(GetSpan(), SourceModuleId())->IsClassTypeSymbol() &&
1244 TypesEqual(parameters[0]->GetType()->BaseType()->AddConst(GetSpan(), SourceModuleId())->AddLvalueReference(GetSpan(), SourceModuleId()), parameters[1]->GetType());
1245 }
1246
1247 bool FunctionSymbol::IsMoveConstructor() const
1248 {
1249 return parameters.size() == 2 && groupName == U"@constructor" &&
1250 parameters[0]->GetType()->PointerCount() == 1 &&
1251 parameters[0]->GetType()->RemovePointer(GetSpan(), SourceModuleId())->IsClassTypeSymbol() &&
1252 TypesEqual(parameters[0]->GetType()->BaseType()->AddRvalueReference(GetSpan(), SourceModuleId()), parameters[1]->GetType());
1253 }
1254
1255 bool FunctionSymbol::IsCopyAssignment() const
1256 {
1257 return parameters.size() == 2 && groupName == U"operator=" &&
1258 parameters[0]->GetType()->PointerCount() == 1 &&
1259 parameters[0]->GetType()->RemovePointer(GetSpan(), SourceModuleId())->IsClassTypeSymbol() &&
1260 TypesEqual(parameters[0]->GetType()->BaseType()->AddConst(GetSpan(), SourceModuleId())->AddLvalueReference(GetSpan(), SourceModuleId()), parameters[1]->GetType());
1261 }
1262
1263 bool FunctionSymbol::IsMoveAssignment() const
1264 {
1265 return parameters.size() == 2 && groupName == U"operator=" &&
1266 parameters[0]->GetType()->PointerCount() == 1 &&
1267 parameters[0]->GetType()->RemovePointer(GetSpan(), SourceModuleId())->IsClassTypeSymbol() &&
1268 TypesEqual(parameters[0]->GetType()->BaseType()->AddRvalueReference(GetSpan(), SourceModuleId()), parameters[1]->GetType());
1269 }
1270
1271 void FunctionSymbol::AddLocalVariable(LocalVariableSymbol* localVariable)
1272 {
1273 localVariables.push_back(localVariable);
1274 }
1275
1276 bool FunctionSymbol::ReturnsClassInterfaceOrClassDelegateByValue() const
1277 {
1278 return returnType&&( returnType->IsClassTypeSymbol() || returnType->GetSymbolType() == SymbolType::classDelegateTypeSymbol || returnType->GetSymbolType() == SymbolType::interfaceTypeSymbol);
1279 }
1280
1281 void FunctionSymbol::SetReturnParam(ParameterSymbol* returnParam_)
1282 {
1283 returnParam.reset(returnParam_);
1284 }
1285
1286 void FunctionSymbol::SetGroupName(const std::u32string& groupName_)
1287 {
1288 groupName = groupName_;
1289 }
1290
1291 void FunctionSymbol::SetSpecifiers(Specifiers specifiers)
1292 {
1293 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
1294 SetAccess(accessSpecifiers);
1295 if ((specifiers & Specifiers::static_) != Specifiers::none)
1296 {
1297 throw Exception("only member functions can be static", GetSpan(), SourceModuleId());
1298 }
1299 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
1300 {
1301 throw Exception("only member functions can be virtual", GetSpan(), SourceModuleId());
1302 }
1303 if ((specifiers & Specifiers::override_) != Specifiers::none)
1304 {
1305 throw Exception("only member functions can be override", GetSpan(), SourceModuleId());
1306 }
1307 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
1308 {
1309 throw Exception("only member functions can be abstract", GetSpan(), SourceModuleId());
1310 }
1311 if ((specifiers & Specifiers::inline_) != Specifiers::none)
1312 {
1313 SetInline();
1314 }
1315 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
1316 {
1317 throw Exception("only constructors can be explicit", GetSpan(), SourceModuleId());
1318 }
1319 if ((specifiers & Specifiers::external_) != Specifiers::none)
1320 {
1321 SetExternal();
1322 }
1323 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
1324 {
1325 throw Exception("only special member functions can be suppressed", GetSpan(), SourceModuleId());
1326 }
1327 if ((specifiers & Specifiers::default_) != Specifiers::none)
1328 {
1329 throw Exception("only special member functions can be default", GetSpan(), SourceModuleId());
1330 }
1331 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
1332 {
1333 SetConstExpr();
1334 }
1335 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
1336 {
1337 SetCDecl();
1338 }
1339 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
1340 {
1341 SetNothrow();
1342 }
1343 if ((specifiers & Specifiers::throw_) != Specifiers::none)
1344 {
1345 if (IsNothrow())
1346 {
1347 throw Exception("function symbol cannot be throw and nothrow at the same time", GetSpan(), SourceModuleId());
1348 }
1349 }
1350 if ((specifiers & Specifiers::new_) != Specifiers::none)
1351 {
1352 throw Exception("only member functions can be new", GetSpan(), SourceModuleId());
1353 }
1354 if ((specifiers & Specifiers::const_) != Specifiers::none)
1355 {
1356 throw Exception("only member functions can be const", GetSpan(), SourceModuleId());
1357 }
1358 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
1359 {
1360 if (!GetGlobalFlag(GlobalFlags::unitTest))
1361 {
1362 throw Exception("function symbol cannot be unit_test", GetSpan(), SourceModuleId());
1363 }
1364 }
1365 if ((specifiers & Specifiers::winapi) != Specifiers::none)
1366 {
1367 SetFlag(FunctionSymbolFlags::winapi);
1368 }
1369 }
1370
1371 void FunctionSymbol::CloneUsingNodes(const std::std::vector<Node*>&usingNodes_)
1372 {
1373 CloneContext cloneContext;
1374 for (Node* usingNode : usingNodes_)
1375 {
1376 usingNodes.Add(usingNode->Clone(cloneContext));
1377 }
1378 }
1379
1380 LocalVariableSymbol* FunctionSymbol::CreateTemporary(TypeSymbol* type, const Span& span, const boost::uuids::uuid& moduleId)
1381 {
1382 LocalVariableSymbol* temporary = new LocalVariableSymbol(span, moduleId, U"@t" + ToUtf32(std::to_string(nextTemporaryIndex++)));
1383 temporary->SetType(type);
1384 AddMember(temporary);
1385 AddLocalVariable(temporary);
1386 return temporary;
1387 }
1388
1389 std::std::vector<LocalVariableSymbol*>FunctionSymbol::CreateTemporariesTo(FunctionSymbol*currentFunction)
1390 {
1391 return std::vector<LocalVariableSymbol*>();
1392 }
1393
1394 void* FunctionSymbol::IrType(Emitter& emitter)
1395 {
1396 void* localIrType = emitter.GetFunctionIrType(this);
1397 if (!localIrType)
1398 {
1399 void* retType = emitter.GetIrTypeForVoid();
1400 if (returnType && returnType->GetSymbolType() != SymbolType::voidTypeSymbol && !ReturnsClassInterfaceOrClassDelegateByValue())
1401 {
1402 retType = returnType->IrType(emitter);
1403 }
1404 bool interfaceMemFun = Parent()->GetSymbolType() == SymbolType::interfaceTypeSymbol;
1405 std::vector<void*> paramTypes;
1406 int np = parameters.size();
1407 for (int i = 0; i < np; ++i)
1408 {
1409 if (i == 0 && interfaceMemFun)
1410 {
1411 paramTypes.push_back(emitter.GetIrTypeForVoidPtrType());
1412 }
1413 else
1414 {
1415 ParameterSymbol* parameter = parameters[i];
1416 TypeSymbol* paramType = parameter->GetType();
1417 if (paramType->IsClassTypeSymbol() || paramType->GetSymbolType() == SymbolType::classDelegateTypeSymbol || paramType->GetSymbolType() == SymbolType::interfaceTypeSymbol)
1418 {
1419 paramType = paramType->AddConst(GetSpan(), SourceModuleId())->AddLvalueReference(GetSpan(), SourceModuleId());
1420 }
1421 paramTypes.push_back(paramType->IrType(emitter));
1422 }
1423 }
1424 if (returnParam)
1425 {
1426 paramTypes.push_back(returnParam->GetType()->IrType(emitter));
1427 }
1428 localIrType = emitter.GetIrTypeForFunction(retType, paramTypes);
1429 emitter.SetFunctionIrType(this, localIrType);
1430 }
1431 return localIrType;
1432 }
1433
1434 std::std::unique_ptr<sngxml::dom::Element>FunctionSymbol::CreateDomElement(TypeMap&typeMap)
1435 {
1436 if (IsTemplateSpecialization()) return std::unique_ptr<sngxml::dom::Element>();
1437 std::unique_ptr<sngxml::dom::Element> element(new sngxml::dom::Element(U"FunctionSymbol"));
1438 if (returnType)
1439 {
1440 std::unique_ptr<sngxml::dom::Element> returnTypeElement(new sngxml::dom::Element(U"returnType"));
1441 int typeId = typeMap.GetOrInsertType(returnType);
1442 returnTypeElement->SetAttribute(U"ref", U"type_" + ToUtf32(std::to_string(typeId)));
1443 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(returnTypeElement.release()));
1444 }
1445 return element;
1446 }
1447
1448 std::u32string FunctionSymbol::Id() const
1449 {
1450 if (IsFunctionTemplate())
1451 {
1452 return ContainerSymbol::Id();
1453 }
1454 else if (IsTemplateSpecialization())
1455 {
1456 if (Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1457 {
1458 Symbol* parent = const_cast<Symbol*>(Parent());
1459 ClassTemplateSpecializationSymbol* parentSpecialization = static_cast<ClassTemplateSpecializationSymbol*>(parent);
1460 if (parentSpecialization->IsPrototype())
1461 {
1462 return ContainerSymbol::Id();
1463 }
1464 else
1465 {
1466 ClassTypeSymbol* classTemplate = parentSpecialization->GetClassTemplate();
1467 ClassTemplateSpecializationSymbol* prototype = classTemplate->Prototype();
1468 if (prototype)
1469 {
1470 FunctionSymbol* functionSymbol = prototype->GetFunctionByIndex(index);
1471 if (functionSymbol)
1472 {
1473 return functionSymbol->Id();
1474 }
1475 else
1476 {
1477 throw Exception("function symbol " + std::to_string(index) + " not found", GetSpan(), SourceModuleId());
1478 }
1479 }
1480 else
1481 {
1482 throw Exception("prototype not found", GetSpan(), SourceModuleId());
1483 }
1484 }
1485 }
1486 else if (functionTemplate)
1487 {
1488 return functionTemplate->Id();
1489 }
1490 else
1491 {
1492 throw Exception("function template expected", GetSpan(), SourceModuleId());
1493 }
1494 }
1495 else
1496 {
1497 return ContainerSymbol::Id();
1498 }
1499 }
1500
1501 void FunctionSymbol::SetTemplateArgumentTypes(const std::std::vector<TypeSymbol*>&templateArgumentTypes_)
1502 {
1503 templateArgumentTypes = templateArgumentTypes_;
1504 }
1505
1506 void FunctionSymbol::Check()
1507 {
1508 ContainerSymbol::Check();
1509 if (functionId.is_nil())
1510 {
1511 throw SymbolCheckException("function symbol has no id", GetSpan(), SourceModuleId());
1512 }
1513 if (groupName.empty())
1514 {
1515 throw SymbolCheckException("function symbol has empty group name", GetSpan(), SourceModuleId());
1516 }
1517 }
1518
1519 void FunctionSymbol::SetPrevUnwindInfoVar(LocalVariableSymbol* prevUnwindInfoVar_)
1520 {
1521 prevUnwindInfoVar.reset(prevUnwindInfoVar_);
1522 }
1523
1524 void FunctionSymbol::SetUnwindInfoVar(LocalVariableSymbol* unwindInfoVar_)
1525 {
1526 unwindInfoVar.reset(unwindInfoVar_);
1527 }
1528
1529 int FunctionSymbol::NextTemporaryIndex()
1530 {
1531 return nextTemporaryIndex++;
1532 }
1533
1534 void FunctionSymbol::CopyFrom(const Symbol* that)
1535 {
1536 ContainerSymbol::CopyFrom(that);
1537 const FunctionSymbol* thatFunctionSymbol = static_cast<const FunctionSymbol*>(that);
1538 functionTemplate = thatFunctionSymbol->functionTemplate;
1539 master = thatFunctionSymbol->master;
1540 functionId = thatFunctionSymbol->functionId;
1541 groupName = thatFunctionSymbol->groupName;
1542 templateParameters = thatFunctionSymbol->templateParameters;
1543 templateArgumentTypes = thatFunctionSymbol->templateArgumentTypes;
1544 parameters = thatFunctionSymbol->parameters;
1545 if (thatFunctionSymbol->returnParam)
1546 {
1547 SetReturnParam(thatFunctionSymbol->returnParam->Clone());
1548 }
1549 localVariables = thatFunctionSymbol->localVariables;
1550 returnType = thatFunctionSymbol->returnType;
1551 flags = thatFunctionSymbol->flags;
1552 index = thatFunctionSymbol->index;
1553 vmtIndex = thatFunctionSymbol->vmtIndex;
1554 imtIndex = thatFunctionSymbol->imtIndex;
1555 functionGroup = thatFunctionSymbol->functionGroup;
1556 isProgramMain = thatFunctionSymbol->isProgramMain;
1557 conversionSourceType = thatFunctionSymbol->conversionSourceType;
1558 conversionTargetType = thatFunctionSymbol->conversionTargetType;
1559 }
1560
1561 FunctionSymbol* FunctionSymbol::Copy() const
1562 {
1563 FunctionSymbol* copy = new FunctionSymbol(GetSpan(), SourceModuleId(), Name());
1564 copy->CopyFrom(this);
1565 return copy;
1566 }
1567
1568 std::std::unique_ptr<Symbol>FunctionSymbol::RemoveFromParent()
1569 {
1570 std::unique_ptr<Symbol> symbol = ContainerSymbol::RemoveFromParent();
1571 if (functionGroup)
1572 {
1573 functionGroup->RemoveFunction(this);
1574 if (functionGroup->IsEmpty())
1575 {
1576 std::unique_ptr<Symbol> functionGroupSymbol = functionGroup->RemoveFromParent();
1577 }
1578 }
1579 return symbol;
1580 }
1581
1582 std::string FunctionSymbol::GetSymbolHelp() const
1583 {
1584 std::string help = "(";
1585 help.append(GetSymbolCategoryDescription()).append(") ");
1586 if (returnType)
1587 {
1588 help.append(ToUtf8(returnType->FullName())).append(" ");
1589 }
1590 help.append(ToUtf8(FullName(true)));
1591 return help;
1592 }
1593
1594 StaticConstructorSymbol::StaticConstructorSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
1595 FunctionSymbol(SymbolType::staticConstructorSymbol, span_, sourceModuleId_, name_)
1596 {
1597 SetGroupName(U"@static_constructor");
1598 }
1599
1600 FunctionSymbol* StaticConstructorSymbol::Copy() const
1601 {
1602 StaticConstructorSymbol* copy = new StaticConstructorSymbol(GetSpan(), SourceModuleId(), Name());
1603 copy->CopyFrom(this);
1604 return copy;
1605 }
1606
1607 std::u32string StaticConstructorSymbol::FullNameWithSpecifiers() const
1608 {
1609 std::u32string fullNameWithSpecifiers = ToUtf32(SymbolFlagStr(GetStableSymbolFlags(), true));
1610 std::u32string f = ToUtf32(FunctionSymbolFlagStr(GetFunctionSymbolFlags()));
1611 if (!f.empty())
1612 {
1613 if (!fullNameWithSpecifiers.empty())
1614 {
1615 fullNameWithSpecifiers.append(1, U' ');
1616 }
1617 fullNameWithSpecifiers.append(f);
1618 }
1619 if (!fullNameWithSpecifiers.empty())
1620 {
1621 fullNameWithSpecifiers.append(1, U' ');
1622 }
1623 fullNameWithSpecifiers.append(FullName());
1624 return fullNameWithSpecifiers;
1625 }
1626
1627 std::u32string StaticConstructorSymbol::CodeName() const
1628 {
1629 return Parent()->CodeName();
1630 }
1631
1632 void StaticConstructorSymbol::SetSpecifiers(Specifiers specifiers)
1633 {
1634 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
1635 SetAccess(accessSpecifiers);
1636 SetStatic();
1637 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
1638 {
1639 throw Exception("static constructor cannot be virtual", GetSpan(), SourceModuleId());
1640 }
1641 if ((specifiers & Specifiers::override_) != Specifiers::none)
1642 {
1643 throw Exception("static constructor cannot be override", GetSpan(), SourceModuleId());
1644 }
1645 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
1646 {
1647 throw Exception("static constructor cannot be abstract", GetSpan(), SourceModuleId());
1648 }
1649 if ((specifiers & Specifiers::inline_) != Specifiers::none)
1650 {
1651 throw Exception("static constructor cannot be inline", GetSpan(), SourceModuleId());
1652 }
1653 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
1654 {
1655 throw Exception("static constructor cannot be explicit", GetSpan(), SourceModuleId());
1656 }
1657 if ((specifiers & Specifiers::external_) != Specifiers::none)
1658 {
1659 throw Exception("static constructor cannot be external", GetSpan(), SourceModuleId());
1660 }
1661 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
1662 {
1663 throw Exception("static constructor cannot be suppressed", GetSpan(), SourceModuleId());
1664 }
1665 if ((specifiers & Specifiers::default_) != Specifiers::none)
1666 {
1667 throw Exception("static constructor cannot be default", GetSpan(), SourceModuleId());
1668 }
1669 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
1670 {
1671 throw Exception("static constructor cannot be constexpr", GetSpan(), SourceModuleId());
1672 }
1673 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
1674 {
1675 throw Exception("static constructor cannot be cdecl", GetSpan(), SourceModuleId());
1676 }
1677 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
1678 {
1679 SetNothrow();
1680 }
1681 if ((specifiers & Specifiers::throw_) != Specifiers::none)
1682 {
1683 if (IsNothrow())
1684 {
1685 throw Exception("static constructor cannot be throw and nothrow at the same time", GetSpan(), SourceModuleId());
1686 }
1687 }
1688 if ((specifiers & Specifiers::new_) != Specifiers::none)
1689 {
1690 throw Exception("static constructor cannot be new", GetSpan(), SourceModuleId());
1691 }
1692 if ((specifiers & Specifiers::const_) != Specifiers::none)
1693 {
1694 throw Exception("static constructor cannot be const", GetSpan(), SourceModuleId());
1695 }
1696 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
1697 {
1698 throw Exception("static constructor cannot be unit_test", GetSpan(), SourceModuleId());
1699 }
1700 }
1701
1702 ConstructorSymbol::ConstructorSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
1703 FunctionSymbol(SymbolType::constructorSymbol, span_, sourceModuleId_, name_)
1704 {
1705 SetGroupName(U"@constructor");
1706 }
1707
1708 FunctionSymbol* ConstructorSymbol::Copy() const
1709 {
1710 ConstructorSymbol* copy = new ConstructorSymbol(GetSpan(), SourceModuleId(), Name());
1711 copy->CopyFrom(this);
1712 return copy;
1713 }
1714
1715 std::string ConstructorSymbol::TypeString() const
1716 {
1717 if (IsDefaultConstructor())
1718 {
1719 return "default_constructor";
1720 }
1721 else if (IsCopyConstructor())
1722 {
1723 return "copy_constructor";
1724 }
1725 else if (IsMoveConstructor())
1726 {
1727 return "move_constructor";
1728 }
1729 else
1730 {
1731 return "constructor";
1732 }
1733 }
1734
1735 std::u32string ConstructorSymbol::DocName() const
1736 {
1737 std::u32string docName;
1738 docName.append(Parent()->DocName());
1739 docName.append(1, '(');
1740 int n = Parameters().size();
1741 for (int i = 1; i < n; ++i)
1742 {
1743 if (i > 1)
1744 {
1745 docName.append(U", ");
1746 }
1747 ParameterSymbol* parameter = Parameters()[i];
1748 if (parameter->GetType()->Ns() == Ns())
1749 {
1750 docName.append(parameter->GetType()->Name());
1751 }
1752 else
1753 {
1754 docName.append(parameter->GetType()->FullName());
1755 }
1756 docName.append(1, ' ').append(parameter->Name());
1757 }
1758 docName.append(1, ')');
1759 return docName;
1760 }
1761
1762 std::u32string ConstructorSymbol::CodeName() const
1763 {
1764 return Parent()->CodeName();
1765 }
1766
1767 uint8_t ConstructorSymbol::ConversionDistance() const
1768 {
1769 return 5;
1770 }
1771
1772 void ConstructorSymbol::SetSpecifiers(Specifiers specifiers)
1773 {
1774 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
1775 SetAccess(accessSpecifiers);
1776 if ((specifiers & Specifiers::static_) != Specifiers::none)
1777 {
1778 throw Exception("ordinary constructor cannot be static", GetSpan(), SourceModuleId());
1779 }
1780 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
1781 {
1782 throw Exception("constructor cannot be virtual", GetSpan(), SourceModuleId());
1783 }
1784 if ((specifiers & Specifiers::override_) != Specifiers::none)
1785 {
1786 throw Exception("constructor cannot be override", GetSpan(), SourceModuleId());
1787 }
1788 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
1789 {
1790 throw Exception("constructor cannot be abstract", GetSpan(), SourceModuleId());
1791 }
1792 if ((specifiers & Specifiers::inline_) != Specifiers::none)
1793 {
1794 SetInline();
1795 }
1796 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
1797 {
1798 SetExplicit();
1799 }
1800 if ((specifiers & Specifiers::external_) != Specifiers::none)
1801 {
1802 throw Exception("constructor cannot be external", GetSpan(), SourceModuleId());
1803 }
1804 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
1805 {
1806 if (IsInline())
1807 {
1808 throw Exception("suppressed member function cannot be inline", GetSpan(), SourceModuleId());
1809 }
1810 SetSuppressed();
1811 }
1812 if ((specifiers & Specifiers::default_) != Specifiers::none)
1813 {
1814 if (IsSuppressed())
1815 {
1816 throw Exception("constructor cannot be default and suppressed at the same time", GetSpan(), SourceModuleId());
1817 }
1818 if (IsInline())
1819 {
1820 throw Exception("default member function cannot be inline", GetSpan(), SourceModuleId());
1821 }
1822 SetDefault();
1823 }
1824 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
1825 {
1826 SetConstExpr();
1827 }
1828 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
1829 {
1830 throw Exception("constructor cannot be cdecl", GetSpan(), SourceModuleId());
1831 }
1832 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
1833 {
1834 SetNothrow();
1835 }
1836 if ((specifiers & Specifiers::throw_) != Specifiers::none)
1837 {
1838 if (IsNothrow())
1839 {
1840 throw Exception("constructor cannot be throw and nothrow at the same time", GetSpan(), SourceModuleId());
1841 }
1842 }
1843 if ((specifiers & Specifiers::new_) != Specifiers::none)
1844 {
1845 throw Exception("constructor cannot be new", GetSpan(), SourceModuleId());
1846 }
1847 if ((specifiers & Specifiers::const_) != Specifiers::none)
1848 {
1849 throw Exception("constructor cannot be const", GetSpan(), SourceModuleId());
1850 }
1851 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
1852 {
1853 throw Exception("constructor cannot be unit_test", GetSpan(), SourceModuleId());
1854 }
1855 }
1856
1857 DestructorSymbol::DestructorSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
1858 FunctionSymbol(SymbolType::destructorSymbol, span_, sourceModuleId_, name_), generated(false)
1859 {
1860 SetGroupName(U"@destructor");
1861 }
1862
1863 FunctionSymbol* DestructorSymbol::Copy() const
1864 {
1865 DestructorSymbol* copy = new DestructorSymbol(GetSpan(), SourceModuleId(), Name());
1866 copy->CopyFrom(this);
1867 copy->generated = generated;
1868 return copy;
1869 }
1870
1871 bool DestructorSymbol::IsExportSymbol() const
1872 {
1873 if (Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1874 {
1875 const ClassTemplateSpecializationSymbol* classTemplateSpecialization = static_cast<const ClassTemplateSpecializationSymbol*>(Parent());
1876 if (classTemplateSpecialization->IsPrototype())
1877 {
1878 return false;
1879 }
1880 }
1881 return true;
1882 }
1883
1884 void DestructorSymbol::Write(SymbolWriter& writer)
1885 {
1886 FunctionSymbol::Write(writer);
1887 writer.GetBinaryWriter().Write(generated);
1888 }
1889
1890 void DestructorSymbol::Read(SymbolReader& reader)
1891 {
1892 FunctionSymbol::Read(reader);
1893 generated = reader.GetBinaryReader().ReadBool();
1894 }
1895
1896 void DestructorSymbol::SetSpecifiers(Specifiers specifiers)
1897 {
1898 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
1899 if (accessSpecifiers != Specifiers::public_)
1900 {
1901 throw Exception("destructor must be public", GetSpan(), SourceModuleId());
1902 }
1903 SetAccess(accessSpecifiers);
1904 if ((specifiers & Specifiers::static_) != Specifiers::none)
1905 {
1906 throw Exception("destructor cannot be static", GetSpan(), SourceModuleId());
1907 }
1908 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
1909 {
1910 SetVirtual();
1911 }
1912 if ((specifiers & Specifiers::override_) != Specifiers::none)
1913 {
1914 if (IsVirtual())
1915 {
1916 throw Exception("destructor cannot be virtual and override at the same time", GetSpan(), SourceModuleId());
1917 }
1918 SetOverride();
1919 }
1920 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
1921 {
1922 throw Exception("destructor cannot be abstract", GetSpan(), SourceModuleId());
1923 }
1924 if ((specifiers & Specifiers::inline_) != Specifiers::none)
1925 {
1926 throw Exception("destructor cannot be inline", GetSpan(), SourceModuleId());
1927 }
1928 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
1929 {
1930 throw Exception("destructor cannot be explicit", GetSpan(), SourceModuleId());
1931 }
1932 if ((specifiers & Specifiers::external_) != Specifiers::none)
1933 {
1934 throw Exception("destructor cannot be external", GetSpan(), SourceModuleId());
1935 }
1936 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
1937 {
1938 throw Exception("destructor cannot be suppressed", GetSpan(), SourceModuleId());
1939 }
1940 if ((specifiers & Specifiers::default_) != Specifiers::none)
1941 {
1942 SetDefault();
1943 }
1944 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
1945 {
1946 throw Exception("destructor cannot be constexpr", GetSpan(), SourceModuleId());
1947 }
1948 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
1949 {
1950 throw Exception("destructor cannot be cdecl", GetSpan(), SourceModuleId());
1951 }
1952 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
1953 {
1954 throw Exception("destructor is implicitly nothrow", GetSpan(), SourceModuleId());
1955 }
1956 if ((specifiers & Specifiers::throw_) != Specifiers::none)
1957 {
1958 throw Exception("destructor cannot be throw", GetSpan(), SourceModuleId());
1959 }
1960 if ((specifiers & Specifiers::new_) != Specifiers::none)
1961 {
1962 throw Exception("destructor cannot be new", GetSpan(), SourceModuleId());
1963 }
1964 if ((specifiers & Specifiers::const_) != Specifiers::none)
1965 {
1966 throw Exception("destructor cannot be const", GetSpan(), SourceModuleId());
1967 }
1968 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
1969 {
1970 throw Exception("destructor cannot be unit_test", GetSpan(), SourceModuleId());
1971 }
1972 }
1973
1974 std::u32string DestructorSymbol::CodeName() const
1975 {
1976 return U"~" + Parent()->CodeName();
1977 }
1978
1979 bool DestructorSymbol::DontThrow() const
1980 {
1981 if (GetBackEnd() == BackEnd::cmcpp)
1982 {
1983 return !HasCleanup();
1984 }
1985 return true;
1986 }
1987
1988 MemberFunctionSymbol::MemberFunctionSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
1989 FunctionSymbol(SymbolType::memberFunctionSymbol, span_, sourceModuleId_, name_)
1990 {
1991 }
1992
1993 FunctionSymbol* MemberFunctionSymbol::Copy() const
1994 {
1995 MemberFunctionSymbol* copy = new MemberFunctionSymbol(GetSpan(), SourceModuleId(), Name());
1996 copy->CopyFrom(this);
1997 return copy;
1998 }
1999
2000 std::string MemberFunctionSymbol::TypeString() const
2001 {
2002 if (IsCopyAssignment())
2003 {
2004 return "copy_assignment";
2005 }
2006 else if (IsMoveAssignment())
2007 {
2008 return "move_assignment";
2009 }
2010 else
2011 {
2012 return "member_function";
2013 }
2014 }
2015
2016 std::u32string MemberFunctionSymbol::DocName() const
2017 {
2018 std::u32string docName;
2019 docName.append(GroupName());
2020 docName.append(1, '(');
2021 int n = Parameters().size();
2022 int start = 1;
2023 if (IsStatic())
2024 {
2025 start = 0;
2026 }
2027 for (int i = start; i < n; ++i)
2028 {
2029 if (i > start)
2030 {
2031 docName.append(U", ");
2032 }
2033 ParameterSymbol* parameter = Parameters()[i];
2034 if (parameter->GetType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2035 {
2036 ClassTemplateSpecializationSymbol* classTemplateSpecializationSymbol = static_cast<ClassTemplateSpecializationSymbol*>(parameter->GetType());
2037 if (classTemplateSpecializationSymbol->GetClassTemplate()->Ns() == Ns())
2038 {
2039 docName.append(classTemplateSpecializationSymbol->Name());
2040 }
2041 else
2042 {
2043 docName.append(classTemplateSpecializationSymbol->FullName());
2044 }
2045 }
2046 else
2047 {
2048 if (parameter->GetType()->Ns() == Ns())
2049 {
2050 docName.append(parameter->GetType()->Name());
2051 }
2052 else
2053 {
2054 docName.append(parameter->GetType()->FullName());
2055 }
2056 }
2057 docName.append(1, ' ').append(parameter->Name());
2058 }
2059 docName.append(1, ')');
2060 if (IsConst())
2061 {
2062 docName.append(U" const");
2063 }
2064 return docName;
2065 }
2066
2067 void MemberFunctionSymbol::SetSpecifiers(Specifiers specifiers)
2068 {
2069 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
2070 SetAccess(accessSpecifiers);
2071 if ((specifiers & Specifiers::static_) != Specifiers::none)
2072 {
2073 SetStatic();
2074 }
2075 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
2076 {
2077 SetVirtual();
2078 }
2079 if ((specifiers & Specifiers::override_) != Specifiers::none)
2080 {
2081 if (IsVirtual())
2082 {
2083 throw Exception("member function cannot be virtual and override at the same time", GetSpan(), SourceModuleId());
2084 }
2085 SetOverride();
2086 }
2087 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
2088 {
2089 if (IsVirtual() || IsOverride())
2090 {
2091 throw Exception("member function cannot be abstract and virtual or override at the same time", GetSpan(), SourceModuleId());
2092 }
2093 SetAbstract();
2094 }
2095 if ((specifiers & Specifiers::inline_) != Specifiers::none)
2096 {
2097 SetInline();
2098 }
2099 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
2100 {
2101 throw Exception("member function cannot be explicit", GetSpan(), SourceModuleId());
2102 }
2103 if ((specifiers & Specifiers::external_) != Specifiers::none)
2104 {
2105 throw Exception("member function cannot be external", GetSpan(), SourceModuleId());
2106 }
2107 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
2108 {
2109 if (IsInline())
2110 {
2111 throw Exception("suppressed member function cannot be inline", GetSpan(), SourceModuleId());
2112 }
2113 if (GroupName() == U"operator=")
2114 {
2115 SetSuppressed();
2116 }
2117 else
2118 {
2119 throw Exception("only special member functions can be suppressed", GetSpan(), SourceModuleId());
2120 }
2121 }
2122 if ((specifiers & Specifiers::default_) != Specifiers::none)
2123 {
2124 if (IsSuppressed())
2125 {
2126 throw Exception("member function cannot be default and suppressed at the same time", GetSpan(), SourceModuleId());
2127 }
2128 if (IsInline())
2129 {
2130 throw Exception("default member function cannot be inline", GetSpan(), SourceModuleId());
2131 }
2132 if (GroupName() == U"operator=")
2133 {
2134 SetDefault();
2135 }
2136 else
2137 {
2138 throw Exception("only special member functions can be default", GetSpan(), SourceModuleId());
2139 }
2140 }
2141 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
2142 {
2143 SetConstExpr();
2144 }
2145 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
2146 {
2147 throw Exception("member function cannot be cdecl", GetSpan(), SourceModuleId());
2148 }
2149 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
2150 {
2151 SetNothrow();
2152 }
2153 if ((specifiers & Specifiers::throw_) != Specifiers::none)
2154 {
2155 if (IsNothrow())
2156 {
2157 throw Exception("member function cannot be throw and nothrow at the same time", GetSpan(), SourceModuleId());
2158 }
2159 }
2160 if ((specifiers & Specifiers::new_) != Specifiers::none)
2161 {
2162 if (IsVirtualAbstractOrOverride())
2163 {
2164 throw Exception("member function cannot be new and virtual, abstract or overridden at the same time", GetSpan(), SourceModuleId());
2165 }
2166 SetNew();
2167 }
2168 if ((specifiers & Specifiers::const_) != Specifiers::none)
2169 {
2170 SetConst();
2171 }
2172 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
2173 {
2174 throw Exception("member function cannot be unit_test", GetSpan(), SourceModuleId());
2175 }
2176 }
2177
2178 int MemberFunctionSymbol::StartParamIndex() const
2179 {
2180 if (IsStatic())
2181 {
2182 return 0;
2183 }
2184 else
2185 {
2186 return 1;
2187 }
2188 }
2189
2190 ConversionFunctionSymbol::ConversionFunctionSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
2191 FunctionSymbol(SymbolType::conversionFunctionSymbol, span_, sourceModuleId_, name_)
2192 {
2193 SetConversion();
2194 }
2195
2196 FunctionSymbol* ConversionFunctionSymbol::Copy() const
2197 {
2198 ConversionFunctionSymbol* copy = new ConversionFunctionSymbol(GetSpan(), SourceModuleId(), Name());
2199 copy->CopyFrom(this);
2200 return copy;
2201 }
2202
2203 std::u32string ConversionFunctionSymbol::DocName() const
2204 {
2205 std::u32string docName;
2206 docName.append(U"operator ");
2207 TypeSymbol* type = ReturnType();
2208 if (type->Ns() == Ns())
2209 {
2210 docName.append(type->Name());
2211 }
2212 else
2213 {
2214 docName.append(type->FullName());
2215 }
2216 docName.append(U"()");
2217 if (IsConst())
2218 {
2219 docName.append(U" const");
2220 }
2221 return docName;
2222 }
2223
2224 void ConversionFunctionSymbol::SetSpecifiers(Specifiers specifiers)
2225 {
2226 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
2227 SetAccess(accessSpecifiers);
2228 if ((specifiers & Specifiers::static_) != Specifiers::none)
2229 {
2230 throw Exception("conversion function cannot be static", GetSpan(), SourceModuleId());
2231 }
2232 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
2233 {
2234 throw Exception("conversion function cannot be virtual", GetSpan(), SourceModuleId());
2235 }
2236 if ((specifiers & Specifiers::override_) != Specifiers::none)
2237 {
2238 throw Exception("conversion function cannot be override", GetSpan(), SourceModuleId());
2239 }
2240 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
2241 {
2242 throw Exception("conversion function cannot be abstract", GetSpan(), SourceModuleId());
2243 }
2244 if ((specifiers & Specifiers::inline_) != Specifiers::none)
2245 {
2246 SetInline();
2247 }
2248 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
2249 {
2250 throw Exception("conversion function cannot be explicit", GetSpan(), SourceModuleId());
2251 }
2252 if ((specifiers & Specifiers::external_) != Specifiers::none)
2253 {
2254 throw Exception("conversion function cannot be external", GetSpan(), SourceModuleId());
2255 }
2256 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
2257 {
2258 throw Exception("conversion function cannot be suppressed", GetSpan(), SourceModuleId());
2259 }
2260 if ((specifiers & Specifiers::default_) != Specifiers::none)
2261 {
2262 throw Exception("conversion function cannot be default", GetSpan(), SourceModuleId());
2263 }
2264 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
2265 {
2266 SetConstExpr();
2267 }
2268 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
2269 {
2270 throw Exception("conversion function cannot be cdecl", GetSpan(), SourceModuleId());
2271 }
2272 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
2273 {
2274 SetNothrow();
2275 }
2276 if ((specifiers & Specifiers::throw_) != Specifiers::none)
2277 {
2278 if (IsNothrow())
2279 {
2280 throw Exception("conversion function cannot be throw and nothrow at the same time", GetSpan(), SourceModuleId());
2281 }
2282 }
2283 if ((specifiers & Specifiers::new_) != Specifiers::none)
2284 {
2285 throw Exception("conversion function cannot be new", GetSpan(), SourceModuleId());
2286 }
2287 if ((specifiers & Specifiers::const_) != Specifiers::none)
2288 {
2289 SetConst();
2290 }
2291 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
2292 {
2293 throw Exception("conversion function cannot be unit_test", GetSpan(), SourceModuleId());
2294 }
2295 }
2296
2297 std::std::unique_ptr<sngxml::dom::Element>ConversionFunctionSymbol::CreateDomElement(TypeMap&typeMap)
2298 {
2299 std::unique_ptr<sngxml::dom::Element> element(new sngxml::dom::Element(U"ConversionFunctionSymbol"));
2300 if (ReturnType())
2301 {
2302 std::unique_ptr<sngxml::dom::Element> returnTypeElement(new sngxml::dom::Element(U"returnType"));
2303 int typeId = typeMap.GetOrInsertType(ReturnType());
2304 returnTypeElement->SetAttribute(U"ref", U"type_" + ToUtf32(std::to_string(typeId)));
2305 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(returnTypeElement.release()));
2306 }
2307 return element;
2308 }
2309
2310 FunctionGroupTypeSymbol::FunctionGroupTypeSymbol(FunctionGroupSymbol* functionGroup_, void* boundFunctionGroup_) :
2311 TypeSymbol(SymbolType::functionGroupTypeSymbol, functionGroup_->GetSpan(), functionGroup_->SourceModuleId(), functionGroup_->Name()), functionGroup(functionGroup_), boundFunctionGroup(boundFunctionGroup_)
2312 {
2313 SetModule(functionGroup->GetModule());
2314 }
2315
2316 MemberExpressionTypeSymbol::MemberExpressionTypeSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_, void* boundMemberExpression_) :
2317 TypeSymbol(SymbolType::memberExpressionTypeSymbol, span_, sourceModuleId_, name_), boundMemberExpression(boundMemberExpression_)
2318 {
2319 }
2320
2321 void InitFunctionSymbol()
2322 {
2323 OperatorMangleMap::Init();
2324 }
2325
2326 void DoneFunctionSymbol()
2327 {
2328 OperatorMangleMap::Done();
2329 }
2330
2331 } }