1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 #include <cmajor/binder/OperationRepository.hpp>
   7 #include <cmajor/binder/BoundCompileUnit.hpp>
   8 #include <cmajor/binder/BoundClass.hpp>
   9 #include <cmajor/binder/BoundFunction.hpp>
  10 #include <cmajor/binder/BoundStatement.hpp>
  11 #include <cmajor/binder/ExpressionBinder.hpp>
  12 #include <cmajor/binder/TypeBinder.hpp>
  13 #include <cmajor/binder/OverloadResolution.hpp>
  14 #include <cmajor/binder/TypeResolver.hpp>
  15 #include <cmajor/symbols/BasicTypeOperation.hpp>
  16 #include <cmajor/symbols/Exception.hpp>
  17 #include <cmajor/symbols/ClassTypeSymbol.hpp>
  18 #include <cmajor/symbols/InterfaceTypeSymbol.hpp>
  19 #include <cmajor/symbols/GlobalFlags.hpp>
  20 #include <cmajor/symbols/SymbolCreatorVisitor.hpp>
  21 #include <sngcm/ast/Identifier.hpp>
  22 #include <sngcm/ast/Expression.hpp>
  23 #include <soulng/util/Unicode.hpp>
  24 
  25 namespace cmajor { namespace binder {
  26 
  27 using namespace soulng::unicode;
  28 
  29 class PointerDefaultCtor public FunctionSymbol
  30 {
  31 public:
  32     PointerDefaultCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
  33     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
  34     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
  35     bool IsBasicTypeOperation() const override { return true; }
  36     const char* ClassName() const override { return "PointerDefaultCtor"; }
  37 private:
  38     TypeSymbol* type;
  39     void* nullValue;
  40 };
  41 
  42 PointerDefaultCtor::PointerDefaultCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@constructor")type(type_)nullValue(nullptr)
  43 {
  44     SetGroupName(U"@constructor");
  45     SetAccess(SymbolAccess::public_);
  46     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
  47     thisParam->SetType(type->AddPointer(spanmoduleId));
  48     AddMember(thisParam);
  49     ComputeName();
  50 }
  51 
  52 void PointerDefaultCtor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
  53 {
  54     Assert(genObjects.size() == 1"default constructor needs one object");
  55     if (!nullValue)
  56     {
  57         nullValue = emitter.CreateDefaultIrValueForPtrType(type->IrType(emitter));
  58     }
  59     emitter.Stack().Push(nullValue);
  60     genObjects[0]->Store(emitterOperationFlags::none);
  61 }
  62 
  63 class PointerDefaultConstructorOperation public Operation
  64 {
  65 public:
  66     PointerDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_);
  67     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
  68         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
  69 private:
  70     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
  71     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
  72 };
  73 
  74 PointerDefaultConstructorOperation::PointerDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"1boundCompileUnit_)
  75 {
  76 }
  77 
  78 void PointerDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
  79     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
  80 {
  81     TypeSymbol* type = arguments[0]->GetType();
  82     if (type->PointerCount() <= 1) return;
  83     if (type->IsReferenceType()) return;
  84     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
  85     {
  86         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
  87         GetBoundCompileUnit().FinalizeBinding(specialization);
  88     }
  89     TypeSymbol* pointerType = type->RemovePointer(spanmoduleId);
  90     FunctionSymbol* function = functionMap[pointerType];
  91     if (!function)
  92     {
  93         function = new PointerDefaultCtor(pointerTypespanmoduleId);
  94         function->SetModule(&GetBoundCompileUnit().GetModule());
  95         function->SetParent(&GetSymbolTable()->GlobalNs());
  96         functionMap[pointerType] = function;
  97         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
  98     }
  99     viableFunctions.Insert(function);
 100 }
 101 
 102 class PointerCopyCtor public FunctionSymbol
 103 {
 104 public:
 105     PointerCopyCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
 106     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 107     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 108     bool IsBasicTypeOperation() const override { return true; }
 109     const char* ClassName() const override { return "PointerCopyCtor"; }
 110 private:
 111     TypeSymbol* type;
 112 };
 113 
 114 PointerCopyCtor::PointerCopyCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@constructor")type(type_)
 115 {
 116     SetGroupName(U"@constructor");
 117     SetAccess(SymbolAccess::public_);
 118     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
 119     thisParam->SetType(type->AddPointer(spanmoduleId));
 120     AddMember(thisParam);
 121     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
 122     thatParam->SetType(type);
 123     AddMember(thatParam);
 124     ComputeName();
 125 }
 126 
 127 void PointerCopyCtor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 128 {
 129     Assert(genObjects.size() == 2"copy constructor needs two objects");
 130     genObjects[1]->Load(emitterOperationFlags::none);
 131     if ((flags & OperationFlags::leaveFirstArg) != OperationFlags::none)
 132     {
 133         emitter.Stack().Dup();
 134         void* ptr = emitter.Stack().Pop();
 135         emitter.SaveObjectPointer(ptr);
 136     }
 137     genObjects[0]->Store(emitterOperationFlags::none);
 138 }
 139 
 140 class PointerCopyConstructorOperation public Operation
 141 {
 142 public:
 143     PointerCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
 144     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 145         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 146 private:
 147     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 148     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 149 };
 150 
 151 PointerCopyConstructorOperation::PointerCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
 152 {
 153 }
 154 
 155 void PointerCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 156     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 157 {
 158     TypeSymbol* type = arguments[0]->GetType();
 159     if (type->PointerCount() <= 1) return;
 160     if (type->IsReferenceType()) return;
 161     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 162     {
 163         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
 164         GetBoundCompileUnit().FinalizeBinding(specialization);
 165     }
 166     TypeSymbol* pointerType = type->RemovePointer(spanmoduleId);
 167     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
 168         !TypesEqual(arguments[1]->GetType()pointerType->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
 169     {
 170         FunctionSymbol* function = functionMap[pointerType];
 171         if (!function)
 172         {
 173             function = new PointerCopyCtor(pointerTypespanmoduleId);
 174             function->SetModule(&GetBoundCompileUnit().GetModule());
 175             function->SetParent(&GetSymbolTable()->GlobalNs());
 176             functionMap[pointerType] = function;
 177             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 178         }
 179         viableFunctions.Insert(function);
 180     }
 181 }
 182 
 183 class PointerMoveCtor public FunctionSymbol
 184 {
 185 public:
 186     PointerMoveCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
 187     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 188     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 189     bool IsBasicTypeOperation() const override { return true; }
 190     const char* ClassName() const override { return "PointerMoveCtor"; }
 191 private:
 192     TypeSymbol* type;
 193 };
 194 
 195 PointerMoveCtor::PointerMoveCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@constructor")type(type_)
 196 {
 197     SetGroupName(U"@constructor");
 198     SetAccess(SymbolAccess::public_);
 199     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
 200     thisParam->SetType(type->AddPointer(spanmoduleId));
 201     AddMember(thisParam);
 202     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
 203     thatParam->SetType(type->AddRvalueReference(spanmoduleId));
 204     AddMember(thatParam);
 205     ComputeName();
 206 }
 207 
 208 void PointerMoveCtor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 209 {
 210     Assert(genObjects.size() == 2"move constructor needs two objects");
 211     genObjects[1]->Load(emitterOperationFlags::none);
 212     void* rvalueRefValue = emitter.Stack().Pop();
 213     emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
 214     if ((flags & OperationFlags::leaveFirstArg) != OperationFlags::none)
 215     {
 216         emitter.Stack().Dup();
 217         void* ptr = emitter.Stack().Pop();
 218         emitter.SaveObjectPointer(ptr);
 219     }
 220     genObjects[0]->Store(emitterOperationFlags::none);
 221 }
 222 
 223 class PointerMoveConstructorOperation public Operation
 224 {
 225 public:
 226     PointerMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_);
 227     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 228         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 229 private:
 230     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 231     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 232 };
 233 
 234 PointerMoveConstructorOperation::PointerMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
 235 {
 236 }
 237 
 238 void PointerMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 239     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 240 {
 241     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
 242     TypeSymbol* type = arguments[0]->GetType();
 243     if (type->PointerCount() <= 1) return;
 244     if (type->IsReferenceType()) return;
 245     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 246     {
 247         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
 248         GetBoundCompileUnit().FinalizeBinding(specialization);
 249     }
 250     TypeSymbol* pointerType = type->RemovePointer(spanmoduleId);
 251     if (TypesEqual(arguments[1]->GetType()pointerType->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
 252     {
 253         FunctionSymbol* function = functionMap[pointerType];
 254         if (!function)
 255         {
 256             function = new PointerMoveCtor(pointerTypespanmoduleId);
 257             function->SetModule(&GetBoundCompileUnit().GetModule());
 258             function->SetParent(&GetSymbolTable()->GlobalNs());
 259             functionMap[pointerType] = function;
 260             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 261         }
 262         viableFunctions.Insert(function);
 263     }
 264 }
 265 
 266 class PointerCopyAssignment public FunctionSymbol
 267 {
 268 public:
 269     PointerCopyAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId);
 270     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 271     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 272     bool IsBasicTypeOperation() const override { return true; }
 273     const char* ClassName() const override { return "PointerCopyAssignment"; }
 274 private:
 275     TypeSymbol* type;
 276 };
 277 
 278 PointerCopyAssignment::PointerCopyAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator=")type(type_)
 279 {
 280     SetGroupName(U"operator=");
 281     SetAccess(SymbolAccess::public_);
 282     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
 283     thisParam->SetType(type->AddPointer(spanmoduleId));
 284     AddMember(thisParam);
 285     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
 286     thatParam->SetType(type);
 287     AddMember(thatParam);
 288     SetReturnType(voidType_);
 289     ComputeName();
 290 }
 291 
 292 void PointerCopyAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 293 {
 294     Assert(genObjects.size() == 2"copy assignment needs two objects");
 295     genObjects[1]->Load(emitterOperationFlags::none);
 296     genObjects[0]->Store(emitterOperationFlags::none);
 297 }
 298 
 299 class PointerCopyAssignmentOperation public Operation
 300 {
 301 public:
 302     PointerCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
 303     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 304         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 305 private:
 306     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 307     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 308 };
 309 
 310 PointerCopyAssignmentOperation::PointerCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
 311 {
 312 }
 313 
 314 void PointerCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 315     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 316 {
 317     TypeSymbol* type = arguments[0]->GetType();
 318     if (type->PointerCount() <= 1) return;
 319     if (type->IsReferenceType()) return;
 320     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 321     {
 322         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
 323         GetBoundCompileUnit().FinalizeBinding(specialization);
 324     }
 325     TypeSymbol* pointerType = type->RemovePointer(spanmoduleId);
 326     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
 327         !TypesEqual(arguments[1]->GetType()pointerType->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
 328     {
 329         FunctionSymbol* function = functionMap[pointerType];
 330         if (!function)
 331         {
 332             function = new PointerCopyAssignment(pointerTypeGetSymbolTable()->GetTypeByName(U"void")spanmoduleId);
 333             function->SetModule(&GetBoundCompileUnit().GetModule());
 334             function->SetParent(&GetSymbolTable()->GlobalNs());
 335             functionMap[pointerType] = function;
 336             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 337         }
 338         viableFunctions.Insert(function);
 339     }
 340 }
 341 
 342 class PointerMoveAssignment public FunctionSymbol
 343 {
 344 public:
 345     PointerMoveAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId);
 346     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 347     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 348     bool IsBasicTypeOperation() const override { return true; }
 349     const char* ClassName() const override { return "PointerMoveAssignment"; }
 350 private:
 351     TypeSymbol* type;
 352 };
 353 
 354 PointerMoveAssignment::PointerMoveAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator=")type(type_)
 355 {
 356     SetGroupName(U"operator=");
 357     SetAccess(SymbolAccess::public_);
 358     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
 359     thisParam->SetType(type->AddPointer(spanmoduleId));
 360     AddMember(thisParam);
 361     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
 362     thatParam->SetType(type->AddRvalueReference(spanmoduleId));
 363     AddMember(thatParam);
 364     SetReturnType(voidType_);
 365     ComputeName();
 366 }
 367 
 368 void PointerMoveAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 369 {
 370     Assert(genObjects.size() == 2"copy assignment needs two objects");
 371     genObjects[1]->Load(emitterOperationFlags::none);
 372     void* rvalueRefValue = emitter.Stack().Pop();
 373     emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
 374     genObjects[0]->Store(emitterOperationFlags::none);
 375 }
 376 
 377 class PointerMoveAssignmentOperation public Operation
 378 {
 379 public:
 380     PointerMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
 381     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 382         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 383 private:
 384     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 385     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 386 };
 387 
 388 PointerMoveAssignmentOperation::PointerMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
 389 {
 390 }
 391 
 392 void PointerMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 393     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 394 {
 395     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
 396     TypeSymbol* type = arguments[0]->GetType();
 397     if (type->PointerCount() <= 1) return;
 398     if (type->IsReferenceType()) return;
 399     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 400     {
 401         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
 402         GetBoundCompileUnit().FinalizeBinding(specialization);
 403     }
 404     TypeSymbol* pointerType = type->RemovePointer(spanmoduleId);
 405     if (TypesEqual(arguments[1]->GetType()pointerType->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
 406     {
 407         FunctionSymbol* function = functionMap[pointerType];
 408         if (!function)
 409         {
 410             function = new PointerMoveAssignment(pointerTypeGetSymbolTable()->GetTypeByName(U"void")spanmoduleId);
 411             function->SetModule(&GetBoundCompileUnit().GetModule());
 412             function->SetParent(&GetSymbolTable()->GlobalNs());
 413             functionMap[pointerType] = function;
 414             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 415         }
 416         viableFunctions.Insert(function);
 417     }
 418 }
 419 
 420 class PointerReturn public FunctionSymbol
 421 {
 422 public:
 423     PointerReturn(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
 424     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 425     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 426     bool IsBasicTypeOperation() const override { return true; }
 427     const char* ClassName() const override { return "PointerReturn"; }
 428 private:
 429     TypeSymbol* type;
 430 };
 431 
 432 PointerReturn::PointerReturn(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@return")type(type_)
 433 {
 434     SetGroupName(U"@return");
 435     SetAccess(SymbolAccess::public_);
 436     ParameterSymbol* valueParam = new ParameterSymbol(spanmoduleIdU"value");
 437     valueParam->SetType(type);
 438     AddMember(valueParam);
 439     SetReturnType(type);
 440     ComputeName();
 441 }
 442 
 443 void PointerReturn::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 444 {
 445     Assert(genObjects.size() == 1"return needs one object");
 446     genObjects[0]->Load(emitterOperationFlags::none);
 447     if ((flags & OperationFlags::leaveFirstArg) != OperationFlags::none)
 448     {
 449         emitter.Stack().Dup();
 450         void* ptr = emitter.Stack().Pop();
 451         emitter.SaveObjectPointer(ptr);
 452     }
 453 }
 454 
 455 class PointerReturnOperation public Operation
 456 {
 457 public:
 458     PointerReturnOperation(BoundCompileUnit& boundCompileUnit_);
 459     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 460         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 461 private:
 462     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 463     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 464 };
 465 
 466 PointerReturnOperation::PointerReturnOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@return"1boundCompileUnit_)
 467 {
 468 }
 469 
 470 void PointerReturnOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 471     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 472 {
 473     TypeSymbol* type = arguments[0]->GetType();
 474     if (!type->IsPointerType()) return;
 475     if (type->IsReferenceType()) return;
 476     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 477     {
 478         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
 479         GetBoundCompileUnit().FinalizeBinding(specialization);
 480     }
 481     FunctionSymbol* function = functionMap[type];
 482     if (!function)
 483     {
 484         function = new PointerReturn(typespanmoduleId);
 485         function->SetModule(&GetBoundCompileUnit().GetModule());
 486         function->SetParent(&GetSymbolTable()->GlobalNs());
 487         functionMap[type] = function;
 488         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 489     }
 490     viableFunctions.Insert(function);
 491 }
 492 
 493 class PointerPlusOffset public FunctionSymbol
 494 {
 495 public:
 496     PointerPlusOffset(TypeSymbol* pointerType_TypeSymbol* longType_const Span& spanconst boost::uuids::uuid& moduleId);
 497     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 498     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 499     bool IsBasicTypeOperation() const override { return true; }
 500     const char* ClassName() const override { return "PointerPlusOffset"; }
 501 };
 502 
 503 PointerPlusOffset::PointerPlusOffset(TypeSymbol* pointerType_TypeSymbol* longType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator+")
 504 {
 505     SetGroupName(U"operator+");
 506     SetAccess(SymbolAccess::public_);
 507     ParameterSymbol* leftParam = new ParameterSymbol(spanmoduleIdU"left");
 508     leftParam->SetType(pointerType_);
 509     AddMember(leftParam);
 510     ParameterSymbol* rightParam = new ParameterSymbol(spanmoduleIdU"right");
 511     rightParam->SetType(longType_);
 512     AddMember(rightParam);
 513     SetReturnType(pointerType_);
 514     ComputeName();
 515 }
 516 
 517 void PointerPlusOffset::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 518 {
 519     Assert(genObjects.size() == 2"operator+ needs two objects");
 520     genObjects[0]->Load(emitterOperationFlags::none);
 521     void* left = emitter.Stack().Pop();
 522     genObjects[1]->Load(emitterOperationFlags::none);
 523     void* right = emitter.Stack().Pop();
 524     emitter.Stack().Push(emitter.ComputeAddress(leftright));
 525 }
 526 
 527 class PointerPlusOffsetOperation public Operation
 528 {
 529 public:
 530     PointerPlusOffsetOperation(BoundCompileUnit& boundCompileUnit_);
 531     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 532         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 533 private:
 534     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 535     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 536 };
 537 
 538 PointerPlusOffsetOperation::PointerPlusOffsetOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator+"2boundCompileUnit_)
 539 {
 540 }
 541 
 542 void PointerPlusOffsetOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 543     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 544 {
 545     TypeSymbol* leftType = arguments[0]->GetType();
 546     if (!leftType->IsPointerType()) return;
 547     leftType = leftType->PlainType(spanmoduleId);
 548     TypeSymbol* rightType = arguments[1]->GetType();
 549     if (!rightType->PlainType(spanmoduleId)->IsIntegralType())
 550     {
 551         ArgumentMatch argumentMatch;
 552         if (!GetBoundCompileUnit().GetConversion(rightTypeGetSymbolTable()->GetTypeByName(U"long")containerScopecurrentFunctionspanmoduleIdargumentMatch))
 553         {
 554             return;
 555         }
 556     }
 557     if (leftType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 558     {
 559         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(leftType->BaseType());
 560         GetBoundCompileUnit().FinalizeBinding(specialization);
 561     }
 562     FunctionSymbol* function = functionMap[leftType];
 563     if (!function)
 564     {
 565         function = new PointerPlusOffset(leftTypeGetSymbolTable()->GetTypeByName(U"long")spanmoduleId);
 566         function->SetModule(&GetBoundCompileUnit().GetModule());
 567         function->SetParent(&GetSymbolTable()->GlobalNs());
 568         functionMap[leftType] = function;
 569         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 570     }
 571     viableFunctions.Insert(function);
 572 }
 573 
 574 class OffsetPlusPointer public FunctionSymbol
 575 {
 576 public:
 577     OffsetPlusPointer(TypeSymbol* longType_TypeSymbol* pointerType_const Span& spanconst boost::uuids::uuid& moduleId);
 578     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 579     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 580     bool IsBasicTypeOperation() const override { return true; }
 581     const char* ClassName() const override { return "OffsetPlusPointer"; }
 582 };
 583 
 584 OffsetPlusPointer::OffsetPlusPointer(TypeSymbol* longType_TypeSymbol* pointerType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator+")
 585 {
 586     SetGroupName(U"operator+");
 587     SetAccess(SymbolAccess::public_);
 588     ParameterSymbol* leftParam = new ParameterSymbol(spanmoduleIdU"left");
 589     leftParam->SetType(longType_);
 590     AddMember(leftParam);
 591     ParameterSymbol* rightParam = new ParameterSymbol(spanmoduleIdU"right");
 592     rightParam->SetType(pointerType_);
 593     AddMember(rightParam);
 594     SetReturnType(pointerType_);
 595     ComputeName();
 596 }
 597 
 598 void OffsetPlusPointer::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 599 {
 600     Assert(genObjects.size() == 2"operator+ needs two objects");
 601     genObjects[0]->Load(emitterOperationFlags::none);
 602     void* left = emitter.Stack().Pop();
 603     genObjects[1]->Load(emitterOperationFlags::none);
 604     void* right = emitter.Stack().Pop();
 605     emitter.Stack().Push(emitter.ComputeAddress(rightleft));
 606 }
 607 
 608 class OffsetPlusPointerOperation public Operation
 609 {
 610 public:
 611     OffsetPlusPointerOperation(BoundCompileUnit& boundCompileUnit_);
 612     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 613         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 614 private:
 615     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 616     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 617 };
 618 
 619 OffsetPlusPointerOperation::OffsetPlusPointerOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator+"2boundCompileUnit_)
 620 {
 621 }
 622 
 623 void OffsetPlusPointerOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 624     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 625 {
 626     TypeSymbol* leftType = arguments[0]->GetType();
 627     if (!leftType->PlainType(spanmoduleId)->IsIntegralType())
 628     {
 629         ArgumentMatch argumentMatch;
 630         if (!GetBoundCompileUnit().GetConversion(leftTypeGetSymbolTable()->GetTypeByName(U"long")containerScopecurrentFunctionspanmoduleIdargumentMatch))
 631         {
 632             return;
 633         }
 634     }
 635     TypeSymbol* rightType = arguments[1]->GetType();
 636     if (!rightType->IsPointerType()) return;
 637     rightType = rightType->PlainType(spanmoduleId);
 638     TypeSymbol* longType = GetSymbolTable()->GetTypeByName(U"long");
 639     if (rightType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 640     {
 641         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(rightType->BaseType());
 642         GetBoundCompileUnit().FinalizeBinding(specialization);
 643     }
 644     FunctionSymbol* function = functionMap[rightType];
 645     if (!function)
 646     {
 647         function = new OffsetPlusPointer(longTyperightTypespanmoduleId);
 648         function->SetModule(&GetBoundCompileUnit().GetModule());
 649         function->SetParent(&GetSymbolTable()->GlobalNs());
 650         functionMap[rightType] = function;
 651         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 652     }
 653     viableFunctions.Insert(function);
 654 }
 655 
 656 class PointerMinusOffset public FunctionSymbol
 657 {
 658 public:
 659     PointerMinusOffset(TypeSymbol* pointerType_TypeSymbol* longType_const Span& spanconst boost::uuids::uuid& moduleId);
 660     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 661     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 662     bool IsBasicTypeOperation() const override { return true; }
 663     const char* ClassName() const override { return "PointerMinusOffset"; }
 664 };
 665 
 666 PointerMinusOffset::PointerMinusOffset(TypeSymbol* pointerType_TypeSymbol* longType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator-")
 667 {
 668     SetGroupName(U"operator-");
 669     SetAccess(SymbolAccess::public_);
 670     ParameterSymbol* leftParam = new ParameterSymbol(spanmoduleIdU"left");
 671     leftParam->SetType(pointerType_);
 672     AddMember(leftParam);
 673     ParameterSymbol* rightParam = new ParameterSymbol(spanmoduleIdU"right");
 674     rightParam->SetType(longType_);
 675     AddMember(rightParam);
 676     SetReturnType(pointerType_);
 677     ComputeName();
 678 }
 679 
 680 void PointerMinusOffset::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 681 {
 682     Assert(genObjects.size() == 2"operator- needs two objects");
 683     genObjects[0]->Load(emitterOperationFlags::none);
 684     void* left = emitter.Stack().Pop();
 685     genObjects[1]->Load(emitterOperationFlags::none);
 686     void* right = emitter.Stack().Pop();
 687     void* offset = emitter.CreateNeg(right);
 688     emitter.Stack().Push(emitter.ComputeAddress(leftoffset));
 689 }
 690 
 691 class PointerMinusOffsetOperation public Operation
 692 {
 693 public:
 694     PointerMinusOffsetOperation(BoundCompileUnit& boundCompileUnit_);
 695     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 696         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 697 private:
 698     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 699     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 700 };
 701 
 702 PointerMinusOffsetOperation::PointerMinusOffsetOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator-"2boundCompileUnit_)
 703 {
 704 }
 705 
 706 void PointerMinusOffsetOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 707     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 708 {
 709     TypeSymbol* leftType = arguments[0]->GetType();
 710     if (!leftType->IsPointerType()) return;
 711     leftType = leftType->PlainType(spanmoduleId);
 712     TypeSymbol* rightType = arguments[1]->GetType();
 713     if (!rightType->PlainType(spanmoduleId)->IsIntegralType())
 714     {
 715         ArgumentMatch argumentMatch;
 716         if (!GetBoundCompileUnit().GetConversion(rightTypeGetSymbolTable()->GetTypeByName(U"long")containerScopecurrentFunctionspanmoduleIdargumentMatch))
 717         {
 718             return;
 719         }
 720     }
 721     if (leftType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 722     {
 723         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(leftType->BaseType());
 724         GetBoundCompileUnit().FinalizeBinding(specialization);
 725     }
 726     FunctionSymbol* function = functionMap[leftType];
 727     if (!function)
 728     {
 729         function = new PointerMinusOffset(leftTypeGetSymbolTable()->GetTypeByName(U"long")spanmoduleId);
 730         function->SetModule(&GetBoundCompileUnit().GetModule());
 731         function->SetParent(&GetSymbolTable()->GlobalNs());
 732         functionMap[leftType] = function;
 733         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 734     }
 735     viableFunctions.Insert(function);
 736 }
 737 
 738 class PointerMinusPointer public FunctionSymbol
 739 {
 740 public:
 741     PointerMinusPointer(TypeSymbol* pointerType_TypeSymbol* longType_const Span& spanconst boost::uuids::uuid& moduleId);
 742     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 743     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 744     bool IsBasicTypeOperation() const override { return true; }
 745     const char* ClassName() const override { return "PointerMinusPointer"; }
 746 };
 747 
 748 PointerMinusPointer::PointerMinusPointer(TypeSymbol* pointerType_TypeSymbol* longType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator-")
 749 {
 750     SetGroupName(U"operator-");
 751     SetAccess(SymbolAccess::public_);
 752     ParameterSymbol* leftParam = new ParameterSymbol(spanmoduleIdU"left");
 753     leftParam->SetType(pointerType_);
 754     AddMember(leftParam);
 755     ParameterSymbol* rightParam = new ParameterSymbol(spanmoduleIdU"right");
 756     rightParam->SetType(pointerType_);
 757     AddMember(rightParam);
 758     SetReturnType(longType_);
 759     ComputeName();
 760 }
 761 
 762 void PointerMinusPointer::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 763 {
 764     Assert(genObjects.size() == 2"operator- needs two objects");
 765     genObjects[0]->Load(emitterOperationFlags::none);
 766     void* left = emitter.Stack().Pop();
 767     genObjects[1]->Load(emitterOperationFlags::none);
 768     void* right = emitter.Stack().Pop();
 769     emitter.Stack().Push(emitter.CreatePtrDiff(leftright));
 770 }
 771 
 772 class PointerMinusPointerOperation public Operation
 773 {
 774 public:
 775     PointerMinusPointerOperation(BoundCompileUnit& boundCompileUnit_);
 776     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 777         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 778 private:
 779     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 780     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 781 };
 782 
 783 PointerMinusPointerOperation::PointerMinusPointerOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator-"2boundCompileUnit_)
 784 {
 785 }
 786 
 787 void PointerMinusPointerOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 788     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 789 {
 790     TypeSymbol* leftType = arguments[0]->GetType();
 791     if (!leftType->IsPointerType()) return;
 792     leftType = leftType->PlainType(spanmoduleId);
 793     TypeSymbol* rightType = arguments[1]->GetType();
 794     if (!rightType->IsPointerType()) return;
 795     rightType = rightType->PlainType(spanmoduleId);
 796     if (leftType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 797     {
 798         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(leftType->BaseType());
 799         GetBoundCompileUnit().FinalizeBinding(specialization);
 800     }
 801     FunctionSymbol* function = functionMap[leftType];
 802     if (!function)
 803     {
 804         function = new PointerMinusPointer(leftTypeGetSymbolTable()->GetTypeByName(U"long")spanmoduleId);
 805         function->SetModule(&GetBoundCompileUnit().GetModule());
 806         function->SetParent(&GetSymbolTable()->GlobalNs());
 807         functionMap[leftType] = function;
 808         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 809     }
 810     viableFunctions.Insert(function);
 811 }
 812 
 813 class PointerEqual public FunctionSymbol
 814 {
 815 public:
 816     PointerEqual(TypeSymbol* pointerType_TypeSymbol* boolType_const Span& spanconst boost::uuids::uuid& moduleId);
 817     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 818     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 819     bool IsBasicTypeOperation() const override { return true; }
 820     const char* ClassName() const override { return "PointerEqual"; }
 821 };
 822 
 823 PointerEqual::PointerEqual(TypeSymbol* pointerType_TypeSymbol* boolType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator==")
 824 {
 825     SetGroupName(U"operator==");
 826     SetAccess(SymbolAccess::public_);
 827     ParameterSymbol* leftParam = new ParameterSymbol(spanmoduleIdU"left");
 828     leftParam->SetType(pointerType_);
 829     AddMember(leftParam);
 830     ParameterSymbol* rightParam = new ParameterSymbol(spanmoduleIdU"right");
 831     rightParam->SetType(pointerType_);
 832     AddMember(rightParam);
 833     SetReturnType(boolType_);
 834     ComputeName();
 835 }
 836 
 837 void PointerEqual::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 838 {
 839     Assert(genObjects.size() == 2"operator== needs two objects");
 840     genObjects[0]->Load(emitterOperationFlags::none);
 841     void* left = emitter.Stack().Pop();
 842     genObjects[1]->Load(emitterOperationFlags::none);
 843     void* right = emitter.Stack().Pop();
 844     emitter.Stack().Push(emitter.CreateICmpEQ(leftright));
 845 }
 846 
 847 class PointerEqualOperation public Operation
 848 {
 849 public:
 850     PointerEqualOperation(BoundCompileUnit& boundCompileUnit_);
 851     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 852         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 853 private:
 854     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 855     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 856 };
 857 
 858 PointerEqualOperation::PointerEqualOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator=="2boundCompileUnit_)
 859 {
 860 }
 861 
 862 void PointerEqualOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 863     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 864 {
 865     TypeSymbol* leftType = arguments[0]->GetType();
 866     if (!leftType->IsPointerType()) return;
 867     leftType = leftType->PlainType(spanmoduleId);
 868     TypeSymbol* rightType = arguments[1]->GetType();
 869     rightType = rightType->PlainType(spanmoduleId);
 870     if (!rightType->IsPointerType()) return;
 871     if (leftType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 872     {
 873         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(leftType->BaseType());
 874         GetBoundCompileUnit().FinalizeBinding(specialization);
 875     }
 876     FunctionSymbol* function = functionMap[leftType];
 877     if (!function)
 878     {
 879         function = new PointerEqual(leftTypeGetSymbolTable()->GetTypeByName(U"bool")spanmoduleId);
 880         function->SetModule(&GetBoundCompileUnit().GetModule());
 881         function->SetParent(&GetSymbolTable()->GlobalNs());
 882         functionMap[leftType] = function;
 883         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 884     }
 885     viableFunctions.Insert(function);
 886 }
 887 
 888 class PointerLess public FunctionSymbol
 889 {
 890 public:
 891     PointerLess(TypeSymbol* pointerType_TypeSymbol* boolType_const Span& spanconst boost::uuids::uuid& moduleId);
 892     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 893     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 894     bool IsBasicTypeOperation() const override { return true; }
 895     const char* ClassName() const override { return "PointerLess"; }
 896 };
 897 
 898 PointerLess::PointerLess(TypeSymbol* pointerType_TypeSymbol* boolType_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator<")
 899 {
 900     SetGroupName(U"operator<");
 901     SetAccess(SymbolAccess::public_);
 902     ParameterSymbol* leftParam = new ParameterSymbol(spanmoduleIdU"left");
 903     leftParam->SetType(pointerType_);
 904     AddMember(leftParam);
 905     ParameterSymbol* rightParam = new ParameterSymbol(spanmoduleIdU"right");
 906     rightParam->SetType(pointerType_);
 907     AddMember(rightParam);
 908     SetReturnType(boolType_);
 909     ComputeName();
 910 }
 911 
 912 void PointerLess::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 913 {
 914     Assert(genObjects.size() == 2"operator< needs two objects");
 915     genObjects[0]->Load(emitterOperationFlags::none);
 916     void* left = emitter.Stack().Pop();
 917     genObjects[1]->Load(emitterOperationFlags::none);
 918     void* right = emitter.Stack().Pop();
 919     emitter.Stack().Push(emitter.CreateICmpULT(leftright));
 920 }
 921 
 922 class PointerLessOperation public Operation
 923 {
 924 public:
 925     PointerLessOperation(BoundCompileUnit& boundCompileUnit_);
 926     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 927         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 928 private:
 929     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
 930     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
 931 };
 932 
 933 PointerLessOperation::PointerLessOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator<"2boundCompileUnit_)
 934 {
 935 }
 936 
 937 void PointerLessOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 938     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 939 {
 940     TypeSymbol* leftType = arguments[0]->GetType();
 941     if (!leftType->IsPointerType()) return;
 942     leftType = leftType->PlainType(spanmoduleId);
 943     TypeSymbol* rightType = arguments[1]->GetType();
 944     if (!rightType->IsPointerType()) return;
 945     rightType = rightType->PlainType(spanmoduleId);
 946     if (leftType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 947     {
 948         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(leftType->BaseType());
 949         GetBoundCompileUnit().FinalizeBinding(specialization);
 950     }
 951     FunctionSymbol* function = functionMap[leftType];
 952     if (!function)
 953     {
 954         function = new PointerLess(leftTypeGetSymbolTable()->GetTypeByName(U"bool")spanmoduleId);
 955         function->SetModule(&GetBoundCompileUnit().GetModule());
 956         function->SetParent(&GetSymbolTable()->GlobalNs());
 957         functionMap[leftType] = function;
 958         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
 959     }
 960     viableFunctions.Insert(function);
 961 }
 962 
 963 class PointerArrow public FunctionSymbol
 964 {
 965 public:
 966     PointerArrow(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
 967     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
 968     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 969     bool IsBasicTypeOperation() const override { return true; }
 970     const char* ClassName() const override { return "PointerArrow"; }
 971 private:
 972     TypeSymbol* type;
 973 };
 974 
 975 PointerArrow::PointerArrow(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"operator->")type(type_)
 976 {
 977     SetGroupName(U"operator->");
 978     SetAccess(SymbolAccess::public_);
 979     ParameterSymbol* operandParam = new ParameterSymbol(spanmoduleIdU"operand");
 980     operandParam->SetType(type->AddPointer(spanmoduleId));
 981     AddMember(operandParam);
 982     SetReturnType(type);
 983     ComputeName();
 984 }
 985 
 986 void PointerArrow::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 987 {
 988     Assert(genObjects.size() == 1"return needs one object");
 989     genObjects[0]->Load(emitterOperationFlags::none);
 990 }
 991 
 992 class PointerArrowOperation public Operation
 993 {
 994 public:
 995     PointerArrowOperation(BoundCompileUnit& boundCompileUnit_);
 996     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
 997         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
 998 private:
 999     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1000     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1001 };
1002 
1003 PointerArrowOperation::PointerArrowOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator->"1boundCompileUnit_)
1004 {
1005 }
1006 
1007 void PointerArrowOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1008     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1009 {
1010     TypeSymbol* type = arguments[0]->GetType();
1011     if (type->PointerCount() <= 1) return;
1012     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1013     {
1014         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1015         GetBoundCompileUnit().FinalizeBinding(specialization);
1016     }
1017     TypeSymbol* pointerType = type->RemovePointer(spanmoduleId);
1018     FunctionSymbol* function = functionMap[pointerType];
1019     if (!function)
1020     {
1021         function = new PointerArrow(pointerTypespanmoduleId);
1022         function->SetModule(&GetBoundCompileUnit().GetModule());
1023         function->SetParent(&GetSymbolTable()->GlobalNs());
1024         functionMap[pointerType] = function;
1025         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1026     }
1027     viableFunctions.Insert(function);
1028 }
1029 
1030 class LvalueRefefenceCopyCtor public FunctionSymbol
1031 {
1032 public:
1033     LvalueRefefenceCopyCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
1034     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1035     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1036     bool IsBasicTypeOperation() const override { return true; }
1037     const char* ClassName() const override { return "LvalueRefefenceCopyCtor"; }
1038 private:
1039     TypeSymbol* type;
1040 };
1041 
1042 LvalueRefefenceCopyCtor::LvalueRefefenceCopyCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@constructor")type(type_)
1043 {
1044     SetGroupName(U"@constructor");
1045     SetAccess(SymbolAccess::public_);
1046     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
1047     thisParam->SetType(type->AddPointer(spanmoduleId));
1048     AddMember(thisParam);
1049     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
1050     thatParam->SetType(type);
1051     AddMember(thatParam);
1052     ComputeName();
1053 }
1054 
1055 void LvalueRefefenceCopyCtor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1056 {
1057     Assert(genObjects.size() == 2"reference copy constructor needs two objects");
1058     genObjects[1]->Load(emitterOperationFlags::none);
1059     genObjects[0]->Store(emitterOperationFlags::none);
1060 }
1061 
1062 class LvalueReferenceCopyConstructorOperation public Operation
1063 {
1064 public:
1065     LvalueReferenceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1066     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1067         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1068 private:
1069     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1070     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1071 };
1072 
1073 LvalueReferenceCopyConstructorOperation::LvalueReferenceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
1074 {
1075 }
1076 
1077 void LvalueReferenceCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1078     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1079 {
1080     TypeSymbol* type = arguments[0]->GetType();
1081     if (type->PointerCount() < 1 || !type->IsLvalueReferenceType()) return;
1082     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1083     {
1084         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1085         GetBoundCompileUnit().FinalizeBinding(specialization);
1086     }
1087     TypeSymbol* lvalueRefType = type->RemovePointer(spanmoduleId);
1088     FunctionSymbol* function = functionMap[lvalueRefType];
1089     if (!function)
1090     {
1091         function = new LvalueRefefenceCopyCtor(lvalueRefTypespanmoduleId);
1092         function->SetModule(&GetBoundCompileUnit().GetModule());
1093         function->SetParent(&GetSymbolTable()->GlobalNs());
1094         functionMap[lvalueRefType] = function;
1095         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1096     }
1097     viableFunctions.Insert(function);
1098 }
1099 
1100 class LvalueReferenceCopyAssignment public FunctionSymbol
1101 {
1102 public:
1103     LvalueReferenceCopyAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId);
1104     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1105     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1106     bool IsBasicTypeOperation() const override { return true; }
1107     bool IsLvalueReferenceCopyAssignment() const override { return true; }
1108     const char* ClassName() const override { return "LvalueReferenceCopyAssignment"; }
1109 private:
1110     TypeSymbol* type;
1111 };
1112 
1113 LvalueReferenceCopyAssignment::LvalueReferenceCopyAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId) :
1114     FunctionSymbol(spanmoduleIdU"operator=")type(type_)
1115 {
1116     SetGroupName(U"operator=");
1117     SetAccess(SymbolAccess::public_);
1118     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
1119     thisParam->SetType(type->AddPointer(spanmoduleId));
1120     AddMember(thisParam);
1121     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
1122     thatParam->SetType(type);
1123     AddMember(thatParam);
1124     SetReturnType(voidType_);
1125     ComputeName();
1126 }
1127 
1128 void LvalueReferenceCopyAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1129 {
1130     Assert(genObjects.size() == 2"copy assignment needs two objects");
1131     genObjects[1]->Load(emitterOperationFlags::none);
1132     genObjects[0]->Store(emitterOperationFlags::none);
1133 }
1134 
1135 class LvalueReferenceCopyAssignmentOperation public Operation
1136 {
1137 public:
1138     LvalueReferenceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1139     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1140         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1141 private:
1142     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1143     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1144 };
1145 
1146 LvalueReferenceCopyAssignmentOperation::LvalueReferenceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
1147 {
1148 }
1149 
1150 void LvalueReferenceCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1151     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1152 {
1153     TypeSymbol* type = arguments[0]->GetType();
1154     if (type->PointerCount() < 1 || !type->IsLvalueReferenceType()) return;
1155     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1156     {
1157         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1158         GetBoundCompileUnit().FinalizeBinding(specialization);
1159     }
1160     TypeSymbol* lvalueRefType = type->RemovePointer(spanmoduleId);
1161     if (lvalueRefType->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
1162     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
1163         !TypesEqual(arguments[1]->GetType()->RemoveConst(spanmoduleId)lvalueRefType->PlainType(spanmoduleId)->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1164     {
1165         FunctionSymbol* function = functionMap[lvalueRefType];
1166         if (!function)
1167         {
1168             function = new LvalueReferenceCopyAssignment(lvalueRefTypeGetSymbolTable()->GetTypeByName(U"void")spanmoduleId);
1169             function->SetModule(&GetBoundCompileUnit().GetModule());
1170             function->SetParent(&GetSymbolTable()->GlobalNs());
1171             functionMap[lvalueRefType] = function;
1172             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1173         }
1174         viableFunctions.Insert(function);
1175     }
1176 }
1177 
1178 class LvalueReferenceMoveAssignment public FunctionSymbol
1179 {
1180 public:
1181     LvalueReferenceMoveAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId);
1182     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1183     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1184     bool IsBasicTypeOperation() const override { return true; }
1185     const char* ClassName() const override { return "LvalueReferenceMoveAssignment"; }
1186 private:
1187     TypeSymbol* type;
1188 };
1189 
1190 LvalueReferenceMoveAssignment::LvalueReferenceMoveAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId) :
1191     FunctionSymbol(spanmoduleIdU"operator=")type(type_)
1192 {
1193     SetGroupName(U"operator=");
1194     SetAccess(SymbolAccess::public_);
1195     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
1196     thisParam->SetType(type->AddPointer(spanmoduleId));
1197     AddMember(thisParam);
1198     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
1199     thatParam->SetType(type->RemoveReference(spanmoduleId)->AddRvalueReference(spanmoduleId));
1200     AddMember(thatParam);
1201     SetReturnType(voidType_);
1202     ComputeName();
1203 }
1204 
1205 void LvalueReferenceMoveAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1206 {
1207     Assert(genObjects.size() == 2"copy assignment needs two objects");
1208     genObjects[1]->Load(emitterOperationFlags::none);
1209     void* rvalueRefValue = emitter.Stack().Pop();
1210     emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
1211     genObjects[0]->Store(emitterOperationFlags::none);
1212 }
1213 
1214 class LvalueReferenceMoveAssignmentOperation public Operation
1215 {
1216 public:
1217     LvalueReferenceMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1218     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1219         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1220 private:
1221     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1222     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1223 };
1224 
1225 LvalueReferenceMoveAssignmentOperation::LvalueReferenceMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
1226 {
1227 }
1228 
1229 void LvalueReferenceMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1230     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1231 {
1232     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1233     TypeSymbol* type = arguments[0]->GetType();
1234     if (type->PointerCount() < 1 || !type->IsLvalueReferenceType()) return;
1235     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1236     {
1237         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1238         GetBoundCompileUnit().FinalizeBinding(specialization);
1239     }
1240     TypeSymbol* lvalueRefType = type->RemovePointer(spanmoduleId);
1241     if (lvalueRefType->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
1242     if (lvalueRefType->PlainType(spanmoduleId)->IsArrayType()) return;
1243     if (TypesEqual(arguments[1]->GetType()->RemoveConst(spanmoduleId)lvalueRefType->PlainType(spanmoduleId)->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1244     {
1245         FunctionSymbol* function = functionMap[lvalueRefType];
1246         if (!function)
1247         {
1248             function = new LvalueReferenceMoveAssignment(lvalueRefTypeGetSymbolTable()->GetTypeByName(U"void")spanmoduleId);
1249             function->SetModule(&GetBoundCompileUnit().GetModule());
1250             function->SetParent(&GetSymbolTable()->GlobalNs());
1251             functionMap[lvalueRefType] = function;
1252             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1253         }
1254         viableFunctions.Insert(function);
1255     }
1256 }
1257 
1258 class LvalueReferenceReturn public FunctionSymbol
1259 {
1260 public:
1261     LvalueReferenceReturn(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
1262     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1263     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1264     bool IsBasicTypeOperation() const override { return true; }
1265     const char* ClassName() const override { return "LvalueReferenceReturn"; }
1266 private:
1267     TypeSymbol* type;
1268 };
1269 
1270 LvalueReferenceReturn::LvalueReferenceReturn(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@return")type(type_)
1271 {
1272     SetGroupName(U"@return");
1273     SetAccess(SymbolAccess::public_);
1274     ParameterSymbol* valueParam = new ParameterSymbol(spanmoduleIdU"value");
1275     valueParam->SetType(type);
1276     AddMember(valueParam);
1277     SetReturnType(type);
1278     ComputeName();
1279 }
1280 
1281 void LvalueReferenceReturn::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1282 {
1283     Assert(genObjects.size() == 1"return needs one object");
1284     genObjects[0]->Load(emitterOperationFlags::none);
1285 }
1286 
1287 class LvalueReferenceReturnOperation public Operation
1288 {
1289 public:
1290     LvalueReferenceReturnOperation(BoundCompileUnit& boundCompileUnit_);
1291     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1292         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1293 private:
1294     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1295     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1296 };
1297 
1298 LvalueReferenceReturnOperation::LvalueReferenceReturnOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@return"1boundCompileUnit_)
1299 {
1300 }
1301 
1302 void LvalueReferenceReturnOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1303     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1304 {
1305     TypeSymbol* type = arguments[0]->GetType();
1306     if (!type->IsLvalueReferenceType()) return;
1307     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1308     {
1309         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1310         GetBoundCompileUnit().FinalizeBinding(specialization);
1311     }
1312     FunctionSymbol* function = functionMap[type];
1313     if (!function)
1314     {
1315         function = new LvalueReferenceReturn(typespanmoduleId);
1316         function->SetModule(&GetBoundCompileUnit().GetModule());
1317         function->SetParent(&GetSymbolTable()->GlobalNs());
1318         functionMap[type] = function;
1319         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1320     }
1321     viableFunctions.Insert(function);
1322 }
1323 
1324 class RvalueRefefenceCopyCtor public FunctionSymbol
1325 {
1326 public:
1327     RvalueRefefenceCopyCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
1328     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1329     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1330     bool IsBasicTypeOperation() const override { return true; }
1331     const char* ClassName() const override { return "RvalueRefefenceCopyCtor"; }
1332 private:
1333     TypeSymbol* type;
1334 };
1335 
1336 RvalueRefefenceCopyCtor::RvalueRefefenceCopyCtor(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) : FunctionSymbol(spanmoduleIdU"@constructor")type(type_)
1337 {
1338     SetGroupName(U"@constructor");
1339     SetAccess(SymbolAccess::public_);
1340     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
1341     thisParam->SetType(type->AddPointer(spanmoduleId));
1342     AddMember(thisParam);
1343     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
1344     thatParam->SetType(type);
1345     AddMember(thatParam);
1346     ComputeName();
1347 }
1348 
1349 void RvalueRefefenceCopyCtor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1350 {
1351     Assert(genObjects.size() == 2"reference copy constructor needs two objects");
1352     genObjects[1]->Load(emitterOperationFlags::none);
1353     genObjects[0]->Store(emitterOperationFlags::none);
1354 }
1355 
1356 class RvalueReferenceCopyConstructorOperation public Operation
1357 {
1358 public:
1359     RvalueReferenceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1360     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1361         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1362 private:
1363     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1364     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1365 };
1366 
1367 RvalueReferenceCopyConstructorOperation::RvalueReferenceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
1368 {
1369 }
1370 
1371 void RvalueReferenceCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1372     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1373 {
1374     TypeSymbol* type = arguments[0]->GetType();
1375     if (type->PointerCount() < 1 || !type->IsRvalueReferenceType()) return;
1376     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1377     {
1378         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1379         GetBoundCompileUnit().FinalizeBinding(specialization);
1380     }
1381     TypeSymbol* rvalueRefType = type->RemovePointer(spanmoduleId);
1382     if (rvalueRefType->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
1383     FunctionSymbol* function = functionMap[rvalueRefType];
1384     if (!function)
1385     {
1386         function = new RvalueRefefenceCopyCtor(rvalueRefTypespanmoduleId);
1387         function->SetModule(&GetBoundCompileUnit().GetModule());
1388         function->SetParent(&GetSymbolTable()->GlobalNs());
1389         functionMap[rvalueRefType] = function;
1390         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1391     }
1392     viableFunctions.Insert(function);
1393 }
1394 
1395 class RvalueReferenceCopyAssignment public FunctionSymbol
1396 {
1397 public:
1398     RvalueReferenceCopyAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId);
1399     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1400     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1401     bool IsBasicTypeOperation() const override { return true; }
1402     const char* ClassName() const override { return "RvalueReferenceCopyAssignment"; }
1403 private:
1404     TypeSymbol* type;
1405 };
1406 
1407 RvalueReferenceCopyAssignment::RvalueReferenceCopyAssignment(TypeSymbol* type_TypeSymbol* voidType_const Span& spanconst boost::uuids::uuid& moduleId) :
1408     FunctionSymbol(spanmoduleIdU"operator=")type(type_)
1409 {
1410     SetGroupName(U"operator=");
1411     SetAccess(SymbolAccess::public_);
1412     ParameterSymbol* thisParam = new ParameterSymbol(spanmoduleIdU"this");
1413     thisParam->SetType(type->AddPointer(spanmoduleId));
1414     AddMember(thisParam);
1415     ParameterSymbol* thatParam = new ParameterSymbol(spanmoduleIdU"that");
1416     thatParam->SetType(type);
1417     AddMember(thatParam);
1418     SetReturnType(voidType_);
1419     ComputeName();
1420 }
1421 
1422 void RvalueReferenceCopyAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1423 {
1424     Assert(genObjects.size() == 2"copy assignment needs two objects");
1425     genObjects[1]->Load(emitterOperationFlags::none);
1426     void* rvalueRefValue = emitter.Stack().Pop();
1427     emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
1428     genObjects[0]->Store(emitterOperationFlags::none);
1429 }
1430 
1431 class RvalueReferenceCopyAssignmentOperation public Operation
1432 {
1433 public:
1434     RvalueReferenceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1435     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1436         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1437 private:
1438     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1439     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1440 };
1441 
1442 RvalueReferenceCopyAssignmentOperation::RvalueReferenceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
1443 {
1444 }
1445 
1446 void RvalueReferenceCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1447     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1448 {
1449     TypeSymbol* type = arguments[0]->GetType();
1450     if (type->PointerCount() < 1 || !type->IsRvalueReferenceType()) return;
1451     TypeSymbol* rvalueRefType = type->RemovePointer(spanmoduleId);
1452     if (rvalueRefType->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
1453     if (rvalueRefType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1454     {
1455         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(rvalueRefType->BaseType());
1456         GetBoundCompileUnit().FinalizeBinding(specialization);
1457     }
1458     FunctionSymbol* function = functionMap[rvalueRefType];
1459     if (!function)
1460     {
1461         function = new RvalueReferenceCopyAssignment(rvalueRefTypeGetSymbolTable()->GetTypeByName(U"void")spanmoduleId);
1462         function->SetModule(&GetBoundCompileUnit().GetModule());
1463         function->SetParent(&GetSymbolTable()->GlobalNs());
1464         functionMap[rvalueRefType] = function;
1465         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1466     }
1467     viableFunctions.Insert(function);
1468 }
1469 
1470 class RvalueReferenceReturn public FunctionSymbol
1471 {
1472 public:
1473     RvalueReferenceReturn(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId);
1474     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1475     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
1476     bool IsBasicTypeOperation() const override { return true; }
1477     const char* ClassName() const override { return "RvalueReferenceReturn"; }
1478 private:
1479     TypeSymbol* type;
1480 };
1481 
1482 RvalueReferenceReturn::RvalueReferenceReturn(TypeSymbol* type_const Span& spanconst boost::uuids::uuid& moduleId) :
1483     FunctionSymbol(spanmoduleIdU"@return")type(type_)
1484 {
1485     SetGroupName(U"@return");
1486     SetAccess(SymbolAccess::public_);
1487     ParameterSymbol* valueParam = new ParameterSymbol(spanmoduleIdU"value");
1488     valueParam->SetType(type);
1489     AddMember(valueParam);
1490     SetReturnType(type);
1491     ComputeName();
1492 }
1493 
1494 void RvalueReferenceReturn::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1495 {
1496     Assert(genObjects.size() == 1"return needs one object");
1497     genObjects[0]->Load(emitterOperationFlags::none);
1498 }
1499 
1500 class RvalueReferenceReturnOperation public Operation
1501 {
1502 public:
1503     RvalueReferenceReturnOperation(BoundCompileUnit& boundCompileUnit_);
1504     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1505         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1506 private:
1507     std::unordered_map<TypeSymbol*FunctionSymbol*> functionMap;
1508     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1509 };
1510 
1511 RvalueReferenceReturnOperation::RvalueReferenceReturnOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@return"1boundCompileUnit_)
1512 {
1513 }
1514 
1515 void RvalueReferenceReturnOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1516     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1517 {
1518     TypeSymbol* type = arguments[0]->GetType();
1519     if (!type->IsRvalueReferenceType()) return;
1520     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1521     {
1522         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1523         GetBoundCompileUnit().FinalizeBinding(specialization);
1524     }
1525     FunctionSymbol* function = functionMap[type];
1526     if (!function)
1527     {
1528         function = new RvalueReferenceReturn(typespanmoduleId);
1529         function->SetModule(&GetBoundCompileUnit().GetModule());
1530         function->SetParent(&GetSymbolTable()->GlobalNs());
1531         functionMap[type] = function;
1532         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1533     }
1534     viableFunctions.Insert(function);
1535 }
1536 
1537 class ArrayDefaultConstructorOperation public Operation
1538 {
1539 public:
1540     ArrayDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1541     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1542         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1543 private:
1544     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1545     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1546 };
1547 
1548 ArrayDefaultConstructorOperation::ArrayDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"1boundCompileUnit_)
1549 {
1550 }
1551 
1552 void ArrayDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1553     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1554 {
1555     TypeSymbol* type = arguments[0]->GetType();
1556     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->IsArrayType()) return;
1557     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1558     {
1559         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1560         GetBoundCompileUnit().FinalizeBinding(specialization);
1561     }
1562     ArrayTypeSymbol* arrayType = static_cast<ArrayTypeSymbol*>(type->RemovePointer(spanmoduleId));
1563     FunctionSymbol* function = functionMap[arrayType->TypeId()];
1564     if (!function)
1565     {
1566         std::vector<FunctionScopeLookup> elementLookups;
1567         elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1568         elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1569         elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1570         std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1571         elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddPointer(spanmoduleId))));
1572         std::unique_ptr<BoundFunctionCall> elementDefaultConstructor = ResolveOverload(U"@constructor"containerScopeelementLookupselementArgumentsGetBoundCompileUnit()currentFunction
1573             spanmoduleId);
1574         FunctionSymbol* elementTypeDefaultConstructor = elementDefaultConstructor->GetFunctionSymbol();
1575         ArrayTypeDefaultConstructor* arrayTypeDefaultConstructor = new ArrayTypeDefaultConstructor(arrayTypeelementTypeDefaultConstructor);
1576         arrayTypeDefaultConstructor->SetTemporariesForElementTypeDefaultCtor(elementDefaultConstructor->ReleaseTemporaries());
1577         function = arrayTypeDefaultConstructor;
1578         function->SetModule(&GetBoundCompileUnit().GetModule());
1579         function->SetParent(&GetSymbolTable()->GlobalNs());
1580         functionMap[arrayType->TypeId()] = function;
1581         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1582     }
1583     viableFunctions.Insert(function);
1584 }
1585 
1586 class ArrayCopyConstructorOperation public Operation
1587 {
1588 public:
1589     ArrayCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1590     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1591         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1592 private:
1593     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1594     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1595 };
1596 
1597 ArrayCopyConstructorOperation::ArrayCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
1598 {
1599 }
1600 
1601 void ArrayCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1602     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1603 {
1604     TypeSymbol* type = arguments[0]->GetType();
1605     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->IsArrayType()) return;
1606     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1607     {
1608         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1609         GetBoundCompileUnit().FinalizeBinding(specialization);
1610     }
1611     ArrayTypeSymbol* arrayType = static_cast<ArrayTypeSymbol*>(type->RemovePointer(spanmoduleId));
1612     if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
1613         !TypesEqual(arguments[1]->GetType()arrayType->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) && 
1614         TypesEqual(arguments[1]->GetType()->PlainType(spanmoduleId)arrayType))
1615     {
1616         FunctionSymbol* function = functionMap[arrayType->TypeId()];
1617         if (!function)
1618         {
1619             std::vector<FunctionScopeLookup> elementLookups;
1620             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1621             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1622             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1623             std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1624             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddPointer(spanmoduleId))));
1625             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddConst(spanmoduleId)->AddLvalueReference(spanmoduleId))));
1626             std::unique_ptr<BoundFunctionCall> elementCopyConstructor = ResolveOverload(U"@constructor"containerScopeelementLookupselementArgumentsGetBoundCompileUnit()currentFunction
1627                 spanmoduleId);
1628             FunctionSymbol* elementTypeCopyConstructor = elementCopyConstructor->GetFunctionSymbol();
1629             ArrayTypeCopyConstructor* arrayTypeCopyConstructor = new ArrayTypeCopyConstructor(arrayTypeelementTypeCopyConstructor);
1630             arrayTypeCopyConstructor->SetTemporariesForElementTypeCopyCtor(elementCopyConstructor->ReleaseTemporaries());
1631             function = arrayTypeCopyConstructor;
1632             function->SetModule(&GetBoundCompileUnit().GetModule());
1633             function->SetParent(&GetSymbolTable()->GlobalNs());
1634             functionMap[arrayType->TypeId()] = function;
1635             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1636         }
1637         viableFunctions.Insert(function);
1638     }
1639 }
1640 
1641 class ArrayMoveConstructorOperation public Operation
1642 {
1643 public:
1644     ArrayMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1645     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1646         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1647 private:
1648     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1649     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1650 };
1651 
1652 ArrayMoveConstructorOperation::ArrayMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
1653 {
1654 }
1655 
1656 void ArrayMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1657     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1658 {
1659     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1660     TypeSymbol* type = arguments[0]->GetType();
1661     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->IsArrayType()) return;
1662     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1663     {
1664         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1665         GetBoundCompileUnit().FinalizeBinding(specialization);
1666     }
1667     ArrayTypeSymbol* arrayType = static_cast<ArrayTypeSymbol*>(type->RemovePointer(spanmoduleId));
1668     if (TypesEqual(arguments[1]->GetType()arrayType->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1669     {
1670         FunctionSymbol* function = functionMap[arrayType->TypeId()];
1671         if (!function)
1672         {
1673             std::vector<FunctionScopeLookup> elementLookups;
1674             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1675             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1676             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1677             std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1678             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddPointer(spanmoduleId))));
1679             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddRvalueReference(spanmoduleId))));
1680             elementArguments.back()->SetFlag(BoundExpressionFlags::bindToRvalueReference);
1681             std::unique_ptr<BoundFunctionCall> elementMoveConstructor = ResolveOverload(U"@constructor"containerScopeelementLookupselementArgumentsGetBoundCompileUnit()currentFunction
1682                 spanmoduleId);
1683             FunctionSymbol* elementTypeMoveConstructor = elementMoveConstructor->GetFunctionSymbol();
1684             ArrayTypeMoveConstructor* arrayTypeMoveConstructor = new ArrayTypeMoveConstructor(arrayTypeelementTypeMoveConstructor);
1685             arrayTypeMoveConstructor->SetTemporariesForElementTypeMoveCtor(elementMoveConstructor->ReleaseTemporaries());
1686             function = arrayTypeMoveConstructor;
1687             function->SetModule(&GetBoundCompileUnit().GetModule());
1688             function->SetParent(&GetSymbolTable()->GlobalNs());
1689             functionMap[arrayType->TypeId()] = function;
1690             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1691         }
1692         viableFunctions.Insert(function);
1693     }
1694 }
1695 
1696 class ArrayCopyAssignmentOperation public Operation
1697 {
1698 public:
1699     ArrayCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1700     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1701         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1702 private:
1703     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1704     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1705 };
1706 
1707 ArrayCopyAssignmentOperation::ArrayCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
1708 {
1709 }
1710 
1711 void ArrayCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1712     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1713 {
1714     TypeSymbol* type = arguments[0]->GetType();
1715     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->IsArrayType()) return;
1716     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1717     {
1718         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1719         GetBoundCompileUnit().FinalizeBinding(specialization);
1720     }
1721     ArrayTypeSymbol* arrayType = static_cast<ArrayTypeSymbol*>(type->RemovePointer(spanmoduleId));
1722     if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none && TypesEqual(arguments[1]->GetType()->PlainType(spanmoduleId)arrayType) || 
1723         !TypesEqual(arguments[1]->GetType()arrayType->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) && 
1724         TypesEqual(arguments[1]->GetType()->PlainType(spanmoduleId)arrayType))
1725     {
1726         FunctionSymbol* function = functionMap[arrayType->TypeId()];
1727         if (!function)
1728         {
1729             std::vector<FunctionScopeLookup> elementLookups;
1730             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1731             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1732             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1733             std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1734             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddPointer(spanmoduleId))));
1735             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddConst(spanmoduleId)->AddLvalueReference(spanmoduleId))));
1736             std::unique_ptr<BoundFunctionCall> elementCopyAssignment = ResolveOverload(U"operator="containerScopeelementLookupselementArgumentsGetBoundCompileUnit()currentFunction
1737                 spanmoduleId);
1738             FunctionSymbol* elementTypeCopyAssignment = elementCopyAssignment->GetFunctionSymbol();
1739             ArrayTypeCopyAssignment*  arrayTypeCopyAssignment = new ArrayTypeCopyAssignment(arrayTypeelementTypeCopyAssignment);
1740             arrayTypeCopyAssignment->SetTemporariesForElementTypeCopyAssignment(elementCopyAssignment->ReleaseTemporaries());
1741             function = arrayTypeCopyAssignment;
1742             function->SetModule(&GetBoundCompileUnit().GetModule());
1743             function->SetParent(&GetSymbolTable()->GlobalNs());
1744             functionMap[arrayType->TypeId()] = function;
1745             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1746         }
1747         viableFunctions.Insert(function);
1748     }
1749 }
1750 
1751 class ArrayMoveAssignmentOperation public Operation
1752 {
1753 public:
1754     ArrayMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1755     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1756         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1757 private:
1758     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1759     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1760 };
1761 
1762 ArrayMoveAssignmentOperation::ArrayMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
1763 {
1764 }
1765 
1766 void ArrayMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1767     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1768 {
1769     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1770     TypeSymbol* type = arguments[0]->GetType();
1771     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->IsArrayType()) return;
1772     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1773     {
1774         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1775         GetBoundCompileUnit().FinalizeBinding(specialization);
1776     }
1777     ArrayTypeSymbol* arrayType = static_cast<ArrayTypeSymbol*>(type->RemovePointer(spanmoduleId));
1778     if (TypesEqual(arguments[1]->GetType()arrayType->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1779     {
1780         FunctionSymbol* function = functionMap[arrayType->TypeId()];
1781         if (!function)
1782         {
1783             std::vector<FunctionScopeLookup> elementLookups;
1784             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1785             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1786             elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1787             std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1788             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddPointer(spanmoduleId))));
1789             elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(spanmoduleIdarrayType->ElementType()->AddRvalueReference(spanmoduleId))));
1790             elementArguments.back()->SetFlag(BoundExpressionFlags::bindToRvalueReference);
1791             std::unique_ptr<BoundFunctionCall> elementMoveAssignment = ResolveOverload(U"operator="containerScopeelementLookupselementArgumentsGetBoundCompileUnit()currentFunction
1792                 spanmoduleId);
1793             FunctionSymbol* elementTypeMoveAssignment = elementMoveAssignment->GetFunctionSymbol();
1794             ArrayTypeMoveAssignment* arrayTypeMoveAssignment = new ArrayTypeMoveAssignment(arrayTypeelementTypeMoveAssignment);
1795             arrayTypeMoveAssignment->SetTemporariesForElementTypeMoveAssignment(elementMoveAssignment->ReleaseTemporaries());
1796             function = arrayTypeMoveAssignment;
1797             function->SetModule(&GetBoundCompileUnit().GetModule());
1798             function->SetParent(&GetSymbolTable()->GlobalNs());
1799             functionMap[arrayType->TypeId()] = function;
1800             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1801         }
1802         viableFunctions.Insert(function);
1803     }
1804 }
1805 
1806 class ArrayElementAccessOperation public Operation
1807 {
1808 public:
1809     ArrayElementAccessOperation(BoundCompileUnit& boundCompileUnit_);
1810     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1811         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1812 private:
1813     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1814     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1815 };
1816 
1817 ArrayElementAccessOperation::ArrayElementAccessOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator[]"2boundCompileUnit_)
1818 {
1819 }
1820 
1821 void ArrayElementAccessOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1822     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1823 {
1824     TypeSymbol* leftType = arguments[0]->GetType();
1825     if (!leftType->PlainType(spanmoduleId)->IsArrayType()) return;
1826     if (leftType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1827     {
1828         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(leftType->BaseType());
1829         GetBoundCompileUnit().FinalizeBinding(specialization);
1830     }
1831     ArrayTypeSymbol* arrayType = static_cast<ArrayTypeSymbol*>(leftType->PlainType(spanmoduleId));
1832     TypeSymbol* rightType = arguments[1]->GetType();
1833     if (!rightType->PlainType(spanmoduleId)->IsIntegralType())
1834     {
1835         ArgumentMatch argumentMatch;
1836         if (!GetBoundCompileUnit().GetConversion(rightTypeGetSymbolTable()->GetTypeByName(U"long")containerScopecurrentFunctionspanmoduleIdargumentMatch))
1837         {
1838             return;
1839         }
1840     }
1841     FunctionSymbol* function = functionMap[arrayType->TypeId()];
1842     if (!function)
1843     {
1844         function = new ArrayTypeElementAccess(arrayType);
1845         function->SetModule(&GetBoundCompileUnit().GetModule());
1846         function->SetParent(&GetSymbolTable()->GlobalNs());
1847         functionMap[arrayType->TypeId()] = function;
1848         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1849     }
1850     viableFunctions.Insert(function);
1851 }
1852 
1853 class InterfaceDefaultConstructorOperation public Operation
1854 {
1855 public:
1856     InterfaceDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1857     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1858         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1859 private:
1860     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1861     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1862 };
1863 
1864 InterfaceDefaultConstructorOperation::InterfaceDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"1boundCompileUnit_)
1865 {
1866 }
1867 
1868 void InterfaceDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1869     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1870 {
1871     TypeSymbol* type = arguments[0]->GetType();
1872     if (type->PointerCount() != 1 || type->RemovePointer(spanmoduleId)->GetSymbolType() != SymbolType::interfaceTypeSymbol) return;
1873     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1874     {
1875         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1876         GetBoundCompileUnit().FinalizeBinding(specialization);
1877     }
1878     InterfaceTypeSymbol* interfaceType = static_cast<InterfaceTypeSymbol*>(type->RemovePointer(spanmoduleId));
1879     FunctionSymbol* function = functionMap[interfaceType->TypeId()];
1880     if (!function)
1881     {
1882         function = new InterfaceTypeDefaultConstructor(interfaceTypespanmoduleId);
1883         function->SetModule(&GetBoundCompileUnit().GetModule());
1884         function->SetParent(&GetSymbolTable()->GlobalNs());
1885         functionMap[interfaceType->TypeId()] = function;
1886         functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1887     }
1888     viableFunctions.Insert(function);
1889 }
1890 
1891 class InterfaceCopyConstructorOperation public Operation
1892 {
1893 public:
1894     InterfaceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1895     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1896         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1897 private:
1898     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1899     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1900 };
1901 
1902 InterfaceCopyConstructorOperation::InterfaceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
1903 {
1904 }
1905 
1906 void InterfaceCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1907     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1908 {
1909     TypeSymbol* type = arguments[0]->GetType();
1910     if (type->PointerCount() != 1 || type->RemovePointer(spanmoduleId)->GetSymbolType() != SymbolType::interfaceTypeSymbol) return;
1911     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1912     {
1913         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1914         GetBoundCompileUnit().FinalizeBinding(specialization);
1915     }
1916     InterfaceTypeSymbol* interfaceType = static_cast<InterfaceTypeSymbol*>(type->RemovePointer(spanmoduleId));
1917     
1918     if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
1919         !TypesEqual(arguments[1]->GetType()interfaceType->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) && 
1920         (TypesEqual(arguments[1]->GetType()->PlainType(spanmoduleId)interfaceType) || arguments[1]->GetType()->PlainType(spanmoduleId)->IsClassTypeSymbol()))
1921     {
1922         if (GetBoundCompileUnit().HasCopyConstructorFor(interfaceType->TypeId()))
1923         {
1924             viableFunctions.Insert(GetBoundCompileUnit().GetCopyConstructorFor(interfaceType->TypeId()));
1925             return;
1926         }
1927         FunctionSymbol* function = functionMap[interfaceType->TypeId()];
1928         if (!function)
1929         {
1930             function = new InterfaceTypeCopyConstructor(interfaceTypespanmoduleId);
1931             GetBoundCompileUnit().AddCopyConstructorToMap(interfaceType->TypeId()function);
1932             function->SetModule(&GetBoundCompileUnit().GetModule());
1933             function->SetParent(&GetSymbolTable()->GlobalNs());
1934             functionMap[interfaceType->TypeId()] = function;
1935             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1936         }
1937         viableFunctions.Insert(function);
1938     }
1939 }
1940 
1941 class InterfaceMoveConstructorOperation public Operation
1942 {
1943 public:
1944     InterfaceMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1945     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1946         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1947 private:
1948     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1949     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1950 };
1951 
1952 InterfaceMoveConstructorOperation::InterfaceMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
1953 {
1954 }
1955 
1956 void InterfaceMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1957     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
1958 {
1959     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1960     TypeSymbol* type = arguments[0]->GetType();
1961     if (type->PointerCount() != 1 || type->RemovePointer(spanmoduleId)->GetSymbolType() != SymbolType::interfaceTypeSymbol) return;
1962     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1963     {
1964         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
1965         GetBoundCompileUnit().FinalizeBinding(specialization);
1966     }
1967     InterfaceTypeSymbol* interfaceType = static_cast<InterfaceTypeSymbol*>(type->RemovePointer(spanmoduleId));
1968     if (TypesEqual(arguments[1]->GetType()interfaceType->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1969     {
1970         FunctionSymbol* function = functionMap[interfaceType->TypeId()];
1971         if (!function)
1972         {
1973             function = new InterfaceTypeMoveConstructor(interfaceTypespanmoduleId);
1974             function->SetModule(&GetBoundCompileUnit().GetModule());
1975             function->SetParent(&GetSymbolTable()->GlobalNs());
1976             functionMap[interfaceType->TypeId()] = function;
1977             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
1978         }
1979         viableFunctions.Insert(function);
1980     }
1981 }
1982 
1983 class InterfaceCopyAssignmentOperation public Operation
1984 {
1985 public:
1986     InterfaceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1987     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1988         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
1989 private:
1990     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
1991     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
1992 };
1993 
1994 InterfaceCopyAssignmentOperation::InterfaceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
1995 {
1996 }
1997 
1998 void InterfaceCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
1999     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2000 {
2001     TypeSymbol* type = arguments[0]->GetType();
2002     if (type->PointerCount() != 1 || type->RemovePointer(spanmoduleId)->GetSymbolType() != SymbolType::interfaceTypeSymbol) return;
2003     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2004     {
2005         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
2006         GetBoundCompileUnit().FinalizeBinding(specialization);
2007     }
2008     InterfaceTypeSymbol* interfaceType = static_cast<InterfaceTypeSymbol*>(type->RemovePointer(spanmoduleId));
2009     if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
2010         !TypesEqual(arguments[1]->GetType()interfaceType->AddRvalueReference(spanmoduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) && 
2011         TypesEqual(arguments[1]->GetType()->PlainType(spanmoduleId)interfaceType))
2012     {
2013         FunctionSymbol* function = functionMap[interfaceType->TypeId()];
2014         if (!function)
2015         {
2016             function = new InterfaceTypeCopyAssignment(interfaceTypespanmoduleId);
2017             function->SetModule(&GetBoundCompileUnit().GetModule());
2018             function->SetParent(&GetSymbolTable()->GlobalNs());
2019             functionMap[interfaceType->TypeId()] = function;
2020             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
2021         }
2022         viableFunctions.Insert(function);
2023     }
2024 }
2025 
2026 class InterfaceMoveAssignmentOperation public Operation
2027 {
2028 public:
2029     InterfaceMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
2030     void CollectViableFunctions(ContainerScope* containerScope_const std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2031         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
2032 private:
2033     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
2034     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
2035 };
2036 
2037 InterfaceMoveAssignmentOperation::InterfaceMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
2038 {
2039 }
2040 
2041 void InterfaceMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2042     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2043 {
2044     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
2045     TypeSymbol* type = arguments[0]->GetType();
2046     if (type->PointerCount() != 1 || type->RemovePointer(spanmoduleId)->GetSymbolType() != SymbolType::interfaceTypeSymbol) return;
2047     if (type->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2048     {
2049         ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type->BaseType());
2050         GetBoundCompileUnit().FinalizeBinding(specialization);
2051     }
2052     InterfaceTypeSymbol* interfaceType = static_cast<InterfaceTypeSymbol*>(type->RemovePointer(spanmoduleId));
2053     if (TypesEqual(arguments[1]->GetType()interfaceType->AddRvalueReference(spanmoduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
2054     {
2055         FunctionSymbol* function = functionMap[interfaceType->TypeId()];
2056         if (!function)
2057         {
2058             function = new InterfaceTypeMoveAssignment(interfaceTypespanmoduleId);
2059             function->SetModule(&GetBoundCompileUnit().GetModule());
2060             function->SetParent(&GetSymbolTable()->GlobalNs());
2061             functionMap[interfaceType->TypeId()] = function;
2062             functions.push_back(std::unique_ptr<FunctionSymbol>(function));
2063         }
2064         viableFunctions.Insert(function);
2065     }
2066 }
2067 
2068 class ClassDefaultConstructor public ConstructorSymbol
2069 {
2070 public:
2071     ClassDefaultConstructor(ClassTypeSymbol* classType_);
2072     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
2073     bool IsGeneratedFunction() const override { return true; }
2074     ClassTypeSymbol* ClassType() { return classType; }
2075     const char* ClassName() const override { return "ClassDefaultConstructor"; }
2076 private:
2077     ClassTypeSymbol* classType;
2078 };
2079 
2080 ClassDefaultConstructor::ClassDefaultConstructor(ClassTypeSymbol* classType_) :
2081     ConstructorSymbol(classType_->GetSpan()classType_->SourceModuleId()U"@constructor")classType(classType_)
2082 {
2083     SetAccess(SymbolAccess::public_);
2084     SetParent(classType);
2085     ParameterSymbol* thisParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"this");
2086     thisParam->SetType(classType->AddPointer(Span()boost::uuids::nil_uuid()));
2087     AddMember(thisParam);
2088     ComputeName();
2089 }
2090 
2091 class ClassDefaultConstructorOperation public Operation
2092 {
2093 public:
2094     ClassDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_);
2095     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2096         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
2097     bool GenerateImplementation(ClassDefaultConstructor* defaultConstructorContainerScope* containerScopeBoundFunction* currentFunctionstd::std::unique_ptr<Exception>&exception
2098         const Span& spanconst boost::uuids::uuid& moduleId);
2099 private:
2100     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
2101     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
2102 };
2103 
2104 ClassDefaultConstructorOperation::ClassDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"1boundCompileUnit_)
2105 {
2106 }
2107 
2108 void ClassDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2109     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2110 {
2111     TypeSymbol* type = arguments[0]->GetType();
2112     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
2113     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type->BaseType());
2114     if (classType->IsStatic())
2115     {
2116         exception.reset(new Exception("cannot create an instance of a static class"spanmoduleIdclassType->GetSpan()classType->SourceModuleId()));
2117         return;
2118     }
2119     if (classType->DefaultConstructor())
2120     {
2121         viableFunctions.Insert(classType->DefaultConstructor());
2122         return;
2123     }
2124     if (classType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2125     {
2126         GetBoundCompileUnit().FinalizeBinding(static_cast<ClassTemplateSpecializationSymbol*>(classType));
2127     }
2128     FunctionSymbol* function = functionMap[classType->TypeId()];
2129     if (!function)
2130     {
2131         std::unique_ptr<ClassDefaultConstructor> defaultConstructor(new ClassDefaultConstructor(classType));
2132         function = defaultConstructor.get();
2133         function->SetModule(&GetBoundCompileUnit().GetModule());
2134         function->SetParent(classType);
2135         function->SetLinkOnceOdrLinkage();
2136         functionMap[classType->TypeId()] = function;
2137         defaultConstructor->SetCompileUnit(GetBoundCompileUnit().GetCompileUnitNode());
2138         defaultConstructor->SetModule(&GetBoundCompileUnit().GetModule());
2139         if (GenerateImplementation(defaultConstructor.get()containerScopecurrentFunctionexceptionspanmoduleId))
2140         {
2141             functions.push_back(std::unique_ptr<FunctionSymbol>(defaultConstructor.release()));
2142         }
2143         else
2144         {
2145             functionMap[classType->TypeId()] = nullptr;
2146             return;
2147         }
2148     }
2149     viableFunctions.Insert(function);
2150 }
2151 
2152 bool ClassDefaultConstructorOperation::GenerateImplementation(ClassDefaultConstructor* defaultConstructorContainerScope* containerScopeBoundFunction* currentFunction
2153     std::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleId)
2154 {
2155     ClassTypeSymbol* classType = defaultConstructor->ClassType();
2156     if (classType->GroupName() == U"Matrix")
2157     {
2158         int x = 0;
2159     }
2160     try
2161     {
2162         bool nothrow = true;
2163         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&GetBoundCompileUnit()defaultConstructor));
2164         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(spanmoduleId)));
2165         if (classType->StaticConstructor())
2166         {
2167             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(
2168                 new BoundFunctionCall(spanmoduleIdclassType->StaticConstructor())))));
2169             if (!classType->StaticConstructor()->DontThrow()) nothrow = false;
2170         }
2171         if (classType->BaseClass())
2172         {
2173             std::vector<FunctionScopeLookup> baseConstructorCallLookups;
2174             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2175             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
2176             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2177             std::vector<std::std::unique_ptr<BoundExpression>>baseConstructorCallArguments;
2178             ParameterSymbol* thisParam = defaultConstructor->Parameters()[0];
2179             ArgumentMatch argumentMatch;
2180             FunctionSymbol* thisToBaseConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2181             if (!thisToBaseConversion)
2182             {
2183                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2184             }
2185             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
2186             baseConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
2187             std::unique_ptr<BoundFunctionCall> baseConstructorCall = ResolveOverload(U"@constructor"containerScopebaseConstructorCallLookupsbaseConstructorCallArgumentsGetBoundCompileUnit()
2188                 boundFunction.get()spanmoduleId);
2189             if (!baseConstructorCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2190             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(baseConstructorCall))));
2191         }
2192         if (classType->IsPolymorphic())
2193         {
2194             ParameterSymbol* thisParam = defaultConstructor->Parameters()[0];
2195             BoundExpression* classPtr = nullptr;
2196             ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
2197             if (vmtPtrHolderClass == classType)
2198             {
2199                 classPtr = new BoundParameter(spanmoduleIdthisParam);
2200             }
2201             else
2202             {
2203                 ArgumentMatch argumentMatch;
2204                 FunctionSymbol* thisToHolderConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()vmtPtrHolderClass->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2205                 if (!thisToHolderConversion)
2206                 {
2207                     throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2208                 }
2209                 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToHolderConversion);
2210             }
2211             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundSetVmtPtrStatement(std::unique_ptr<BoundExpression>(classPtr)classType)));
2212         }
2213         int n = classType->MemberVariables().size();
2214         for (int i = 0; i < n; ++i)
2215         {
2216             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
2217             std::vector<FunctionScopeLookup> memberConstructorCallLookups;
2218             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2219             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2220             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2221             std::vector<std::std::unique_ptr<BoundExpression>>memberConstructorCallArguments;
2222             BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
2223             boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIddefaultConstructor->GetThisParam())));
2224             memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
2225                 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
2226             std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor"containerScopememberConstructorCallLookupsmemberConstructorCallArguments
2227                 GetBoundCompileUnit()boundFunction.get()spanmoduleId);
2228             if (!memberConstructorCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2229             boundFunction->MoveTemporaryDestructorCallsTo(*memberConstructorCall);
2230             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(memberConstructorCall))));
2231         }
2232         GetBoundCompileUnit().AddBoundNode(std::move(boundFunction));
2233         if (nothrow)
2234         {
2235             defaultConstructor->SetNothrow();
2236         }
2237     }
2238     catch (const Exception& ex;)
2239     {
2240         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
2241         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
2242         references.insert(references.end()ex.References().begin()ex.References().end());
2243         exception.reset(new Exception("cannot create default constructor for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()spanmoduleIdreferences));
2244         return false;
2245     }
2246     return  true;
2247 }
2248 
2249 class ClassCopyConstructor public ConstructorSymbol
2250 {
2251 public:
2252     ClassCopyConstructor(ClassTypeSymbol* classType_);
2253     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
2254     bool IsGeneratedFunction() const override { return true; }
2255     ClassTypeSymbol* ClassType() { return classType; }
2256     const char* ClassName() const override { return "ClassCopyConstructor"; }
2257 private:
2258     ClassTypeSymbol* classType;
2259 };
2260 
2261 ClassCopyConstructor::ClassCopyConstructor(ClassTypeSymbol* classType_) :
2262     ConstructorSymbol(classType_->GetSpan()classType_->SourceModuleId()U"@constructor")classType(classType_)
2263 {
2264     SetAccess(SymbolAccess::public_);
2265     SetParent(classType);
2266     ParameterSymbol* thisParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"this");
2267     thisParam->SetType(classType->AddPointer(Span()boost::uuids::nil_uuid()));
2268     AddMember(thisParam);
2269     ParameterSymbol* thatParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"that");
2270     thatParam->SetType(classType->AddConst(Span()boost::uuids::nil_uuid())->AddLvalueReference(Span()boost::uuids::nil_uuid()));
2271     AddMember(thatParam);
2272     ComputeName();
2273 }
2274 
2275 class ClassCopyConstructorOperation public Operation
2276 {
2277 public:
2278     ClassCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
2279     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2280         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
2281     bool GenerateImplementation(ClassCopyConstructor* copyConstructorContainerScope* containerScopeBoundFunction* currentFunctionstd::std::unique_ptr<Exception>&exception
2282         const Span& spanconst boost::uuids::uuid& moduleId);
2283     void AddFunction(std::std::unique_ptr<FunctionSymbol>&&function){functions.push_back(std::move(function));}
2284 private:
2285     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
2286     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
2287 };
2288 
2289 ClassCopyConstructorOperation::ClassCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
2290 {
2291 }
2292 
2293 void ClassCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2294     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2295 {
2296     TypeSymbol* type = arguments[0]->GetType();
2297     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
2298     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type->BaseType());
2299     if (classType->IsStatic())
2300     {
2301         exception.reset(new Exception("cannot copy an instance of a static class"spanmoduleIdclassType->GetSpan()classType->SourceModuleId()));
2302         return;
2303     }
2304     TypeSymbol* rightType = arguments[1]->GetType()->PlainType(spanmoduleId);
2305     bool typesEqual = TypesEqual(rightTypeclassType);
2306     bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2307     bool conversionFunctionExists = false;
2308     if (!typesEqual)
2309     {
2310         ArgumentMatch argumentMatch;
2311         FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightTypeclassTypecontainerScopecurrentFunctionspanmoduleIdargumentMatch);
2312         if (conversion && conversion->GetSymbolType() == SymbolType::conversionFunctionSymbol)
2313         {
2314             conversionFunctionExists = true;
2315             if (conversion->ReturnsClassInterfaceOrClassDelegateByValue())
2316             {
2317                 bindToRvalueRef = true;
2318             }
2319         }
2320     }
2321     if (typesEqual || 
2322         (((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
2323         !TypesEqual(arguments[1]->GetType()classType->AddRvalueReference(spanmoduleId)) && !bindToRvalueRef) && (typesEqual || conversionFunctionExists)))
2324     {
2325         if (classType->CopyConstructor())
2326         {
2327             if (!classType->CopyConstructor()->IsSuppressed())
2328             {
2329                 viableFunctions.Insert(classType->CopyConstructor());
2330             }
2331             return;
2332         }
2333         if (GetBoundCompileUnit().HasCopyConstructorFor(classType->TypeId()))
2334         {
2335             viableFunctions.Insert(GetBoundCompileUnit().GetCopyConstructorFor(classType->TypeId()));
2336             return;
2337         }
2338         if (classType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2339         {
2340             GetBoundCompileUnit().FinalizeBinding(static_cast<ClassTemplateSpecializationSymbol*>(classType));
2341         }
2342         FunctionSymbol* function = functionMap[classType->TypeId()];
2343         if (!function)
2344         {
2345             std::unique_ptr<ClassCopyConstructor> copyConstructor(new ClassCopyConstructor(classType));
2346             function = copyConstructor.get();
2347             function->SetModule(&GetBoundCompileUnit().GetModule());
2348             function->SetParent(classType);
2349             function->SetLinkOnceOdrLinkage();
2350             functionMap[classType->TypeId()] = function;
2351             copyConstructor->SetCompileUnit(GetBoundCompileUnit().GetCompileUnitNode());
2352             copyConstructor->SetModule(&GetBoundCompileUnit().GetModule());
2353             if (GenerateImplementation(copyConstructor.get()containerScopecurrentFunctionexceptionspanmoduleId))
2354             {
2355                 GetBoundCompileUnit().AddCopyConstructorToMap(classType->TypeId()copyConstructor.get());
2356                 functions.push_back(std::unique_ptr<FunctionSymbol>(copyConstructor.release()));
2357             }
2358             else
2359             {
2360                 functionMap[classType->TypeId()] = nullptr;
2361                 return;
2362             }
2363         }
2364         viableFunctions.Insert(function);
2365     }
2366 }
2367 
2368 bool ClassCopyConstructorOperation::GenerateImplementation(ClassCopyConstructor* copyConstructorContainerScope* containerScopeBoundFunction* currentFunction
2369     std::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleId)
2370 {
2371     ClassTypeSymbol* classType = copyConstructor->ClassType();
2372     try
2373     {
2374         bool nothrow = true;
2375         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&GetBoundCompileUnit()copyConstructor));
2376         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(spanmoduleId)));
2377         if (classType->StaticConstructor())
2378         {
2379             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(new BoundFunctionCall(spanmoduleId
2380                 classType->StaticConstructor())))));
2381             if (!classType->StaticConstructor()->DontThrow()) nothrow = false;
2382         }
2383         if (classType->BaseClass())
2384         {
2385             std::vector<FunctionScopeLookup> baseConstructorCallLookups;
2386             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2387             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
2388             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2389             std::vector<std::std::unique_ptr<BoundExpression>>baseConstructorCallArguments;
2390             ParameterSymbol* thisParam = copyConstructor->Parameters()[0];
2391             ArgumentMatch argumentMatch;
2392             FunctionSymbol* thisToBaseConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2393             if (!thisToBaseConversion)
2394             {
2395                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2396             }
2397             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
2398             baseConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
2399             ParameterSymbol* thatParam = copyConstructor->Parameters()[1];
2400             FunctionSymbol* thatToBaseConversion = GetBoundCompileUnit().GetConversion(thatParam->GetType()classType->BaseClass()->AddConst(spanmoduleId)->AddLvalueReference(spanmoduleId)containerScope
2401                 currentFunctionspanmoduleIdargumentMatch);
2402             if (!thatToBaseConversion)
2403             {
2404                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2405             }
2406             BoundExpression* thatArgumentConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion);
2407             baseConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(thatArgumentConversion));
2408             std::unique_ptr<BoundFunctionCall> baseConstructorCall = ResolveOverload(U"@constructor"containerScopebaseConstructorCallLookupsbaseConstructorCallArgumentsGetBoundCompileUnit()
2409                 boundFunction.get()spanmoduleId);
2410             if (!baseConstructorCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2411             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(baseConstructorCall))));
2412         }
2413         if (classType->IsPolymorphic())
2414         {
2415             ParameterSymbol* thisParam = copyConstructor->Parameters()[0];
2416             BoundExpression* classPtr = nullptr;
2417             ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
2418             if (vmtPtrHolderClass == classType)
2419             {
2420                 classPtr = new BoundParameter(spanmoduleIdthisParam);
2421             }
2422             else
2423             {
2424                 ArgumentMatch argumentMatch;
2425                 FunctionSymbol* thisToHolderConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()vmtPtrHolderClass->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2426                 if (!thisToHolderConversion)
2427                 {
2428                     throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2429                 }
2430                 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToHolderConversion);
2431             }
2432             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundSetVmtPtrStatement(std::unique_ptr<BoundExpression>(classPtr)classType)));
2433         }
2434         int n = classType->MemberVariables().size();
2435         for (int i = 0; i < n; ++i)
2436         {
2437             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
2438             std::vector<FunctionScopeLookup> memberConstructorCallLookups;
2439             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2440             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2441             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2442             std::vector<std::std::unique_ptr<BoundExpression>>memberConstructorCallArguments;
2443             BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
2444             boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdcopyConstructor->GetThisParam())));
2445             memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
2446                 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
2447             ParameterSymbol* thatParam = copyConstructor->Parameters()[1];
2448             BoundMemberVariable* thatBoundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
2449             thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
2450                 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatParam->GetType()->BaseType()->AddPointer(spanmoduleId))));
2451             memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(thatBoundMemberVariable));
2452             std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor"containerScopememberConstructorCallLookupsmemberConstructorCallArguments
2453                 GetBoundCompileUnit()boundFunction.get()spanmoduleId);
2454             if (!memberConstructorCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2455             boundFunction->MoveTemporaryDestructorCallsTo(*memberConstructorCall);
2456             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(memberConstructorCall))));
2457         }
2458         GetBoundCompileUnit().AddBoundNode(std::move(boundFunction));
2459         if (nothrow)
2460         {
2461             copyConstructor->SetNothrow();
2462         }
2463     }
2464     catch (const Exception& ex;)
2465     {
2466         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
2467         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
2468         references.insert(references.end()ex.References().begin()ex.References().end());
2469         exception.reset(new Exception("cannot create copy constructor for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()spanmoduleIdreferences));
2470         return false;
2471     }
2472     return true;
2473 }
2474 
2475 class ClassMoveConstructor public ConstructorSymbol
2476 {
2477 public:
2478     ClassMoveConstructor(ClassTypeSymbol* classType_);
2479     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
2480     bool IsGeneratedFunction() const override { return true; }
2481     ClassTypeSymbol* ClassType() { return classType; }
2482     const char* ClassName() const override { return "ClassMoveConstructor"; }
2483 private:
2484     ClassTypeSymbol* classType;
2485 };
2486 
2487 ClassMoveConstructor::ClassMoveConstructor(ClassTypeSymbol* classType_) :
2488     ConstructorSymbol(classType_->GetSpan()classType_->SourceModuleId()U"@constructor")classType(classType_)
2489 {
2490     SetAccess(SymbolAccess::public_);
2491     SetParent(classType);
2492     ParameterSymbol* thisParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"this");
2493     thisParam->SetType(classType->AddPointer(Span()boost::uuids::nil_uuid()));
2494     AddMember(thisParam);
2495     ParameterSymbol* thatParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"that");
2496     thatParam->SetType(classType->AddRvalueReference(Span()boost::uuids::nil_uuid()));
2497     AddMember(thatParam);
2498     ComputeName();
2499 }
2500 
2501 class ClassMoveConstructorOperation public Operation
2502 {
2503 public:
2504     ClassMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_);
2505     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2506         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
2507     bool GenerateImplementation(ClassMoveConstructor* moveConstructorContainerScope* containerScopeBoundFunction* currentFunctionstd::std::unique_ptr<Exception>&exceptionconstSpan&span
2508         const boost::uuids::uuid& moduleId);
2509 private:
2510     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
2511     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
2512 };
2513 
2514 ClassMoveConstructorOperation::ClassMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"@constructor"2boundCompileUnit_)
2515 {
2516 }
2517 
2518 void ClassMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2519     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2520 {
2521     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
2522     TypeSymbol* type = arguments[0]->GetType();
2523     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
2524     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type->BaseType());
2525     if (classType->IsStatic())
2526     {
2527         exception.reset(new Exception("cannot move an instance of a static class"spanmoduleIdclassType->GetSpan()classType->SourceModuleId()));
2528         return;
2529     }
2530     TypeSymbol* rightType = arguments[1]->GetType()->PlainType(spanmoduleId);
2531     bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2532     bool typesEqual = TypesEqual(arguments[1]->GetType()classType->AddRvalueReference(spanmoduleId));
2533     if (!typesEqual)
2534     {
2535         ArgumentMatch argumentMatch;
2536         FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightTypeclassTypecontainerScopecurrentFunctionspanmoduleIdargumentMatch);
2537         if (conversion && conversion->GetSymbolType() == SymbolType::conversionFunctionSymbol)
2538         {
2539             if (conversion->ReturnsClassInterfaceOrClassDelegateByValue())
2540             {
2541                 bindToRvalueRef = true;
2542             }
2543         }
2544         else if (!TypesEqual(rightTypeclassType))
2545         {
2546             return;
2547         }
2548     }
2549     if (typesEqual || bindToRvalueRef)
2550     {
2551         if (classType->MoveConstructor())
2552         {
2553             viableFunctions.Insert(classType->MoveConstructor());
2554             return;
2555         }
2556         if (classType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2557         {
2558             GetBoundCompileUnit().FinalizeBinding(static_cast<ClassTemplateSpecializationSymbol*>(classType));
2559         }
2560         FunctionSymbol* function = functionMap[classType->TypeId()];
2561         if (!function)
2562         {
2563             std::unique_ptr<ClassMoveConstructor> moveConstructor(new ClassMoveConstructor(classType));
2564             function = moveConstructor.get();
2565             function->SetModule(&GetBoundCompileUnit().GetModule());
2566             function->SetParent(classType);
2567             function->SetLinkOnceOdrLinkage();
2568             functionMap[classType->TypeId()] = function;
2569             moveConstructor->SetCompileUnit(GetBoundCompileUnit().GetCompileUnitNode());
2570             moveConstructor->SetModule(&GetBoundCompileUnit().GetModule());
2571             if (GenerateImplementation(moveConstructor.get()containerScopecurrentFunctionexceptionspanmoduleId))
2572             {
2573                 functions.push_back(std::unique_ptr<FunctionSymbol>(moveConstructor.release()));
2574             }
2575             else
2576             {
2577                 functionMap[classType->TypeId()] = nullptr;
2578                 return;
2579             }
2580         }
2581         viableFunctions.Insert(function);
2582     }
2583 }
2584 
2585 bool ClassMoveConstructorOperation::GenerateImplementation(ClassMoveConstructor* moveConstructorContainerScope* containerScopeBoundFunction* currentFunction
2586     std::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleId)
2587 {
2588     ClassTypeSymbol* classType = moveConstructor->ClassType();
2589     try
2590     {
2591         bool nothrow = true;
2592         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&GetBoundCompileUnit()moveConstructor));
2593         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(spanmoduleId)));
2594         if (classType->StaticConstructor())
2595         {
2596             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(new BoundFunctionCall(spanmoduleId
2597                 classType->StaticConstructor())))));
2598             if (!classType->StaticConstructor()->DontThrow()) nothrow = false;
2599         }
2600         if (classType->BaseClass())
2601         {
2602             std::vector<FunctionScopeLookup> baseConstructorCallLookups;
2603             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2604             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
2605             baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2606             std::vector<std::std::unique_ptr<BoundExpression>>baseConstructorCallArguments;
2607             ParameterSymbol* thisParam = moveConstructor->Parameters()[0];
2608             ArgumentMatch argumentMatch;
2609             FunctionSymbol* thisToBaseConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2610             if (!thisToBaseConversion)
2611             {
2612                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2613             }
2614             std::unique_ptr<BoundExpression> baseClassPointerConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion));
2615             baseConstructorCallArguments.push_back(std::move(baseClassPointerConversion));
2616             ParameterSymbol* thatParam = moveConstructor->Parameters()[1];
2617             FunctionSymbol* thatToBaseConversion = GetBoundCompileUnit().GetConversion(thatParam->GetType()classType->BaseClass()->AddRvalueReference(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2618             if (!thatToBaseConversion)
2619             {
2620                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2621             }
2622             std::unique_ptr<BoundExpression> thatArgumentConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion));
2623             baseConstructorCallArguments.push_back(std::move(thatArgumentConversion));
2624             std::unique_ptr<BoundFunctionCall> baseConstructorCall = ResolveOverload(U"@constructor"containerScopebaseConstructorCallLookupsbaseConstructorCallArgumentsGetBoundCompileUnit()
2625                 boundFunction.get()spanmoduleId);
2626             if (!baseConstructorCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2627             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(baseConstructorCall))));
2628         }
2629         if (classType->IsPolymorphic())
2630         {
2631             ParameterSymbol* thisParam = moveConstructor->Parameters()[0];
2632             BoundExpression* classPtr = nullptr;
2633             ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
2634             if (vmtPtrHolderClass == classType)
2635             {
2636                 classPtr = new BoundParameter(spanmoduleIdthisParam);
2637             }
2638             else
2639             {
2640                 ArgumentMatch argumentMatch;
2641                 FunctionSymbol* thisToHolderConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()vmtPtrHolderClass->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2642                 if (!thisToHolderConversion)
2643                 {
2644                     throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2645                 }
2646                 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToHolderConversion);
2647             }
2648             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundSetVmtPtrStatement(std::unique_ptr<BoundExpression>(classPtr)classType)));
2649         }
2650         int n = classType->MemberVariables().size();
2651         for (int i = 0; i < n; ++i)
2652         {
2653             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
2654             std::vector<FunctionScopeLookup> memberConstructorCallLookups;
2655             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2656             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2657             memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2658             std::vector<std::std::unique_ptr<BoundExpression>>memberConstructorCallArguments;
2659             BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
2660             boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdmoveConstructor->GetThisParam())));
2661             memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
2662                 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
2663             ParameterSymbol* thatParam = moveConstructor->Parameters()[1];
2664             std::unique_ptr<BoundMemberVariable> thatBoundMemberVariable(new BoundMemberVariable(spanmoduleIdmemberVariableSymbol));
2665             thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
2666                 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatParam->GetType()->BaseType()->AddPointer(spanmoduleId))));
2667             std::vector<FunctionScopeLookup> rvalueLookups;
2668             rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2669             rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2670             std::vector<std::std::unique_ptr<BoundExpression>>rvalueArguments;
2671             rvalueArguments.push_back(std::move(thatBoundMemberVariable));
2672             std::unique_ptr<BoundFunctionCall> rvalueMemberCall = ResolveOverload(U"System.Rvalue"containerScopervalueLookupsrvalueArgumentsGetBoundCompileUnit()boundFunction.get()span
2673                 moduleId);
2674             memberConstructorCallArguments.push_back(std::move(rvalueMemberCall));
2675             std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor"containerScopememberConstructorCallLookupsmemberConstructorCallArguments
2676                 GetBoundCompileUnit()boundFunction.get()spanmoduleId);
2677             if (!memberConstructorCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2678             boundFunction->MoveTemporaryDestructorCallsTo(*memberConstructorCall);
2679             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(memberConstructorCall))));
2680         }
2681         GetBoundCompileUnit().AddBoundNode(std::move(boundFunction));
2682         if (nothrow)
2683         {
2684             moveConstructor->SetNothrow();
2685         }
2686     }
2687     catch (const Exception& ex;)
2688     {
2689         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
2690         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
2691         references.insert(references.end()ex.References().begin()ex.References().end());
2692         exception.reset(new Exception("cannot create move constructor for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()spanmoduleIdreferences));
2693         return false;
2694     }
2695     return true;
2696 }
2697 
2698 class ClassCopyAssignment public MemberFunctionSymbol
2699 {
2700 public:
2701     ClassCopyAssignment(ClassTypeSymbol* classType_TypeSymbol* voidType_);
2702     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
2703     bool IsGeneratedFunction() const override { return true; }
2704     ClassTypeSymbol* ClassType() { return classType; }
2705     const char* ClassName() const override { return "ClassCopyAssignment"; }
2706 private:
2707     ClassTypeSymbol* classType;
2708 };
2709 
2710 ClassCopyAssignment::ClassCopyAssignment(ClassTypeSymbol* classType_TypeSymbol* voidType_) :
2711     MemberFunctionSymbol(classType_->GetSpan()classType_->SourceModuleId()U"operator=")classType(classType_)
2712 {
2713     SetGroupName(U"operator=");
2714     SetAccess(SymbolAccess::public_);
2715     SetParent(classType);
2716     ParameterSymbol* thisParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"this");
2717     thisParam->SetType(classType->AddPointer(Span()boost::uuids::nil_uuid()));
2718     AddMember(thisParam);
2719     ParameterSymbol* thatParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"that");
2720     thatParam->SetType(classType->AddConst(Span()boost::uuids::nil_uuid())->AddLvalueReference(Span()boost::uuids::nil_uuid()));
2721     AddMember(thatParam);
2722     SetReturnType(voidType_);
2723     ComputeName();
2724 }
2725 
2726 class ClassCopyAssignmentOperation public Operation
2727 {
2728 public:
2729     ClassCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
2730     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2731         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
2732     bool GenerateImplementation(ClassCopyAssignment* copyAssignmentContainerScope* containerScopeBoundFunction* currentFunctionstd::std::unique_ptr<Exception>&exceptionconstSpan&span
2733         const boost::uuids::uuid& moduleId);
2734 private:
2735     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
2736     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
2737 };
2738 
2739 ClassCopyAssignmentOperation::ClassCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
2740 {
2741 }
2742 
2743 void ClassCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2744     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2745 {
2746     TypeSymbol* type = arguments[0]->GetType();
2747     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
2748     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type->BaseType());
2749     if (classType->IsStatic())
2750     {
2751         exception.reset(new Exception("cannot assign an instance of a static class"spanmoduleIdclassType->GetSpan()classType->SourceModuleId()));
2752         return;
2753     }
2754     TypeSymbol* rightType = arguments[1]->GetType()->PlainType(spanmoduleId);
2755     bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2756     bool conversionFunctionExists = false;
2757     bool typesEqual = TypesEqual(rightTypeclassType);
2758     if (!typesEqual)
2759     {
2760         ArgumentMatch argumentMatch;
2761         FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightTypeclassTypecontainerScopecurrentFunctionspanmoduleIdargumentMatch);
2762         if (conversion && conversion->GetSymbolType() == SymbolType::conversionFunctionSymbol)
2763         {
2764             conversionFunctionExists = true;
2765             if (conversion->ReturnsClassInterfaceOrClassDelegateByValue())
2766             {
2767                 bindToRvalueRef = true;
2768             }
2769         }
2770     }
2771     if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none || 
2772         !TypesEqual(arguments[1]->GetType()classType->AddRvalueReference(spanmoduleId)) && !bindToRvalueRef) && (TypesEqual(rightTypeclassType) || conversionFunctionExists))
2773     {
2774         if (classType->CopyAssignment())
2775         {
2776             viableFunctions.Insert(classType->CopyAssignment());
2777             return;
2778         }
2779         if (classType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2780         {
2781             GetBoundCompileUnit().FinalizeBinding(static_cast<ClassTemplateSpecializationSymbol*>(classType));
2782         }
2783         FunctionSymbol* function = functionMap[classType->TypeId()];
2784         if (!function)
2785         {
2786             std::unique_ptr<ClassCopyAssignment> copyAssignment(new ClassCopyAssignment(classTypeGetBoundCompileUnit().GetSymbolTable().GetTypeByName(U"void")));
2787             function = copyAssignment.get();
2788             function->SetModule(&GetBoundCompileUnit().GetModule());
2789             function->SetParent(classType);
2790             function->SetLinkOnceOdrLinkage();
2791             functionMap[classType->TypeId()] = function;
2792             copyAssignment->SetCompileUnit(GetBoundCompileUnit().GetCompileUnitNode());
2793             copyAssignment->SetModule(&GetBoundCompileUnit().GetModule());
2794             if (GenerateImplementation(copyAssignment.get()containerScopecurrentFunctionexceptionspanmoduleId))
2795             {
2796                 functions.push_back(std::unique_ptr<FunctionSymbol>(copyAssignment.release()));
2797             }
2798             else
2799             {
2800                 functionMap[classType->TypeId()] = nullptr;
2801                 return;
2802             }
2803         }
2804         viableFunctions.Insert(function);
2805     }
2806 }
2807 
2808 bool ClassCopyAssignmentOperation::GenerateImplementation(ClassCopyAssignment* copyAssignmentContainerScope* containerScopeBoundFunction* currentFunction
2809     std::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleId)
2810 {
2811     ClassTypeSymbol* classType = copyAssignment->ClassType();
2812     try
2813     {
2814         bool nothrow = true;
2815         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&GetBoundCompileUnit()copyAssignment));
2816         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(spanmoduleId)));
2817         if (classType->BaseClass())
2818         {
2819             std::vector<FunctionScopeLookup> baseAssignmentCallLookups;
2820             baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2821             baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
2822             baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2823             std::vector<std::std::unique_ptr<BoundExpression>>baseAssignmentCallArguments;
2824             ParameterSymbol* thisParam = copyAssignment->Parameters()[0];
2825             ArgumentMatch argumentMatch;
2826             FunctionSymbol* thisToBaseConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
2827             if (!thisToBaseConversion)
2828             {
2829                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2830             }
2831             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
2832             baseAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
2833             ParameterSymbol* thatParam = copyAssignment->Parameters()[1];
2834             FunctionSymbol* thatToBaseConversion = GetBoundCompileUnit().GetConversion(thatParam->GetType()classType->BaseClass()->AddConst(spanmoduleId)->AddLvalueReference(spanmoduleId)containerScope
2835                 currentFunctionspanmoduleIdargumentMatch);
2836             if (!thatToBaseConversion)
2837             {
2838                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
2839             }
2840             BoundExpression* thatArgumentConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion);
2841             baseAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(thatArgumentConversion));
2842             std::unique_ptr<BoundFunctionCall> baseAssignmentCall = ResolveOverload(U"operator="containerScopebaseAssignmentCallLookupsbaseAssignmentCallArgumentsGetBoundCompileUnit()
2843                 boundFunction.get()spanmoduleId);
2844             if (!baseAssignmentCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2845             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(baseAssignmentCall))));
2846         }
2847         int n = classType->MemberVariables().size();
2848         for (int i = 0; i < n; ++i)
2849         {
2850             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
2851             std::vector<FunctionScopeLookup> memberAssignmentCallLookups;
2852             memberAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
2853             memberAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2854             memberAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
2855             std::vector<std::std::unique_ptr<BoundExpression>>memberAssignmentCallArguments;
2856             BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
2857             boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdcopyAssignment->GetThisParam())));
2858             memberAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(
2859                 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
2860             ParameterSymbol* thatParam = copyAssignment->Parameters()[1];
2861             BoundMemberVariable* thatBoundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
2862             thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
2863                 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatParam->GetType()->BaseType()->AddPointer(spanmoduleId))));
2864             memberAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(thatBoundMemberVariable));
2865             std::unique_ptr<BoundFunctionCall> memberAssignmentCall = ResolveOverload(U"operator="containerScopememberAssignmentCallLookupsmemberAssignmentCallArguments
2866                 GetBoundCompileUnit()boundFunction.get()spanmoduleId);
2867             if (!memberAssignmentCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
2868             boundFunction->MoveTemporaryDestructorCallsTo(*memberAssignmentCall);
2869             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(memberAssignmentCall))));
2870         }
2871         GetBoundCompileUnit().AddBoundNode(std::move(boundFunction));
2872         if (nothrow)
2873         {
2874             copyAssignment->SetNothrow();
2875         }
2876     }
2877     catch (const Exception& ex;)
2878     {
2879         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
2880         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
2881         references.insert(references.end()ex.References().begin()ex.References().end());
2882         exception.reset(new Exception("cannot create copy assignment for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()spanmoduleIdreferences));
2883         return false;
2884     }
2885     return true;
2886 }
2887 
2888 class ClassMoveAssignment public MemberFunctionSymbol
2889 {
2890 public:
2891     ClassMoveAssignment(ClassTypeSymbol* classType_TypeSymbol* voidType_);
2892     SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
2893     bool IsGeneratedFunction() const override { return true; }
2894     ClassTypeSymbol* ClassType() { return classType; }
2895     const char* ClassName() const override { return "ClassMoveAssignment"; }
2896 private:
2897     ClassTypeSymbol* classType;
2898 };
2899 
2900 ClassMoveAssignment::ClassMoveAssignment(ClassTypeSymbol* classType_TypeSymbol* voidType_) :
2901     MemberFunctionSymbol(classType_->GetSpan()classType_->SourceModuleId()U"operator=")classType(classType_)
2902 {
2903     SetGroupName(U"operator=");
2904     SetAccess(SymbolAccess::public_);
2905     SetParent(classType);
2906     ParameterSymbol* thisParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"this");
2907     thisParam->SetType(classType->AddPointer(Span()boost::uuids::nil_uuid()));
2908     AddMember(thisParam);
2909     ParameterSymbol* thatParam = new ParameterSymbol(classType_->GetSpan()classType_->SourceModuleId()U"that");
2910     thatParam->SetType(classType->AddRvalueReference(Span()boost::uuids::nil_uuid()));
2911     AddMember(thatParam);
2912     SetReturnType(voidType_);
2913     ComputeName();
2914 }
2915 
2916 class ClassMoveAssignmentOperation public Operation
2917 {
2918 public:
2919     ClassMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
2920     void CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2921         ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags) override;
2922     bool GenerateImplementation(ClassMoveAssignment* moveAssignmentContainerScope* containerScopeBoundFunction* currentFunctionstd::std::unique_ptr<Exception>&exceptionconstSpan&span
2923         const boost::uuids::uuid& moduleId);
2924 private:
2925     std::unordered_map<boost::uuids::uuidFunctionSymbol*boost::boost::hash<boost::uuids::uuid>>functionMap;
2926     std::vector<std::std::unique_ptr<FunctionSymbol>>functions;
2927 };
2928 
2929 ClassMoveAssignmentOperation::ClassMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_) : Operation(U"operator="2boundCompileUnit_)
2930 {
2931 }
2932 
2933 void ClassMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
2934     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
2935 {
2936     if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
2937     TypeSymbol* type = arguments[0]->GetType();
2938     if (type->PointerCount() != 1 || !type->RemovePointer(spanmoduleId)->PlainType(spanmoduleId)->IsClassTypeSymbol()) return;
2939     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type->BaseType());
2940     if (classType->IsStatic())
2941     {
2942         exception.reset(new Exception("cannot assign an instance of a static class"spanmoduleIdclassType->GetSpan()classType->SourceModuleId()));
2943         return;
2944     }
2945     TypeSymbol* rightType = arguments[1]->GetType()->PlainType(spanmoduleId);
2946     bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2947     bool typesEqual = TypesEqual(arguments[1]->GetType()classType->AddRvalueReference(spanmoduleId));
2948     if (!typesEqual)
2949     {
2950         ArgumentMatch argumentMatch;
2951         FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightTypeclassTypecontainerScopecurrentFunctionspanmoduleIdargumentMatch);
2952         if (conversion && conversion->GetSymbolType() == SymbolType::conversionFunctionSymbol)
2953         {
2954             if (conversion->ReturnsClassInterfaceOrClassDelegateByValue())
2955             {
2956                 bindToRvalueRef = true;
2957             }
2958         }
2959     }
2960     if (typesEqual || bindToRvalueRef)
2961     {
2962         if (classType->MoveAssignment())
2963         {
2964             viableFunctions.Insert(classType->MoveAssignment());
2965             return;
2966         }
2967         if (classType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
2968         {
2969             GetBoundCompileUnit().FinalizeBinding(static_cast<ClassTemplateSpecializationSymbol*>(classType));
2970         }
2971         FunctionSymbol* function = functionMap[classType->TypeId()];
2972         if (!function)
2973         {
2974             std::unique_ptr<ClassMoveAssignment> moveAssignment(new ClassMoveAssignment(classTypeGetBoundCompileUnit().GetSymbolTable().GetTypeByName(U"void")));
2975             function = moveAssignment.get();
2976             function->SetModule(&GetBoundCompileUnit().GetModule());
2977             function->SetParent(classType);
2978             function->SetLinkOnceOdrLinkage();
2979             functionMap[classType->TypeId()] = function;
2980             moveAssignment->SetCompileUnit(GetBoundCompileUnit().GetCompileUnitNode());
2981             moveAssignment->SetModule(&GetBoundCompileUnit().GetModule());
2982             if (GenerateImplementation(moveAssignment.get()containerScopecurrentFunctionexceptionspanmoduleId))
2983             {
2984                 functions.push_back(std::unique_ptr<FunctionSymbol>(moveAssignment.release()));
2985             }
2986             else
2987             {
2988                 functionMap[classType->TypeId()] = nullptr;
2989                 return;
2990             }
2991         }
2992         viableFunctions.Insert(function);
2993     }
2994 }
2995 
2996 bool ClassMoveAssignmentOperation::GenerateImplementation(ClassMoveAssignment* moveAssignmentContainerScope* containerScopeBoundFunction* currentFunction
2997     std::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleId)
2998 {
2999     ClassTypeSymbol* classType = moveAssignment->ClassType();
3000     try
3001     {
3002         bool nothrow = true;
3003         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&GetBoundCompileUnit()moveAssignment));
3004         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(spanmoduleId)));
3005         if (classType->BaseClass())
3006         {
3007             std::vector<FunctionScopeLookup> baseAssignmentCallLookups;
3008             baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3009             baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3010             baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3011             std::vector<std::std::unique_ptr<BoundExpression>>baseAssignmentCallArguments;
3012             ParameterSymbol* thisParam = moveAssignment->Parameters()[0];
3013             ArgumentMatch argumentMatch;
3014             FunctionSymbol* thisToBaseConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
3015             if (!thisToBaseConversion)
3016             {
3017                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
3018             }
3019             std::unique_ptr<BoundExpression> baseClassPointerConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion));
3020             baseAssignmentCallArguments.push_back(std::move(baseClassPointerConversion));
3021             ParameterSymbol* thatParam = moveAssignment->Parameters()[1];
3022             FunctionSymbol* thatToBaseConversion = GetBoundCompileUnit().GetConversion(thatParam->GetType()classType->BaseClass()->AddRvalueReference(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
3023             if (!thatToBaseConversion)
3024             {
3025                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
3026             }
3027             std::unique_ptr<BoundExpression> thatArgumentConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion));
3028             baseAssignmentCallArguments.push_back(std::move(thatArgumentConversion));
3029             std::unique_ptr<BoundFunctionCall> baseAssignmentCall = ResolveOverload(U"operator="containerScopebaseAssignmentCallLookupsbaseAssignmentCallArgumentsGetBoundCompileUnit()
3030                 boundFunction.get()spanmoduleId);
3031             if (!baseAssignmentCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
3032             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(baseAssignmentCall))));
3033         }
3034         int n = classType->MemberVariables().size();
3035         for (int i = 0; i < n; ++i)
3036         {
3037             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
3038             std::unique_ptr<BoundMemberVariable> boundMemberVariable(new BoundMemberVariable(spanmoduleIdmemberVariableSymbol));
3039             boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdmoveAssignment->GetThisParam())));
3040             ParameterSymbol* thatParam = moveAssignment->Parameters()[1];
3041             std::unique_ptr<BoundMemberVariable> thatBoundMemberVariable(new BoundMemberVariable(spanmoduleIdmemberVariableSymbol));
3042             thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
3043                 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatParam->GetType()->BaseType()->AddPointer(spanmoduleId))));
3044             std::vector<FunctionScopeLookup> swapLookups;
3045             swapLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3046             swapLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3047             std::vector<std::std::unique_ptr<BoundExpression>>swapArguments;
3048             swapArguments.push_back(std::move(boundMemberVariable));
3049             swapArguments.push_back(std::move(thatBoundMemberVariable));
3050             std::unique_ptr<BoundFunctionCall> swapMemberCall = ResolveOverload(U"System.Swap"containerScopeswapLookupsswapArgumentsGetBoundCompileUnit()boundFunction.get()spanmoduleId);
3051             if (!swapMemberCall->GetFunctionSymbol()->DontThrow()) nothrow = false;
3052             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(swapMemberCall))));
3053         }
3054         GetBoundCompileUnit().AddBoundNode(std::move(boundFunction));
3055         if (nothrow)
3056         {
3057             moveAssignment->SetNothrow();
3058         }
3059     }
3060     catch (const Exception& ex;)
3061     {
3062         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
3063         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
3064         references.insert(references.end()ex.References().begin()ex.References().end());
3065         exception.reset(new Exception("cannot create move assignment for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()spanmoduleIdreferences));
3066         return false;
3067     }
3068     return true;
3069 }
3070 
3071 void GenerateDestructorImplementation(BoundClass* boundClassDestructorSymbol* destructorSymbolBoundCompileUnit& boundCompileUnitContainerScope* containerScopeBoundFunction* currentFunction
3072     const Span& spanconst boost::uuids::uuid& moduleId)
3073 {
3074     ClassTypeSymbol* classType = boundClass->GetClassTypeSymbol();
3075     try
3076     {
3077         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitdestructorSymbol));
3078         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(spanmoduleId)));
3079         if (classType->IsPolymorphic())
3080         {
3081             ParameterSymbol* thisParam = destructorSymbol->Parameters()[0];
3082             BoundExpression* classPtr = nullptr;
3083             ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
3084             if (vmtPtrHolderClass == classType)
3085             {
3086                 classPtr = new BoundParameter(spanmoduleIdthisParam);
3087             }
3088             else
3089             {
3090                 ArgumentMatch argumentMatch;
3091                 FunctionSymbol* thisToHolderConversion = boundCompileUnit.GetConversion(thisParam->GetType()vmtPtrHolderClass->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
3092                 if (!thisToHolderConversion)
3093                 {
3094                     throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
3095                 }
3096                 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToHolderConversion);
3097             }
3098             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundSetVmtPtrStatement(std::unique_ptr<BoundExpression>(classPtr)classType)));
3099         }
3100         int n = classType->MemberVariables().size();
3101         for (int i = n - 1; i >= 0; --i)
3102         {
3103             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
3104             if (memberVariableSymbol->GetType()->HasNontrivialDestructor())
3105             {
3106                 std::vector<FunctionScopeLookup> memberDestructorCallLookups;
3107                 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3108                 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->ClassInterfaceOrNsScope()));
3109                 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3110                 std::vector<std::std::unique_ptr<BoundExpression>>memberDestructorCallArguments;
3111                 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3112                 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIddestructorSymbol->GetThisParam())));
3113                 memberDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
3114                     new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3115                 std::unique_ptr<BoundFunctionCall> memberDestructorCall = ResolveOverload(U"@destructor"containerScopememberDestructorCallLookupsmemberDestructorCallArguments
3116                     boundCompileUnitboundFunction.get()spanmoduleId);
3117                 boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(memberDestructorCall)spanmoduleId)));
3118             }
3119         }
3120         if (classType->BaseClass() && classType->BaseClass()->HasNontrivialDestructor())
3121         {
3122             std::vector<FunctionScopeLookup> baseDestructorCallLookups;
3123             baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3124             baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3125             baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3126             std::vector<std::std::unique_ptr<BoundExpression>>baseDestructorCallArguments;
3127             ParameterSymbol* thisParam = destructorSymbol->Parameters()[0];
3128             ArgumentMatch argumentMatch;
3129             FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopecurrentFunctionspanmoduleIdargumentMatch);
3130             if (!thisToBaseConversion)
3131             {
3132                 throw Exception("base class conversion not found"spanmoduleIdclassType->GetSpan()classType->SourceModuleId());
3133             }
3134             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
3135             baseDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3136             std::unique_ptr<BoundFunctionCall> baseDestructorCall = ResolveOverload(U"@destructor"containerScopebaseDestructorCallLookupsbaseDestructorCallArgumentsboundCompileUnit
3137                 boundFunction.get()spanmoduleId);
3138             boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(baseDestructorCall)spanmoduleId)));
3139         }
3140         boundClass->AddMember(std::move(boundFunction));
3141     }
3142     catch (const Exception& ex;)
3143     {
3144         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
3145         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
3146         references.insert(references.end()ex.References().begin()ex.References().end());
3147         throw Exception("cannot create destructor for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()spanmoduleIdreferences);
3148     }
3149 }
3150 
3151 BoundExpression* MakeExitEntryPtr(BoundCompileUnit& boundCompileUnitContainerScope* containerScopeconst Span& spanconst boost::uuids::uuid& moduleId)
3152 {
3153     Symbol* symbol = containerScope->Lookup(U"System.ExitEntry"ScopeLookup::this_and_base_and_parent);
3154     if (symbol)
3155     {
3156         if (symbol->IsTypeSymbol())
3157         {
3158             if (symbol->GetSymbolType() == SymbolType::classGroupTypeSymbol)
3159             {
3160                 ClassGroupTypeSymbol* classGroupSymbol = static_cast<ClassGroupTypeSymbol*>(symbol);
3161                 symbol = classGroupSymbol->GetClass(0);
3162             }
3163             TypeSymbol* exitEntryType = static_cast<TypeSymbol*>(symbol);
3164             SymbolCreatorVisitor symbolCreatorVisitor(boundCompileUnit.GetSymbolTable());
3165             GlobalVariableNode globalVariableNode(spanmoduleIdSpecifiers::private_new DotNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System")
3166                 new IdentifierNode(spanmoduleIdU"ExitEntry"))
3167                 new IdentifierNode(spanmoduleIdU"exit@entry@" + ToUtf32(std::to_string(boundCompileUnit.GetNextExitEntryIndex())))boundCompileUnit.GetCompileUnitNode());
3168             globalVariableNode.Accept(symbolCreatorVisitor);
3169             TypeBinder typeBinder(boundCompileUnit);
3170             typeBinder.SetContainerScope(containerScope);
3171             globalVariableNode.Accept(typeBinder);
3172             BoundGlobalVariable* exitEntryGlobalVariable = static_cast<BoundGlobalVariable*>(typeBinder.GetBoundGlobalVariable()->Clone());
3173             return new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(exitEntryGlobalVariable)exitEntryType->AddPointer(spanmoduleId));
3174         }
3175         else
3176         {
3177             throw Exception("System.ExitEntry expected to denote a type"spanmoduleId);
3178         }
3179     }
3180     else
3181     {
3182         throw Exception("System.ExitEntry symbol not found"spanmoduleId);
3183     }
3184 }
3185 
3186 void GenerateStaticClassInitialization(StaticConstructorSymbol* staticConstructorSymbolStaticConstructorNode* staticConstructorNodeBoundCompileUnit& boundCompileUnit
3187     BoundCompoundStatement* boundCompoundStatementBoundFunction* boundFunctionContainerScope* containerScopeStatementBinder* statementBinderconst Span& spanconst boost::uuids::uuid& moduleId)
3188 {
3189     Symbol* parent = staticConstructorSymbol->Parent();
3190     Assert(parent->GetSymbolType() == SymbolType::classTypeSymbol || parent->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type symbol expected");
3191     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(parent);
3192     try
3193     {
3194         Assert(classType->InitializedVar()"initialized variable expected");
3195         std::unique_ptr<BoundIfStatement> ifStatement(new BoundIfStatement(spanmoduleIdstd::unique_ptr<BoundExpression>(new BoundMemberVariable(spanmoduleIdclassType->InitializedVar()))
3196             std::unique_ptr<BoundStatement>(new BoundReturnStatement(std::unique_ptr<BoundFunctionCall>(nullptr)spanmoduleId))std::unique_ptr<BoundStatement>(nullptr)));
3197         boundCompoundStatement->AddStatement(std::move(ifStatement));
3198         if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
3199         {
3200             IdentifierNode staticInitCriticalSection(spanmoduleIdU"System.Runtime.StaticInitCriticalSection");
3201             TypeSymbol* staticInitCriticalSectionClassType = ResolveType(&staticInitCriticalSectionboundCompileUnitcontainerScope);
3202             std::vector<FunctionScopeLookup> constructorLookups;
3203             constructorLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3204             constructorLookups.push_back(FunctionScopeLookup(ScopeLookup::this_staticInitCriticalSectionClassType->ClassInterfaceOrNsScope()));
3205             constructorLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3206             std::vector<std::std::unique_ptr<BoundExpression>>constructorArguments;
3207             constructorArguments.push_back(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(
3208                 new BoundLocalVariable(spanmoduleIdstaticConstructorSymbol->CreateTemporary(staticInitCriticalSectionClassTypespanmoduleId)))
3209                 staticInitCriticalSectionClassType->AddPointer(spanmoduleId))));
3210             constructorArguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new UuidValue(spanmoduleId
3211                 boundCompileUnit.Install(classType->TypeId())))boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3212             std::unique_ptr<BoundConstructionStatement> constructionStatement(new BoundConstructionStatement(
3213                 ResolveOverload(U"@constructor"containerScopeconstructorLookupsconstructorArgumentsboundCompileUnitboundFunctionspanmoduleId)spanmoduleId));
3214             boundCompoundStatement->AddStatement(std::move(constructionStatement));
3215             std::unique_ptr<BoundIfStatement> ifStatement2(new BoundIfStatement(spanmoduleIdstd::unique_ptr<BoundExpression>(new BoundMemberVariable(spanmoduleIdclassType->InitializedVar()))
3216                 std::unique_ptr<BoundStatement>(new BoundReturnStatement(std::unique_ptr<BoundFunctionCall>(nullptr)spanmoduleId))std::unique_ptr<BoundStatement>(nullptr)));
3217             boundCompoundStatement->AddStatement(std::move(ifStatement2));
3218         }
3219         std::vector<FunctionScopeLookup> assignmentLookups;
3220         assignmentLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3221         assignmentLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3222         std::vector<std::std::unique_ptr<BoundExpression>>assignmentArguments;
3223         assignmentArguments.push_back(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(new BoundMemberVariable(spanmoduleIdclassType->InitializedVar()))
3224             classType->InitializedVar()->GetType()->AddPointer(spanmoduleId))));
3225         assignmentArguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new BoolValue(spanmoduleIdtrue))
3226             boundCompileUnit.GetSymbolTable().GetTypeByName(U"bool"))));
3227         std::unique_ptr<BoundAssignmentStatement> assignmentStatement(new BoundAssignmentStatement(
3228             ResolveOverload(U"operator="containerScopeassignmentLookupsassignmentArgumentsboundCompileUnitboundFunctionspanmoduleId)spanmoduleId));
3229         boundCompoundStatement->AddStatement(std::move(assignmentStatement));
3230         ClassTypeSymbol* baseClass = classType->BaseClass();
3231         if (baseClass)
3232         {
3233             if (baseClass->StaticConstructor())
3234             {
3235                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(
3236                     new BoundFunctionCall(spanmoduleIdbaseClass->StaticConstructor())))));
3237             }
3238         }
3239         std::unordered_map<std::u32stringMemberInitializerNode*> memberInitializerMap;
3240         int n = staticConstructorNode->Initializers().Count();
3241         for (int i = 0; i < n; ++i)
3242         {
3243             InitializerNode* initializer = staticConstructorNode->Initializers()[i];
3244             if (initializer->GetNodeType() == NodeType::thisInitializerNode)
3245             {
3246                 throw Exception("static constructor cannot have 'this' initializers"initializer->GetSpan()initializer->ModuleId());
3247             }
3248             else if (initializer->GetNodeType() == NodeType::baseInitializerNode)
3249             {
3250                 throw Exception("static constructor cannot have 'base' initializers"initializer->GetSpan()initializer->ModuleId());
3251             }
3252             else if (initializer->GetNodeType() == NodeType::memberInitializerNode)
3253             {
3254                 MemberInitializerNode* memberInitializer = static_cast<MemberInitializerNode*>(initializer);
3255                 std::u32string memberName = memberInitializer->MemberId()->Str();
3256                 auto it = memberInitializerMap.find(memberName);
3257                 if (it != memberInitializerMap.cend())
3258                 {
3259                     throw Exception("already has initializer for member variable '" + ToUtf8(memberName) + "'"initializer->GetSpan()initializer->ModuleId());
3260                 }
3261                 memberInitializerMap[memberName] = memberInitializer;
3262             }
3263         }
3264         int nm = classType->StaticMemberVariables().size();
3265         for (int i = 0; i < nm; ++i)
3266         {
3267             MemberVariableSymbol* memberVariableSymbol = classType->StaticMemberVariables()[i];
3268             auto it = memberInitializerMap.find(memberVariableSymbol->Name());
3269             if (it != memberInitializerMap.cend())
3270             {
3271                 MemberInitializerNode* memberInitializer = it->second;
3272                 memberInitializerMap.erase(memberInitializer->MemberId()->Str());
3273                 std::vector<FunctionScopeLookup> lookups;
3274                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3275                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3276                 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3277                 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3278                 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3279                 std::unique_ptr<BoundExpression> addrOfBoundMemberVariable(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)
3280                     boundMemberVariable->GetType()->AddPointer(spanmoduleId)));
3281                 std::unique_ptr<BoundExpression> addrOfBoundMemberVariable2;
3282                 ClassTypeSymbol* memberVariableClassTypeWithDestructor = nullptr;
3283                 if (memberVariableSymbol->GetType()->HasNontrivialDestructor())
3284                 {
3285                     addrOfBoundMemberVariable2.reset(addrOfBoundMemberVariable->Clone());
3286                     memberVariableClassTypeWithDestructor = static_cast<ClassTypeSymbol*>(memberVariableSymbol->GetType()->BaseType());
3287                 }
3288                 arguments.push_back(std::move(addrOfBoundMemberVariable));
3289                 int n = memberInitializer->Arguments().Count();
3290                 for (int i = 0; i < n; ++i)
3291                 {
3292                     Node* argumentNode = memberInitializer->Arguments()[i];
3293                     std::unique_ptr<BoundExpression> argument = BindExpression(argumentNodeboundCompileUnitboundFunctioncontainerScopestatementBinder);
3294                     arguments.push_back(std::move(argument));
3295                 }
3296                 std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunction
3297                     spanmoduleId);
3298                 boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3299                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3300                 if (memberVariableClassTypeWithDestructor)
3301                 {
3302                     if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
3303                     {
3304                         std::vector<FunctionScopeLookup> enqueueLookups;
3305                         enqueueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3306                         enqueueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3307                         std::vector<std::std::unique_ptr<BoundExpression>>enqueueArguments;
3308                         enqueueArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::unique_ptr<BoundExpression>(new BoundFunctionPtr(spanmoduleId
3309                             memberVariableClassTypeWithDestructor->Destructor()boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId)))
3310                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3311                         enqueueArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2)
3312                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3313                         const char32_t* enqueueDestructorFunction = U"RtEnqueueDestruction";
3314                         std::unique_ptr<BoundFunctionCall> enqueueDestructorCall = ResolveOverload(enqueueDestructorFunctioncontainerScopeenqueueLookupsenqueueArgumentsboundCompileUnit
3315                             boundFunctionspanmoduleId);
3316                         boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(enqueueDestructorCall))));
3317                     }
3318                     else if (GetBackEnd() == BackEnd::cmsx)
3319                     {
3320                         std::vector<FunctionScopeLookup> atExitLookups;
3321                         atExitLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3322                         atExitLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3323                         std::vector<std::std::unique_ptr<BoundExpression>>atExitArguments;
3324                         atExitArguments.push_back(std::unique_ptr<BoundExpression>(MakeExitEntryPtr(boundCompileUnitcontainerScopespanmoduleId)));
3325                         atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::unique_ptr<BoundExpression>(new BoundFunctionPtr(spanmoduleId
3326                             memberVariableClassTypeWithDestructor->Destructor()boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId)))
3327                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3328                         atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2)
3329                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3330                         const char32_t* atExitFunction = U"at_exit";
3331                         std::unique_ptr<BoundFunctionCall> atExitCall = ResolveOverload(atExitFunctioncontainerScopeatExitLookupsatExitArgumentsboundCompileUnit
3332                             boundFunctionspanmoduleId);
3333                         boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(atExitCall))));
3334                     }
3335                 }
3336             }
3337             else
3338             {
3339                 std::vector<FunctionScopeLookup> lookups;
3340                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3341                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3342                 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3343                 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3344                 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3345                 std::unique_ptr<BoundExpression> addrOfBoundMemberVariable(
3346                     new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId)));
3347                 std::unique_ptr<BoundExpression> addrOfBoundMemberVariable2;
3348                 ClassTypeSymbol* memberVariableClassTypeWithDestructor = nullptr;
3349                 if (memberVariableSymbol->GetType()->HasNontrivialDestructor())
3350                 {
3351                     addrOfBoundMemberVariable2.reset(addrOfBoundMemberVariable->Clone());
3352                     memberVariableClassTypeWithDestructor = static_cast<ClassTypeSymbol*>(memberVariableSymbol->GetType()->BaseType());
3353                 }
3354                 arguments.push_back(std::move(addrOfBoundMemberVariable));
3355                 std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunction
3356                     spanmoduleId);
3357                 boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3358                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3359                 if (memberVariableClassTypeWithDestructor)
3360                 {
3361                     if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
3362                     {
3363                         std::vector<FunctionScopeLookup> enqueueLookups;
3364                         enqueueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3365                         enqueueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3366                         std::vector<std::std::unique_ptr<BoundExpression>>enqueueArguments;
3367                         enqueueArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::unique_ptr<BoundExpression>(new BoundFunctionPtr(spanmoduleId
3368                             memberVariableClassTypeWithDestructor->Destructor()boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId)))
3369                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3370                         enqueueArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2)
3371                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3372                         const char32_t* enqueueDestructorFunction = U"RtEnqueueDestruction";
3373                         std::unique_ptr<BoundFunctionCall> enqueueDestructorCall = ResolveOverload(enqueueDestructorFunctioncontainerScopeenqueueLookupsenqueueArgumentsboundCompileUnit
3374                             boundFunctionspanmoduleId);
3375                         boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(enqueueDestructorCall))));
3376                     }
3377                     else if (GetBackEnd() == BackEnd::cmsx)
3378                     {
3379                         std::vector<FunctionScopeLookup> atExitLookups;
3380                         atExitLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3381                         atExitLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3382                         std::vector<std::std::unique_ptr<BoundExpression>>atExitArguments;
3383                         atExitArguments.push_back(std::unique_ptr<BoundExpression>(MakeExitEntryPtr(boundCompileUnitcontainerScopespanmoduleId)));
3384                         atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::unique_ptr<BoundExpression>(new BoundFunctionPtr(spanmoduleId
3385                             memberVariableClassTypeWithDestructor->Destructor()boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId)))
3386                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3387                         atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2)
3388                             boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId))));
3389                         const char32_t* atExitFunction = U"at_exit";
3390                         std::unique_ptr<BoundFunctionCall> atExitCall = ResolveOverload(atExitFunctioncontainerScopeatExitLookupsatExitArgumentsboundCompileUnit
3391                             boundFunctionspanmoduleId);
3392                         boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(atExitCall))));
3393                     }
3394                 }
3395             }
3396         }
3397     }
3398     catch (const Exception& ex;)
3399     {
3400         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
3401         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
3402         references.insert(references.end()ex.References().begin()ex.References().end());
3403         throw Exception("could not generate static initialization for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()
3404             staticConstructorNode->GetSpan()staticConstructorNode->ModuleId()references);
3405     }
3406 }
3407 
3408 void GenerateClassInitialization(ConstructorSymbol* constructorSymbolConstructorNode* constructorNodeBoundCompoundStatement* boundCompoundStatementBoundFunction* boundFunction
3409     BoundCompileUnit& boundCompileUnitContainerScope* containerScopeStatementBinder* statementBinderbool generateDefaultconst Span& spanconst boost::uuids::uuid& moduleId)
3410 {
3411     Symbol* parent = constructorSymbol->Parent();
3412     Assert(parent->GetSymbolType() == SymbolType::classTypeSymbol || parent->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type symbol expected");
3413     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(parent);
3414     if (generateDefault)
3415     {
3416         if (classType->IsStatic())
3417         {
3418             throw Exception("cannot create default initialization for class '" + ToUtf8(classType->FullName()) + "'. Reason: class is static"spanmoduleId);
3419         }
3420     }
3421     try
3422     {
3423         if (classType->StaticConstructor())
3424         {
3425             boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(new BoundFunctionCall(spanmoduleId
3426                 classType->StaticConstructor())))));
3427         }
3428         ParameterSymbol* thisParam = constructorSymbol->GetThisParam();
3429         Assert(thisParam"this parameter expected");
3430         ThisInitializerNode* thisInitializer = nullptr;
3431         BaseInitializerNode* baseInitializer = nullptr;
3432         std::unordered_map<std::u32stringMemberInitializerNode*> memberInitializerMap;
3433         int ni = constructorNode->Initializers().Count();
3434         for (int i = 0; i < ni; ++i)
3435         {
3436             InitializerNode* initializer = constructorNode->Initializers()[i];
3437             if (initializer->GetNodeType() == NodeType::thisInitializerNode)
3438             {
3439                 if (thisInitializer)
3440                 {
3441                     throw Exception("already has 'this' initializer"initializer->GetSpan()initializer->ModuleId());
3442                 }
3443                 else if (baseInitializer)
3444                 {
3445                     throw Exception("cannot have both 'this' and 'base' initializer"initializer->GetSpan()initializer->ModuleId());
3446                 }
3447                 thisInitializer = static_cast<ThisInitializerNode*>(initializer);
3448             }
3449             else if (initializer->GetNodeType() == NodeType::baseInitializerNode)
3450             {
3451                 if (baseInitializer)
3452                 {
3453                     throw Exception("already has 'base' initializer"initializer->GetSpan()initializer->ModuleId());
3454                 }
3455                 else if (thisInitializer)
3456                 {
3457                     throw Exception("cannot have both 'this' and 'base' initializer"initializer->GetSpan()initializer->ModuleId());
3458                 }
3459                 baseInitializer = static_cast<BaseInitializerNode*>(initializer);
3460             }
3461             else if (initializer->GetNodeType() == NodeType::memberInitializerNode)
3462             {
3463                 MemberInitializerNode* memberInitializer = static_cast<MemberInitializerNode*>(initializer);
3464                 std::u32string memberName = memberInitializer->MemberId()->Str();
3465                 auto it = memberInitializerMap.find(memberName);
3466                 if (it != memberInitializerMap.cend())
3467                 {
3468                     throw Exception("already has initializer for member variable '" + ToUtf8(memberName) + "'"initializer->GetSpan()initializer->ModuleId());
3469                 }
3470                 memberInitializerMap[memberName] = memberInitializer;
3471             }
3472         }
3473         if (thisInitializer)
3474         {
3475             std::vector<FunctionScopeLookup> lookups;
3476             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3477             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->GetContainerScope()));
3478             lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3479             std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3480             arguments.push_back(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3481             int n = thisInitializer->Arguments().Count();
3482             for (int i = 0; i < n; ++i)
3483             {
3484                 Node* argumentNode = thisInitializer->Arguments()[i];
3485                 std::unique_ptr<BoundExpression> argument = BindExpression(argumentNodeboundCompileUnitboundFunctioncontainerScopestatementBinder);
3486                 arguments.push_back(std::move(argument));
3487             }
3488             OverloadResolutionFlags flags = OverloadResolutionFlags::none;
3489             if (!constructorSymbol->IsMoveConstructor())
3490             {
3491                 flags = flags | OverloadResolutionFlags::noRvalueRef;
3492             }
3493             std::unique_ptr<Exception> exception;
3494             std::vector<TypeSymbol*> templateArgumentTypes;
3495             std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunctionspanmoduleId
3496                 flagstemplateArgumentTypesexception);
3497             boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3498             boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3499         }
3500         else if (baseInitializer)
3501         {
3502             if (!classType->BaseClass())
3503             {
3504                 throw Exception("class '" + ToUtf8(classType->FullName()) + "' does not have a base class"constructorNode->GetSpan()constructorNode->ModuleId()
3505                     classType->GetSpan()classType->SourceModuleId());
3506             }
3507             std::vector<FunctionScopeLookup> lookups;
3508             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3509             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3510             lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3511             std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3512             ArgumentMatch argumentMatch;
3513             FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopeboundFunction
3514                 spanmoduleIdargumentMatch);
3515             if (!thisToBaseConversion)
3516             {
3517                 throw Exception("base class conversion not found"constructorNode->GetSpan()constructorNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3518             }
3519             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
3520             arguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3521             int n = baseInitializer->Arguments().Count();
3522             for (int i = 0; i < n; ++i)
3523             {
3524                 Node* argumentNode = baseInitializer->Arguments()[i];
3525                 std::unique_ptr<BoundExpression> argument = BindExpression(argumentNodeboundCompileUnitboundFunctioncontainerScopestatementBinder);
3526                 arguments.push_back(std::move(argument));
3527             }
3528             OverloadResolutionFlags flags = OverloadResolutionFlags::none;
3529             if (!constructorSymbol->IsMoveConstructor())
3530             {
3531                 flags = flags | OverloadResolutionFlags::noRvalueRef;
3532             }
3533             std::unique_ptr<Exception> exception;
3534             std::vector<TypeSymbol*> templateArgumentTypes;
3535             std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunctionspanmoduleId
3536                 flagstemplateArgumentTypesexception);
3537             boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3538             boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3539         }
3540         else if (classType->BaseClass())
3541         {
3542             std::vector<FunctionScopeLookup> lookups;
3543             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3544             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3545             lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3546             std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3547             ArgumentMatch argumentMatch;
3548             FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopeboundFunction
3549                 spanmoduleIdargumentMatch);
3550             if (!thisToBaseConversion)
3551             {
3552                 throw Exception("base class conversion not found"constructorNode->GetSpan()constructorNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3553             }
3554             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
3555             arguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3556             bool copyConstructor = constructorSymbol->IsCopyConstructor();
3557             if (copyConstructor)
3558             {
3559                 ParameterSymbol* thatParam = constructorSymbol->Parameters()[1];
3560                 ArgumentMatch argumentMatch;
3561                 FunctionSymbol* thatToBaseConversion = boundCompileUnit.GetConversion(thatParam->GetType()
3562                     classType->BaseClass()->AddConst(spanmoduleId)->AddLvalueReference(spanmoduleId)containerScopeboundFunctionspanmoduleIdargumentMatch);
3563                 if (!thatToBaseConversion)
3564                 {
3565                     throw Exception("base class conversion not found"constructorNode->GetSpan()constructorNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3566                 }
3567                 BoundExpression* baseClassReferenceConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion);
3568                 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassReferenceConversion));
3569             }
3570             OverloadResolutionFlags flags = OverloadResolutionFlags::none;
3571             if (!constructorSymbol->IsMoveConstructor())
3572             {
3573                 flags = flags | OverloadResolutionFlags::noRvalueRef;
3574             }
3575             std::unique_ptr<Exception> exception;
3576             std::vector<TypeSymbol*> templateArgumentTypes;
3577             std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunctionspanmoduleId
3578                 flagstemplateArgumentTypesexception);
3579             boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3580             boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3581         }
3582         if (classType->IsPolymorphic() && !thisInitializer)
3583         {
3584             BoundExpression* classPtr = nullptr;
3585             ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
3586             if (vmtPtrHolderClass == classType)
3587             {
3588                 classPtr = new BoundParameter(spanmoduleIdthisParam);
3589             }
3590             else
3591             {
3592                 ArgumentMatch argumentMatch;
3593                 FunctionSymbol* thisToHolderConversion = boundCompileUnit.GetConversion(thisParam->GetType()vmtPtrHolderClass->AddPointer(spanmoduleId)containerScopeboundFunction
3594                     spanmoduleIdargumentMatch);
3595                 if (!thisToHolderConversion)
3596                 {
3597                     throw Exception("base class conversion not found"constructorNode->GetSpan()constructorNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3598                 }
3599                 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToHolderConversion);
3600             }
3601             boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundSetVmtPtrStatement(std::unique_ptr<BoundExpression>(classPtr)classType)));
3602         }
3603         int nm = classType->MemberVariables().size();
3604         for (int i = 0; i < nm; ++i)
3605         {
3606             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
3607             auto it = memberInitializerMap.find(memberVariableSymbol->Name());
3608             if (it != memberInitializerMap.cend())
3609             {
3610                 MemberInitializerNode* memberInitializer = it->second;
3611                 memberInitializerMap.erase(memberInitializer->MemberId()->Str());
3612                 std::vector<FunctionScopeLookup> lookups;
3613                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3614                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3615                 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3616                 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3617                 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3618                 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3619                 arguments.push_back(std::unique_ptr<BoundExpression>(
3620                     new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3621                 int n = memberInitializer->Arguments().Count();
3622                 for (int i = 0; i < n; ++i)
3623                 {
3624                     Node* argumentNode = memberInitializer->Arguments()[i];
3625                     std::unique_ptr<BoundExpression> argument = BindExpression(argumentNodeboundCompileUnitboundFunctioncontainerScopestatementBinder);
3626                     arguments.push_back(std::move(argument));
3627                 }
3628                 OverloadResolutionFlags flags = OverloadResolutionFlags::none;
3629                 std::unique_ptr<Exception> exception;
3630                 std::vector<TypeSymbol*> templateArgumentTypes;
3631                 std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunctionspanmoduleId
3632                     flagstemplateArgumentTypesexception);
3633                 boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3634                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3635             }
3636             else if (!thisInitializer)
3637             {
3638                 if (constructorSymbol->IsCopyConstructor())
3639                 {
3640                     std::vector<FunctionScopeLookup> lookups;
3641                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3642                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3643                     lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3644                     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3645                     BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3646                     boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3647                     arguments.push_back(std::unique_ptr<BoundExpression>(
3648                         new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3649                     CloneContext cloneContext;
3650                     DotNode thatMemberVarNode(spanmoduleIdconstructorNode->Parameters()[0]->Clone(cloneContext)
3651                         new IdentifierNode(spanmoduleIdmemberVariableSymbol->Name()));
3652                     std::unique_ptr<BoundExpression> thatMemberVarArgument = BindExpression(&thatMemberVarNodeboundCompileUnitboundFunctioncontainerScopestatementBinder);
3653                     arguments.push_back(std::move(thatMemberVarArgument));
3654                     std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunction
3655                         spanmoduleId);
3656                     boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3657                     boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3658                 }
3659                 else if (constructorSymbol->IsMoveConstructor())
3660                 {
3661                     std::vector<FunctionScopeLookup> lookups;
3662                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3663                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3664                     lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3665                     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3666                     BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3667                     boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3668                     arguments.push_back(std::unique_ptr<BoundExpression>(
3669                         new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3670                     ParameterSymbol* thatParam = constructorSymbol->Parameters()[1];
3671                     std::unique_ptr<BoundMemberVariable> thatBoundMemberVariable(new BoundMemberVariable(spanmoduleIdmemberVariableSymbol));
3672                     thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
3673                         new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(
3674                             new BoundParameter(spanmoduleIdthatParam))thatParam->GetType()->BaseType()->AddPointer(spanmoduleId))));
3675                     std::vector<FunctionScopeLookup> rvalueLookups;
3676                     rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3677                     rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3678                     std::vector<std::std::unique_ptr<BoundExpression>>rvalueArguments;
3679                     rvalueArguments.push_back(std::move(thatBoundMemberVariable));
3680                     std::unique_ptr<BoundFunctionCall> rvalueMemberCall = ResolveOverload(U"System.Rvalue"containerScopervalueLookupsrvalueArgumentsboundCompileUnitboundFunction
3681                         spanmoduleId);
3682                     arguments.push_back(std::move(rvalueMemberCall));
3683                     std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunction
3684                         spanmoduleId);
3685                     boundFunction->MoveTemporaryDestructorCallsTo(*memberConstructorCall);
3686                     boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(memberConstructorCall))));
3687                 }
3688                 else
3689                 {
3690                     std::vector<FunctionScopeLookup> lookups;
3691                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3692                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3693                     lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3694                     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3695                     BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3696                     boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3697                     arguments.push_back(std::unique_ptr<BoundExpression>(
3698                         new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3699                     OverloadResolutionFlags flags = OverloadResolutionFlags::none;
3700                     if (!constructorSymbol->IsMoveConstructor())
3701                     {
3702                         flags = flags | OverloadResolutionFlags::noRvalueRef;
3703                     }
3704                     std::unique_ptr<Exception> exception;
3705                     std::vector<TypeSymbol*> templateArgumentTypes;
3706                     std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopelookupsargumentsboundCompileUnitboundFunctionspanmoduleId
3707                         flagstemplateArgumentTypesexception);
3708                     boundFunction->MoveTemporaryDestructorCallsTo(*constructorCall);
3709                     boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(constructorCall))));
3710                 }
3711             }
3712         }
3713         if (!memberInitializerMap.empty())
3714         {
3715             MemberInitializerNode* initializer = memberInitializerMap.begin()->second;
3716             throw Exception("no member variable found for initializer named '" + ToUtf8(initializer->MemberId()->Str()) + "'"initializer->GetSpan()initializer->ModuleId()
3717                 classType->GetSpan()classType->SourceModuleId());
3718         }
3719     }
3720     catch (const Exception& ex;)
3721     {
3722         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
3723         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
3724         references.insert(references.end()ex.References().begin()ex.References().end());
3725         throw Exception("could not generate initialization for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()constructorNode->GetSpan()constructorNode->ModuleId()
3726             references);
3727     }
3728 }
3729 
3730 void GenerateClassAssignment(MemberFunctionSymbol* assignmentFunctionSymbolMemberFunctionNode* assignmentNodeBoundCompoundStatement* boundCompoundStatementBoundFunction* boundFunction
3731     BoundCompileUnit& boundCompileUnitContainerScope* containerScopeStatementBinder* statementBinderbool generateDefaultconst Span& spanconst boost::uuids::uuid& moduleId)
3732 {
3733     Symbol* parent = assignmentFunctionSymbol->Parent();
3734     Assert(parent->GetSymbolType() == SymbolType::classTypeSymbol || parent->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type symbol expected");
3735     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(parent);
3736     if (generateDefault)
3737     {
3738         if (classType->IsStatic())
3739         {
3740             throw Exception("cannot create default assigment for class '" + ToUtf8(classType->FullName()) + "'. Reason: class is static"spanmoduleId);
3741         }
3742     }
3743     try
3744     {
3745         ParameterSymbol* thisParam = assignmentFunctionSymbol->GetThisParam();
3746         Assert(thisParam"this parameter expected");
3747         if (assignmentFunctionSymbol->IsCopyAssignment())
3748         {
3749             if (classType->BaseClass())
3750             {
3751                 std::vector<FunctionScopeLookup> lookups;
3752                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3753                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3754                 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3755                 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3756                 ArgumentMatch argumentMatch;
3757                 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopeboundFunction
3758                     spanmoduleIdargumentMatch);
3759                 if (!thisToBaseConversion)
3760                 {
3761                     throw Exception("base class conversion not found"assignmentNode->GetSpan()assignmentNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3762                 }
3763                 BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
3764                 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3765                 ParameterSymbol* thatParam = assignmentFunctionSymbol->Parameters()[1];
3766                 FunctionSymbol* thatToBaseConversion = boundCompileUnit.GetConversion(thatParam->GetType()
3767                     classType->BaseClass()->AddConst(spanmoduleId)->AddLvalueReference(spanmoduleId)containerScopeboundFunctionspanmoduleIdargumentMatch);
3768                 if (!thatToBaseConversion)
3769                 {
3770                     throw Exception("base class conversion not found"assignmentNode->GetSpan()assignmentNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3771                 }
3772                 BoundExpression* baseClassReferenceConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion);
3773                 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassReferenceConversion));
3774                 std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator="containerScopelookupsargumentsboundCompileUnitboundFunction
3775                     spanmoduleId);
3776                 boundFunction->MoveTemporaryDestructorCallsTo(*assignmentCall);
3777                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(assignmentCall))));
3778             }
3779             if (generateDefault)
3780             {
3781                 int n = classType->MemberVariables().size();
3782                 for (int i = 0; i < n; ++i)
3783                 {
3784                     MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
3785                     std::vector<FunctionScopeLookup> lookups;
3786                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3787                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3788                     lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3789                     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3790                     BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3791                     boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3792                     arguments.push_back(std::unique_ptr<BoundExpression>(
3793                         new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3794                     CloneContext cloneContext;
3795                     DotNode thatMemberVarNode(spanmoduleIdassignmentNode->Parameters()[0]->Clone(cloneContext)
3796                         new IdentifierNode(spanmoduleIdmemberVariableSymbol->Name()));
3797                     std::unique_ptr<BoundExpression> thatMemberVarArgument = BindExpression(&thatMemberVarNodeboundCompileUnitboundFunctioncontainerScopestatementBinder);
3798                     arguments.push_back(std::move(thatMemberVarArgument));
3799                     std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator="containerScopelookupsargumentsboundCompileUnitboundFunction
3800                         spanmoduleId);
3801                     boundFunction->MoveTemporaryDestructorCallsTo(*assignmentCall);
3802                     boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(assignmentCall))));
3803                 }
3804             }
3805         }
3806         else if (assignmentFunctionSymbol->IsMoveAssignment())
3807         {
3808             if (classType->BaseClass())
3809             {
3810                 std::vector<FunctionScopeLookup> lookups;
3811                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3812                 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3813                 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3814                 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3815                 ArgumentMatch argumentMatch;
3816                 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScope
3817                     boundFunctionspanmoduleIdargumentMatch);
3818                 if (!thisToBaseConversion)
3819                 {
3820                     throw Exception("base class conversion not found"assignmentNode->GetSpan()assignmentNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3821                 }
3822                 BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
3823                 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3824                 ParameterSymbol* thatParam = assignmentFunctionSymbol->Parameters()[1];
3825                 FunctionSymbol* thatToBaseConversion = boundCompileUnit.GetConversion(thatParam->GetType()
3826                     classType->BaseClass()->AddRvalueReference(spanmoduleId)containerScopeboundFunctionspanmoduleIdargumentMatch);
3827                 if (!thatToBaseConversion)
3828                 {
3829                     throw Exception("base class conversion not found"assignmentNode->GetSpan()assignmentNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3830                 }
3831                 BoundExpression* baseClassReferenceConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthatParam))thatToBaseConversion);
3832                 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassReferenceConversion));
3833                 std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator="containerScopelookupsargumentsboundCompileUnitboundFunction
3834                     spanmoduleId);
3835                 boundFunction->MoveTemporaryDestructorCallsTo(*assignmentCall);
3836                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(assignmentCall))));
3837             }
3838             if (generateDefault)
3839             {
3840                 int n = classType->MemberVariables().size();
3841                 for (int i = 0; i < n; ++i)
3842                 {
3843                     MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
3844                     std::vector<FunctionScopeLookup> lookups;
3845                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3846                     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3847                     lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3848                     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3849                     BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3850                     boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam)));
3851                     arguments.push_back(std::unique_ptr<BoundExpression>(boundMemberVariable));
3852                     BoundMemberVariable* thatBoundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3853                     ParameterSymbol* thatParam = assignmentFunctionSymbol->Parameters()[1];
3854                     TypeSymbol* thatPtrType = thatParam->GetType()->RemoveReference(spanmoduleId)->AddPointer(spanmoduleId);
3855                     thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(
3856                         new BoundParameter(spanmoduleIdthatParam))thatPtrType)));
3857                     arguments.push_back(std::unique_ptr<BoundExpression>(thatBoundMemberVariable));
3858                     std::unique_ptr<BoundFunctionCall> swapCall = ResolveOverload(U"System.Swap"containerScopelookupsargumentsboundCompileUnitboundFunctionspanmoduleId);
3859                     boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::move(swapCall))));
3860                 }
3861             }
3862         }
3863     }
3864     catch (const Exception& ex;)
3865     {
3866         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
3867         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
3868         references.insert(references.end()ex.References().begin()ex.References().end());
3869         throw Exception("could not generate assignment for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()assignmentNode->GetSpan()assignmentNode->ModuleId()references);
3870     }
3871 }
3872 
3873 void GenerateClassTermination(DestructorSymbol* destructorSymbolDestructorNode* destructorNodeBoundCompoundStatement* boundCompoundStatementBoundFunction* boundFunction
3874     BoundCompileUnit& boundCompileUnitContainerScope* containerScopeStatementBinder* statementBinderconst Span& spanconst boost::uuids::uuid& moduleId)
3875 {
3876     Symbol* parent = destructorSymbol->Parent();
3877     Assert(parent->GetSymbolType() == SymbolType::classTypeSymbol || parent->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type symbol expected");
3878     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(parent);
3879     try
3880     {
3881         ParameterSymbol* thisParam = destructorSymbol->GetThisParam();
3882         Assert(thisParam"this parameter expected");
3883         if (classType->IsPolymorphic())
3884         {
3885             ParameterSymbol* thisParam = destructorSymbol->Parameters()[0];
3886             BoundExpression* classPtr = nullptr;
3887             ClassTypeSymbol* vmtPtrHolderClass = classType->VmtPtrHolderClass();
3888             if (vmtPtrHolderClass == classType)
3889             {
3890                 classPtr = new BoundParameter(spanmoduleIdthisParam);
3891             }
3892             else
3893             {
3894                 ArgumentMatch argumentMatch;
3895                 FunctionSymbol* thisToHolderConversion = boundCompileUnit.GetConversion(thisParam->GetType()vmtPtrHolderClass->AddPointer(spanmoduleId)containerScopeboundFunction
3896                     spanmoduleIdargumentMatch);
3897                 if (!thisToHolderConversion)
3898                 {
3899                     throw Exception("base class conversion not found"destructorNode->GetSpan()destructorNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3900                 }
3901                 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToHolderConversion);
3902             }
3903             boundCompoundStatement->InsertStatementToFront(std::unique_ptr<BoundStatement>(new BoundSetVmtPtrStatement(std::unique_ptr<BoundExpression>(classPtr)classType)));
3904         }
3905         int n = classType->MemberVariables().size();
3906         for (int i = n - 1; i >= 0; --i)
3907         {
3908             MemberVariableSymbol* memberVariableSymbol = classType->MemberVariables()[i];
3909             if (memberVariableSymbol->GetType()->HasNontrivialDestructor())
3910             {
3911                 std::vector<FunctionScopeLookup> memberDestructorCallLookups;
3912                 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3913                 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
3914                 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3915                 std::vector<std::std::unique_ptr<BoundExpression>>memberDestructorCallArguments;
3916                 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(spanmoduleIdmemberVariableSymbol);
3917                 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIddestructorSymbol->GetThisParam())));
3918                 memberDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
3919                     new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable)boundMemberVariable->GetType()->AddPointer(spanmoduleId))));
3920                 std::unique_ptr<BoundFunctionCall> memberDestructorCall = ResolveOverload(U"@destructor"containerScopememberDestructorCallLookupsmemberDestructorCallArguments
3921                     boundCompileUnitboundFunctionspanmoduleId);
3922                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(memberDestructorCall)spanmoduleId)));
3923             }
3924         }
3925         if (classType->BaseClass() && classType->BaseClass()->HasNontrivialDestructor())
3926         {
3927             std::vector<FunctionScopeLookup> baseDestructorCallLookups;
3928             baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
3929             baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->BaseClass()->GetContainerScope()));
3930             baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
3931             std::vector<std::std::unique_ptr<BoundExpression>>baseDestructorCallArguments;
3932             ArgumentMatch argumentMatch;
3933             FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType()classType->BaseClass()->AddPointer(spanmoduleId)containerScopeboundFunction
3934                 spanmoduleIdargumentMatch);
3935             if (!thisToBaseConversion)
3936             {
3937                 throw Exception("base class conversion not found"destructorNode->GetSpan()destructorNode->ModuleId()classType->GetSpan()classType->SourceModuleId());
3938             }
3939             BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(spanmoduleIdthisParam))thisToBaseConversion);
3940             baseDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3941             std::unique_ptr<BoundFunctionCall> baseDestructorCall = ResolveOverload(U"@destructor"containerScopebaseDestructorCallLookupsbaseDestructorCallArgumentsboundCompileUnit
3942                 boundFunctionspanmoduleId);
3943             boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(baseDestructorCall)spanmoduleId)));
3944         }
3945     }
3946     catch (const Exception& ex;)
3947     {
3948         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
3949         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
3950         references.insert(references.end()ex.References().begin()ex.References().end());
3951         throw Exception("could not generate termination for class '" + ToUtf8(classType->FullName()) + "'. Reason: " + ex.Message()destructorNode->GetSpan()destructorNode->ModuleId()references);
3952     }
3953 }
3954 
3955 Operation::Operation(const std::u32string& groupName_int arity_BoundCompileUnit& boundCompileUnit_) : groupName(groupName_)arity(arity_)boundCompileUnit(boundCompileUnit_)
3956 {
3957 }
3958 
3959 Operation::~Operation()
3960 {
3961 }
3962 
3963 SymbolTable* Operation::GetSymbolTable()
3964 {
3965     return &boundCompileUnit.GetSymbolTable();
3966 }
3967 
3968 BoundCompileUnit& Operation::GetBoundCompileUnit()
3969 {
3970     return boundCompileUnit;
3971 }
3972 
3973 void ArityOperation::Add(Operation* operation)
3974 {
3975     operations.push_back(operation);
3976 }
3977 
3978 void ArityOperation::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
3979     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
3980 {
3981     for (Operation* operation : operations)
3982     {
3983         operation->CollectViableFunctions(containerScopeargumentscurrentFunctionviableFunctionsexceptionspanmoduleIdflags);
3984     }
3985 }
3986 
3987 void OperationGroup::Add(Operation* operation)
3988 {
3989     int arity = operation->Arity();
3990     if (arity >= arityOperations.size())
3991     {
3992         arityOperations.resize(arity + 1);
3993     }
3994     ArityOperation* arityOperation = arityOperations[arity].get();
3995     if (!arityOperation)
3996     {
3997         arityOperation = new ArityOperation();
3998         arityOperations[arity].reset(arityOperation);
3999     }
4000     arityOperation->Add(operation);
4001 }
4002 
4003 void OperationGroup::CollectViableFunctions(ContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&argumentsBoundFunction*currentFunction
4004     ViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
4005 {
4006     int arity = arguments.size();
4007     if (arity < arityOperations.size())
4008     {
4009         ArityOperation* arityOperation = arityOperations[arity].get();
4010         if (arityOperation)
4011         {
4012             arityOperation->CollectViableFunctions(containerScopeargumentscurrentFunctionviableFunctionsexceptionspanmoduleIdflags);
4013         }
4014     }
4015 }
4016 
4017 OperationRepository::OperationRepository(BoundCompileUnit& boundCompileUnit_) : boundCompileUnit(boundCompileUnit_)copyConstructorOperation(nullptr)
4018 {
4019     Add(new LvalueReferenceCopyConstructorOperation(boundCompileUnit));
4020     Add(new LvalueReferenceCopyAssignmentOperation(boundCompileUnit));
4021     Add(new LvalueReferenceMoveAssignmentOperation(boundCompileUnit));
4022     Add(new LvalueReferenceReturnOperation(boundCompileUnit));
4023     Add(new RvalueReferenceCopyConstructorOperation(boundCompileUnit));
4024     Add(new RvalueReferenceCopyAssignmentOperation(boundCompileUnit));
4025     Add(new RvalueReferenceReturnOperation(boundCompileUnit));
4026     Add(new PointerDefaultConstructorOperation(boundCompileUnit));
4027     Add(new PointerCopyConstructorOperation(boundCompileUnit));
4028     Add(new PointerMoveConstructorOperation(boundCompileUnit));
4029     Add(new PointerCopyAssignmentOperation(boundCompileUnit));
4030     Add(new PointerMoveAssignmentOperation(boundCompileUnit));
4031     Add(new PointerReturnOperation(boundCompileUnit));
4032     Add(new PointerPlusOffsetOperation(boundCompileUnit));
4033     Add(new OffsetPlusPointerOperation(boundCompileUnit));
4034     Add(new PointerMinusOffsetOperation(boundCompileUnit));
4035     Add(new PointerMinusPointerOperation(boundCompileUnit));
4036     Add(new PointerEqualOperation(boundCompileUnit));
4037     Add(new PointerLessOperation(boundCompileUnit));
4038     Add(new PointerArrowOperation(boundCompileUnit));
4039     Add(new ClassDefaultConstructorOperation(boundCompileUnit));
4040     copyConstructorOperation = new ClassCopyConstructorOperation(boundCompileUnit);
4041     Add(copyConstructorOperation);
4042     Add(new ClassMoveConstructorOperation(boundCompileUnit));
4043     Add(new ClassCopyAssignmentOperation(boundCompileUnit));
4044     Add(new ClassMoveAssignmentOperation(boundCompileUnit));
4045     Add(new ArrayDefaultConstructorOperation(boundCompileUnit));
4046     Add(new ArrayCopyConstructorOperation(boundCompileUnit));
4047     Add(new ArrayMoveConstructorOperation(boundCompileUnit));
4048     Add(new ArrayCopyAssignmentOperation(boundCompileUnit));
4049     Add(new ArrayMoveAssignmentOperation(boundCompileUnit));
4050     Add(new ArrayElementAccessOperation(boundCompileUnit));
4051     Add(new InterfaceDefaultConstructorOperation(boundCompileUnit));
4052     Add(new InterfaceCopyConstructorOperation(boundCompileUnit));
4053     Add(new InterfaceMoveConstructorOperation(boundCompileUnit));
4054     Add(new InterfaceCopyAssignmentOperation(boundCompileUnit));
4055     Add(new InterfaceMoveAssignmentOperation(boundCompileUnit));
4056 }
4057 
4058 void OperationRepository::Add(Operation* operation)
4059 {
4060     OperationGroup* group = nullptr;
4061     auto it = operationGroupMap.find(operation->GroupName());
4062     if (it != operationGroupMap.cend())
4063     {
4064         group = it->second;
4065     }
4066     else
4067     {
4068         group = new OperationGroup();
4069         operationGroupMap.insert(std::make_pair(operation->GroupName()group));
4070         operationGroups.push_back(std::unique_ptr<OperationGroup>(group));
4071     }
4072     group->Add(operation);
4073     operations.push_back(std::unique_ptr<Operation>(operation));
4074 }
4075 
4076 void OperationRepository::CollectViableFunctions(const std::u32string& groupNameContainerScope* containerScopeconst std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments
4077     BoundFunction* currentFunctionViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
4078 {
4079     auto it = operationGroupMap.find(groupName);
4080     if (it != operationGroupMap.cend())
4081     {
4082         OperationGroup* operationGroup = it->second;
4083         operationGroup->CollectViableFunctions(containerScopeargumentscurrentFunctionviableFunctionsexceptionspanmoduleIdflags);
4084     }
4085 }
4086 
4087 void OperationRepository::GenerateCopyConstructorFor(ClassTypeSymbol* classTypeSymbolContainerScope* containerScopeBoundFunction* currentFunctionconst Span& spanconst boost::uuids::uuid& moduleId)
4088 {
4089     if (boundCompileUnit.HasCopyConstructorFor(classTypeSymbol->TypeId())) return;
4090     std::unique_ptr<ClassCopyConstructor> copyConstructor(new ClassCopyConstructor(classTypeSymbol));
4091     copyConstructor->SetCompileUnit(boundCompileUnit.GetCompileUnitNode());
4092     copyConstructor->SetModule(&boundCompileUnit.GetModule());
4093     ClassCopyConstructorOperation* copyConstructorOp = static_cast<ClassCopyConstructorOperation*>(copyConstructorOperation);
4094     std::unique_ptr<Exception> exception;
4095     if (copyConstructorOp->GenerateImplementation(copyConstructor.get()containerScopecurrentFunctionexceptionspanmoduleId))
4096     {
4097         copyConstructor->SetModule(&boundCompileUnit.GetModule());
4098         copyConstructor->SetParent(classTypeSymbol);
4099         copyConstructor->SetLinkOnceOdrLinkage();
4100         boundCompileUnit.AddCopyConstructorFor(classTypeSymbol->TypeId()std::move(copyConstructor));
4101     }
4102     else
4103     {
4104         if (exception)
4105         {
4106             throw *exception;
4107         }
4108         else
4109         {
4110             throw Exception("could not generate copy constructor for class '" + ToUtf8(classTypeSymbol->FullName()) + "'"spanmoduleId);
4111         }
4112     }
4113 }
4114 
4115 void OperationRepository::GenerateCopyConstructorFor(InterfaceTypeSymbol* interfaceTypeSymbolContainerScope* containerScopeBoundFunction* currentFunctionconst Span& spanconst boost::uuids::uuid& moduleId)
4116 {
4117     if (boundCompileUnit.HasCopyConstructorFor(interfaceTypeSymbol->TypeId())) return;
4118     std::unique_ptr<InterfaceTypeCopyConstructor> copyConstructor(new InterfaceTypeCopyConstructor(interfaceTypeSymbolspanmoduleId));
4119     boundCompileUnit.GetSymbolTable().SetFunctionIdFor(copyConstructor.get());
4120     copyConstructor->SetCompileUnit(boundCompileUnit.GetCompileUnitNode());
4121     copyConstructor->SetModule(&boundCompileUnit.GetModule());
4122     copyConstructor->SetParent(interfaceTypeSymbol);
4123     boundCompileUnit.AddCopyConstructorFor(interfaceTypeSymbol->TypeId()std::move(copyConstructor));
4124 }
4125 
4126 } } // namespace cmajor::binder