1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   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* leftFunctionSymbol* 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(leftSpecializationrightSpecialization))
  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::u32stringstd::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::functionGroupSymbolspan_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(1U'_').append(OperatorMangleMap::Instance().Mangle(Name()));
 199     }
 200     else if (Name().find(U'@') == std::u32string::npos)
 201     {
 202         mangledName.append(1U'_').append(Name());
 203     }
 204     mangledName.append(1U'_').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(endvarArgFunctions.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(endfunctionList.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 arityViableFunctionSet& viableFunctionsModule* 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* elementTypeMap& 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(fromFunctionfunctionSymbol)) 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::functionSymbolspan_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(readerthisfunctionTemplateId0);
 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(readerthisreturnTypeId0);
 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(readerthistemplateArgumentId-1 - i);
 603     }
 604     if (IsConversion())
 605     {
 606         boost::uuids::uuid conversionSourceTypeId;
 607         reader.GetBinaryReader().ReadUuid(conversionSourceTypeId);
 608         reader.GetSymbolTable()->EmplaceTypeRequest(readerthisconversionSourceTypeId10000);
 609         boost::uuids::uuid conversionTargetTypeId;
 610         reader.GetBinaryReader().ReadUuid(conversionTargetTypeId);
 611         reader.GetSymbolTable()->EmplaceTypeRequest(readerthisconversionTargetTypeId10001);
 612         reader.AddConversion(this);
 613     }
 614 }
 615 
 616 void FunctionSymbol::EmplaceFunction(FunctionSymbol* functionSymbolint 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* typeSymbolint 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(1U'(');
 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(1U' ');
 709         name.append(std::u32string(parameter->Name()));
 710     }
 711     name.append(1U')');
 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(1U'_').append(OperatorMangleMap::Instance().Mangle(GroupName()));
 730     }
 731     else if (groupName.find(U'@') == std::u32string::npos)
 732     {
 733         mangledName.append(1U'_').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(1U'_').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(1U'_').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(1U'.');
 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(1U'(');
 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(1U')');
 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(1U' ');
 821         }
 822         fullNameWithSpecifiers.append(f);
 823     }
 824     if (!fullNameWithSpecifiers.empty())
 825     {
 826         fullNameWithSpecifiers.append(1U' ');
 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& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 919 {
 920     if ((flags & OperationFlags::virtualCall) != OperationFlags::none)
 921     {
 922         GenerateVirtualCall(emittergenObjectsflagsspanmoduleId);
 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(emitterflags & OperationFlags::functionCallFlags);
 930     }
 931     emitter.SetCurrentDebugLocation(span);
 932     void* functionType = IrType(emitter);
 933     void* callee = emitter.GetOrInsertFunction(ToUtf8(MangledName())functionTypeDontThrow());
 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(calleeargs));
 962             }
 963             else
 964             {
 965                 emitter.Stack().Push(emitter.CreateCallInst(calleeargsbundlesspan));
 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(calleenextBlockunwindBlockargs));
 989             }
 990             else
 991             {
 992                 emitter.Stack().Push(emitter.CreateInvokeInst(calleenextBlockunwindBlockargsbundlesspan));
 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(calleeargs);
1007             }
1008             else
1009             {
1010                 emitter.CreateCallInst(calleeargsbundlesspan);
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(calleenextBlockunwindBlockargs);
1034             }
1035             else
1036             {
1037                 emitter.CreateInvokeInst(calleenextBlockunwindBlockargsbundlesspan);
1038             }
1039             if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1040             {
1041                 emitter.SetCurrentBasicBlock(nextBlock);
1042             }
1043         }
1044     }
1045 }
1046 
1047 void FunctionSymbol::GenerateVirtualCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::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(emitterOperationFlags::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(thisPtrvmtPtrHolderClass->AddPointer(GetSpan()SourceModuleId())->IrType(emitter));
1070             }
1071             void* vmtPtr = emitter.GetVmtPtr(thisPtrvmtPtrHolderClass->VmtPtrIndex()classType->VmtPtrType(emitter));
1072             void* methodPtr = emitter.GetMethodPtr(vmtPtrVmtIndex() + GetFunctionVmtIndexOffset());
1073             callee = emitter.CreateBitCast(methodPtremitter.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(calleeargs));
1105             }
1106             else
1107             {
1108                 emitter.Stack().Push(emitter.CreateCallInst(calleeargsbundlesspan));
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(calleenextBlockunwindBlockargs));
1132             }
1133             else
1134             {
1135                 emitter.Stack().Push(emitter.CreateInvokeInst(calleenextBlockunwindBlockargsbundlesspan));
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(calleeargs);
1150             }
1151             else
1152             {
1153                 emitter.CreateCallInst(calleeargsbundlesspan);
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(calleenextBlockunwindBlockargs);
1177             }
1178             else
1179             {
1180                 emitter.CreateInvokeInst(calleenextBlockunwindBlockargsbundlesspan);
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>>&argumentValuesconstSpan&spanconstboost::uuids::uuid&moduleIdValue*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* typeconst Span& spanconst boost::uuids::uuid& moduleId)
1381 {
1382     LocalVariableSymbol* temporary = new LocalVariableSymbol(spanmoduleIdU"@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(retTypeparamTypes);
1429         emitter.SetFunctionIrType(thislocalIrType);
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::staticConstructorSymbolspan_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(1U' ');
1616         }
1617         fullNameWithSpecifiers.append(f);
1618     }
1619     if (!fullNameWithSpecifiers.empty())
1620     {
1621         fullNameWithSpecifiers.append(1U' ');
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::constructorSymbolspan_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::destructorSymbolspan_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::memberFunctionSymbolspan_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::conversionFunctionSymbolspan_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::functionGroupTypeSymbolfunctionGroup_->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::memberExpressionTypeSymbolspan_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 } } // namespace cmajor::symbols