1
2
3
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& span, const boost::uuids::uuid& moduleId);
33 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
34 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@constructor"), type(type_), nullValue(nullptr)
43 {
44 SetGroupName(U"@constructor");
45 SetAccess(SymbolAccess::public_);
46 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
47 thisParam->SetType(type->AddPointer(span, moduleId));
48 AddMember(thisParam);
49 ComputeName();
50 }
51
52 void PointerDefaultCtor::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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(emitter, OperationFlags::none);
61 }
62
63 class PointerDefaultConstructorOperation : public Operation
64 {
65 public:
66 PointerDefaultConstructorOperation(BoundCompileUnit& boundCompileUnit_);
67 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
68 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 1, boundCompileUnit_)
75 {
76 }
77
78 void PointerDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
79 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
90 FunctionSymbol* function = functionMap[pointerType];
91 if (!function)
92 {
93 function = new PointerDefaultCtor(pointerType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
106 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
107 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@constructor"), type(type_)
115 {
116 SetGroupName(U"@constructor");
117 SetAccess(SymbolAccess::public_);
118 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
119 thisParam->SetType(type->AddPointer(span, moduleId));
120 AddMember(thisParam);
121 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
122 thatParam->SetType(type);
123 AddMember(thatParam);
124 ComputeName();
125 }
126
127 void PointerCopyCtor::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
128 {
129 Assert(genObjects.size() == 2, "copy constructor needs two objects");
130 genObjects[1]->Load(emitter, OperationFlags::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(emitter, OperationFlags::none);
138 }
139
140 class PointerCopyConstructorOperation : public Operation
141 {
142 public:
143 PointerCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
144 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
145 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 2, boundCompileUnit_)
152 {
153 }
154
155 void PointerCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
156 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
167 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none ||
168 !TypesEqual(arguments[1]->GetType(), pointerType->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
169 {
170 FunctionSymbol* function = functionMap[pointerType];
171 if (!function)
172 {
173 function = new PointerCopyCtor(pointerType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
187 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
188 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@constructor"), type(type_)
196 {
197 SetGroupName(U"@constructor");
198 SetAccess(SymbolAccess::public_);
199 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
200 thisParam->SetType(type->AddPointer(span, moduleId));
201 AddMember(thisParam);
202 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
203 thatParam->SetType(type->AddRvalueReference(span, moduleId));
204 AddMember(thatParam);
205 ComputeName();
206 }
207
208 void PointerMoveCtor::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
209 {
210 Assert(genObjects.size() == 2, "move constructor needs two objects");
211 genObjects[1]->Load(emitter, OperationFlags::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(emitter, OperationFlags::none);
221 }
222
223 class PointerMoveConstructorOperation : public Operation
224 {
225 public:
226 PointerMoveConstructorOperation(BoundCompileUnit& boundCompileUnit_);
227 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
228 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 2, boundCompileUnit_)
235 {
236 }
237
238 void PointerMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
239 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
251 if (TypesEqual(arguments[1]->GetType(), pointerType->AddRvalueReference(span, moduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
252 {
253 FunctionSymbol* function = functionMap[pointerType];
254 if (!function)
255 {
256 function = new PointerMoveCtor(pointerType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
270 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
271 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator="), type(type_)
279 {
280 SetGroupName(U"operator=");
281 SetAccess(SymbolAccess::public_);
282 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
283 thisParam->SetType(type->AddPointer(span, moduleId));
284 AddMember(thisParam);
285 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
286 thatParam->SetType(type);
287 AddMember(thatParam);
288 SetReturnType(voidType_);
289 ComputeName();
290 }
291
292 void PointerCopyAssignment::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
293 {
294 Assert(genObjects.size() == 2, "copy assignment needs two objects");
295 genObjects[1]->Load(emitter, OperationFlags::none);
296 genObjects[0]->Store(emitter, OperationFlags::none);
297 }
298
299 class PointerCopyAssignmentOperation : public Operation
300 {
301 public:
302 PointerCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
303 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
304 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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=", 2, boundCompileUnit_)
311 {
312 }
313
314 void PointerCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
315 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
326 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none ||
327 !TypesEqual(arguments[1]->GetType(), pointerType->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
328 {
329 FunctionSymbol* function = functionMap[pointerType];
330 if (!function)
331 {
332 function = new PointerCopyAssignment(pointerType, GetSymbolTable()->GetTypeByName(U"void"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
346 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
347 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator="), type(type_)
355 {
356 SetGroupName(U"operator=");
357 SetAccess(SymbolAccess::public_);
358 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
359 thisParam->SetType(type->AddPointer(span, moduleId));
360 AddMember(thisParam);
361 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
362 thatParam->SetType(type->AddRvalueReference(span, moduleId));
363 AddMember(thatParam);
364 SetReturnType(voidType_);
365 ComputeName();
366 }
367
368 void PointerMoveAssignment::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
369 {
370 Assert(genObjects.size() == 2, "copy assignment needs two objects");
371 genObjects[1]->Load(emitter, OperationFlags::none);
372 void* rvalueRefValue = emitter.Stack().Pop();
373 emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
374 genObjects[0]->Store(emitter, OperationFlags::none);
375 }
376
377 class PointerMoveAssignmentOperation : public Operation
378 {
379 public:
380 PointerMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
381 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
382 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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=", 2, boundCompileUnit_)
389 {
390 }
391
392 void PointerMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
393 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
405 if (TypesEqual(arguments[1]->GetType(), pointerType->AddRvalueReference(span, moduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
406 {
407 FunctionSymbol* function = functionMap[pointerType];
408 if (!function)
409 {
410 function = new PointerMoveAssignment(pointerType, GetSymbolTable()->GetTypeByName(U"void"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
424 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
425 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@return"), type(type_)
433 {
434 SetGroupName(U"@return");
435 SetAccess(SymbolAccess::public_);
436 ParameterSymbol* valueParam = new ParameterSymbol(span, moduleId, U"value");
437 valueParam->SetType(type);
438 AddMember(valueParam);
439 SetReturnType(type);
440 ComputeName();
441 }
442
443 void PointerReturn::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
444 {
445 Assert(genObjects.size() == 1, "return needs one object");
446 genObjects[0]->Load(emitter, OperationFlags::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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
460 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 1, boundCompileUnit_)
467 {
468 }
469
470 void PointerReturnOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
471 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(type, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
497 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
498 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator+")
504 {
505 SetGroupName(U"operator+");
506 SetAccess(SymbolAccess::public_);
507 ParameterSymbol* leftParam = new ParameterSymbol(span, moduleId, U"left");
508 leftParam->SetType(pointerType_);
509 AddMember(leftParam);
510 ParameterSymbol* rightParam = new ParameterSymbol(span, moduleId, U"right");
511 rightParam->SetType(longType_);
512 AddMember(rightParam);
513 SetReturnType(pointerType_);
514 ComputeName();
515 }
516
517 void PointerPlusOffset::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
518 {
519 Assert(genObjects.size() == 2, "operator+ needs two objects");
520 genObjects[0]->Load(emitter, OperationFlags::none);
521 void* left = emitter.Stack().Pop();
522 genObjects[1]->Load(emitter, OperationFlags::none);
523 void* right = emitter.Stack().Pop();
524 emitter.Stack().Push(emitter.ComputeAddress(left, right));
525 }
526
527 class PointerPlusOffsetOperation : public Operation
528 {
529 public:
530 PointerPlusOffsetOperation(BoundCompileUnit& boundCompileUnit_);
531 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
532 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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+", 2, boundCompileUnit_)
539 {
540 }
541
542 void PointerPlusOffsetOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
543 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
544 {
545 TypeSymbol* leftType = arguments[0]->GetType();
546 if (!leftType->IsPointerType()) return;
547 leftType = leftType->PlainType(span, moduleId);
548 TypeSymbol* rightType = arguments[1]->GetType();
549 if (!rightType->PlainType(span, moduleId)->IsIntegralType())
550 {
551 ArgumentMatch argumentMatch;
552 if (!GetBoundCompileUnit().GetConversion(rightType, GetSymbolTable()->GetTypeByName(U"long"), containerScope, currentFunction, span, moduleId, argumentMatch))
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(leftType, GetSymbolTable()->GetTypeByName(U"long"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
578 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
579 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator+")
585 {
586 SetGroupName(U"operator+");
587 SetAccess(SymbolAccess::public_);
588 ParameterSymbol* leftParam = new ParameterSymbol(span, moduleId, U"left");
589 leftParam->SetType(longType_);
590 AddMember(leftParam);
591 ParameterSymbol* rightParam = new ParameterSymbol(span, moduleId, U"right");
592 rightParam->SetType(pointerType_);
593 AddMember(rightParam);
594 SetReturnType(pointerType_);
595 ComputeName();
596 }
597
598 void OffsetPlusPointer::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
599 {
600 Assert(genObjects.size() == 2, "operator+ needs two objects");
601 genObjects[0]->Load(emitter, OperationFlags::none);
602 void* left = emitter.Stack().Pop();
603 genObjects[1]->Load(emitter, OperationFlags::none);
604 void* right = emitter.Stack().Pop();
605 emitter.Stack().Push(emitter.ComputeAddress(right, left));
606 }
607
608 class OffsetPlusPointerOperation : public Operation
609 {
610 public:
611 OffsetPlusPointerOperation(BoundCompileUnit& boundCompileUnit_);
612 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
613 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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+", 2, boundCompileUnit_)
620 {
621 }
622
623 void OffsetPlusPointerOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
624 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
625 {
626 TypeSymbol* leftType = arguments[0]->GetType();
627 if (!leftType->PlainType(span, moduleId)->IsIntegralType())
628 {
629 ArgumentMatch argumentMatch;
630 if (!GetBoundCompileUnit().GetConversion(leftType, GetSymbolTable()->GetTypeByName(U"long"), containerScope, currentFunction, span, moduleId, argumentMatch))
631 {
632 return;
633 }
634 }
635 TypeSymbol* rightType = arguments[1]->GetType();
636 if (!rightType->IsPointerType()) return;
637 rightType = rightType->PlainType(span, moduleId);
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(longType, rightType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
660 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
661 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator-")
667 {
668 SetGroupName(U"operator-");
669 SetAccess(SymbolAccess::public_);
670 ParameterSymbol* leftParam = new ParameterSymbol(span, moduleId, U"left");
671 leftParam->SetType(pointerType_);
672 AddMember(leftParam);
673 ParameterSymbol* rightParam = new ParameterSymbol(span, moduleId, U"right");
674 rightParam->SetType(longType_);
675 AddMember(rightParam);
676 SetReturnType(pointerType_);
677 ComputeName();
678 }
679
680 void PointerMinusOffset::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
681 {
682 Assert(genObjects.size() == 2, "operator- needs two objects");
683 genObjects[0]->Load(emitter, OperationFlags::none);
684 void* left = emitter.Stack().Pop();
685 genObjects[1]->Load(emitter, OperationFlags::none);
686 void* right = emitter.Stack().Pop();
687 void* offset = emitter.CreateNeg(right);
688 emitter.Stack().Push(emitter.ComputeAddress(left, offset));
689 }
690
691 class PointerMinusOffsetOperation : public Operation
692 {
693 public:
694 PointerMinusOffsetOperation(BoundCompileUnit& boundCompileUnit_);
695 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
696 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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-", 2, boundCompileUnit_)
703 {
704 }
705
706 void PointerMinusOffsetOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
707 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
708 {
709 TypeSymbol* leftType = arguments[0]->GetType();
710 if (!leftType->IsPointerType()) return;
711 leftType = leftType->PlainType(span, moduleId);
712 TypeSymbol* rightType = arguments[1]->GetType();
713 if (!rightType->PlainType(span, moduleId)->IsIntegralType())
714 {
715 ArgumentMatch argumentMatch;
716 if (!GetBoundCompileUnit().GetConversion(rightType, GetSymbolTable()->GetTypeByName(U"long"), containerScope, currentFunction, span, moduleId, argumentMatch))
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(leftType, GetSymbolTable()->GetTypeByName(U"long"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
742 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
743 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator-")
749 {
750 SetGroupName(U"operator-");
751 SetAccess(SymbolAccess::public_);
752 ParameterSymbol* leftParam = new ParameterSymbol(span, moduleId, U"left");
753 leftParam->SetType(pointerType_);
754 AddMember(leftParam);
755 ParameterSymbol* rightParam = new ParameterSymbol(span, moduleId, U"right");
756 rightParam->SetType(pointerType_);
757 AddMember(rightParam);
758 SetReturnType(longType_);
759 ComputeName();
760 }
761
762 void PointerMinusPointer::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
763 {
764 Assert(genObjects.size() == 2, "operator- needs two objects");
765 genObjects[0]->Load(emitter, OperationFlags::none);
766 void* left = emitter.Stack().Pop();
767 genObjects[1]->Load(emitter, OperationFlags::none);
768 void* right = emitter.Stack().Pop();
769 emitter.Stack().Push(emitter.CreatePtrDiff(left, right));
770 }
771
772 class PointerMinusPointerOperation : public Operation
773 {
774 public:
775 PointerMinusPointerOperation(BoundCompileUnit& boundCompileUnit_);
776 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
777 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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-", 2, boundCompileUnit_)
784 {
785 }
786
787 void PointerMinusPointerOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
788 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
789 {
790 TypeSymbol* leftType = arguments[0]->GetType();
791 if (!leftType->IsPointerType()) return;
792 leftType = leftType->PlainType(span, moduleId);
793 TypeSymbol* rightType = arguments[1]->GetType();
794 if (!rightType->IsPointerType()) return;
795 rightType = rightType->PlainType(span, moduleId);
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(leftType, GetSymbolTable()->GetTypeByName(U"long"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
817 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
818 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator==")
824 {
825 SetGroupName(U"operator==");
826 SetAccess(SymbolAccess::public_);
827 ParameterSymbol* leftParam = new ParameterSymbol(span, moduleId, U"left");
828 leftParam->SetType(pointerType_);
829 AddMember(leftParam);
830 ParameterSymbol* rightParam = new ParameterSymbol(span, moduleId, U"right");
831 rightParam->SetType(pointerType_);
832 AddMember(rightParam);
833 SetReturnType(boolType_);
834 ComputeName();
835 }
836
837 void PointerEqual::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
838 {
839 Assert(genObjects.size() == 2, "operator== needs two objects");
840 genObjects[0]->Load(emitter, OperationFlags::none);
841 void* left = emitter.Stack().Pop();
842 genObjects[1]->Load(emitter, OperationFlags::none);
843 void* right = emitter.Stack().Pop();
844 emitter.Stack().Push(emitter.CreateICmpEQ(left, right));
845 }
846
847 class PointerEqualOperation : public Operation
848 {
849 public:
850 PointerEqualOperation(BoundCompileUnit& boundCompileUnit_);
851 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
852 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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==", 2, boundCompileUnit_)
859 {
860 }
861
862 void PointerEqualOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
863 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
864 {
865 TypeSymbol* leftType = arguments[0]->GetType();
866 if (!leftType->IsPointerType()) return;
867 leftType = leftType->PlainType(span, moduleId);
868 TypeSymbol* rightType = arguments[1]->GetType();
869 rightType = rightType->PlainType(span, moduleId);
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(leftType, GetSymbolTable()->GetTypeByName(U"bool"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
892 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
893 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator<")
899 {
900 SetGroupName(U"operator<");
901 SetAccess(SymbolAccess::public_);
902 ParameterSymbol* leftParam = new ParameterSymbol(span, moduleId, U"left");
903 leftParam->SetType(pointerType_);
904 AddMember(leftParam);
905 ParameterSymbol* rightParam = new ParameterSymbol(span, moduleId, U"right");
906 rightParam->SetType(pointerType_);
907 AddMember(rightParam);
908 SetReturnType(boolType_);
909 ComputeName();
910 }
911
912 void PointerLess::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
913 {
914 Assert(genObjects.size() == 2, "operator< needs two objects");
915 genObjects[0]->Load(emitter, OperationFlags::none);
916 void* left = emitter.Stack().Pop();
917 genObjects[1]->Load(emitter, OperationFlags::none);
918 void* right = emitter.Stack().Pop();
919 emitter.Stack().Push(emitter.CreateICmpULT(left, right));
920 }
921
922 class PointerLessOperation : public Operation
923 {
924 public:
925 PointerLessOperation(BoundCompileUnit& boundCompileUnit_);
926 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
927 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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<", 2, boundCompileUnit_)
934 {
935 }
936
937 void PointerLessOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
938 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
939 {
940 TypeSymbol* leftType = arguments[0]->GetType();
941 if (!leftType->IsPointerType()) return;
942 leftType = leftType->PlainType(span, moduleId);
943 TypeSymbol* rightType = arguments[1]->GetType();
944 if (!rightType->IsPointerType()) return;
945 rightType = rightType->PlainType(span, moduleId);
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(leftType, GetSymbolTable()->GetTypeByName(U"bool"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
967 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
968 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"operator->"), type(type_)
976 {
977 SetGroupName(U"operator->");
978 SetAccess(SymbolAccess::public_);
979 ParameterSymbol* operandParam = new ParameterSymbol(span, moduleId, U"operand");
980 operandParam->SetType(type->AddPointer(span, moduleId));
981 AddMember(operandParam);
982 SetReturnType(type);
983 ComputeName();
984 }
985
986 void PointerArrow::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
987 {
988 Assert(genObjects.size() == 1, "return needs one object");
989 genObjects[0]->Load(emitter, OperationFlags::none);
990 }
991
992 class PointerArrowOperation : public Operation
993 {
994 public:
995 PointerArrowOperation(BoundCompileUnit& boundCompileUnit_);
996 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
997 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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->", 1, boundCompileUnit_)
1004 {
1005 }
1006
1007 void PointerArrowOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1008 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
1018 FunctionSymbol* function = functionMap[pointerType];
1019 if (!function)
1020 {
1021 function = new PointerArrow(pointerType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1034 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1035 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@constructor"), type(type_)
1043 {
1044 SetGroupName(U"@constructor");
1045 SetAccess(SymbolAccess::public_);
1046 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
1047 thisParam->SetType(type->AddPointer(span, moduleId));
1048 AddMember(thisParam);
1049 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
1050 thatParam->SetType(type);
1051 AddMember(thatParam);
1052 ComputeName();
1053 }
1054
1055 void LvalueRefefenceCopyCtor::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1056 {
1057 Assert(genObjects.size() == 2, "reference copy constructor needs two objects");
1058 genObjects[1]->Load(emitter, OperationFlags::none);
1059 genObjects[0]->Store(emitter, OperationFlags::none);
1060 }
1061
1062 class LvalueReferenceCopyConstructorOperation : public Operation
1063 {
1064 public:
1065 LvalueReferenceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1066 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1067 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 2, boundCompileUnit_)
1074 {
1075 }
1076
1077 void LvalueReferenceCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1078 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
1088 FunctionSymbol* function = functionMap[lvalueRefType];
1089 if (!function)
1090 {
1091 function = new LvalueRefefenceCopyCtor(lvalueRefType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1104 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1105 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) :
1114 FunctionSymbol(span, moduleId, U"operator="), type(type_)
1115 {
1116 SetGroupName(U"operator=");
1117 SetAccess(SymbolAccess::public_);
1118 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
1119 thisParam->SetType(type->AddPointer(span, moduleId));
1120 AddMember(thisParam);
1121 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
1122 thatParam->SetType(type);
1123 AddMember(thatParam);
1124 SetReturnType(voidType_);
1125 ComputeName();
1126 }
1127
1128 void LvalueReferenceCopyAssignment::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1129 {
1130 Assert(genObjects.size() == 2, "copy assignment needs two objects");
1131 genObjects[1]->Load(emitter, OperationFlags::none);
1132 genObjects[0]->Store(emitter, OperationFlags::none);
1133 }
1134
1135 class LvalueReferenceCopyAssignmentOperation : public Operation
1136 {
1137 public:
1138 LvalueReferenceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1139 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1140 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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=", 2, boundCompileUnit_)
1147 {
1148 }
1149
1150 void LvalueReferenceCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1151 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
1161 if (lvalueRefType->PlainType(span, moduleId)->IsClassTypeSymbol()) return;
1162 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none ||
1163 !TypesEqual(arguments[1]->GetType()->RemoveConst(span, moduleId), lvalueRefType->PlainType(span, moduleId)->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1164 {
1165 FunctionSymbol* function = functionMap[lvalueRefType];
1166 if (!function)
1167 {
1168 function = new LvalueReferenceCopyAssignment(lvalueRefType, GetSymbolTable()->GetTypeByName(U"void"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1182 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1183 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) :
1191 FunctionSymbol(span, moduleId, U"operator="), type(type_)
1192 {
1193 SetGroupName(U"operator=");
1194 SetAccess(SymbolAccess::public_);
1195 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
1196 thisParam->SetType(type->AddPointer(span, moduleId));
1197 AddMember(thisParam);
1198 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
1199 thatParam->SetType(type->RemoveReference(span, moduleId)->AddRvalueReference(span, moduleId));
1200 AddMember(thatParam);
1201 SetReturnType(voidType_);
1202 ComputeName();
1203 }
1204
1205 void LvalueReferenceMoveAssignment::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1206 {
1207 Assert(genObjects.size() == 2, "copy assignment needs two objects");
1208 genObjects[1]->Load(emitter, OperationFlags::none);
1209 void* rvalueRefValue = emitter.Stack().Pop();
1210 emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
1211 genObjects[0]->Store(emitter, OperationFlags::none);
1212 }
1213
1214 class LvalueReferenceMoveAssignmentOperation : public Operation
1215 {
1216 public:
1217 LvalueReferenceMoveAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1218 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1219 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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=", 2, boundCompileUnit_)
1226 {
1227 }
1228
1229 void LvalueReferenceMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1230 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
1241 if (lvalueRefType->PlainType(span, moduleId)->IsClassTypeSymbol()) return;
1242 if (lvalueRefType->PlainType(span, moduleId)->IsArrayType()) return;
1243 if (TypesEqual(arguments[1]->GetType()->RemoveConst(span, moduleId), lvalueRefType->PlainType(span, moduleId)->AddRvalueReference(span, moduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1244 {
1245 FunctionSymbol* function = functionMap[lvalueRefType];
1246 if (!function)
1247 {
1248 function = new LvalueReferenceMoveAssignment(lvalueRefType, GetSymbolTable()->GetTypeByName(U"void"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1262 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1263 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@return"), type(type_)
1271 {
1272 SetGroupName(U"@return");
1273 SetAccess(SymbolAccess::public_);
1274 ParameterSymbol* valueParam = new ParameterSymbol(span, moduleId, U"value");
1275 valueParam->SetType(type);
1276 AddMember(valueParam);
1277 SetReturnType(type);
1278 ComputeName();
1279 }
1280
1281 void LvalueReferenceReturn::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1282 {
1283 Assert(genObjects.size() == 1, "return needs one object");
1284 genObjects[0]->Load(emitter, OperationFlags::none);
1285 }
1286
1287 class LvalueReferenceReturnOperation : public Operation
1288 {
1289 public:
1290 LvalueReferenceReturnOperation(BoundCompileUnit& boundCompileUnit_);
1291 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1292 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 1, boundCompileUnit_)
1299 {
1300 }
1301
1302 void LvalueReferenceReturnOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1303 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(type, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1328 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1329 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) : FunctionSymbol(span, moduleId, U"@constructor"), type(type_)
1337 {
1338 SetGroupName(U"@constructor");
1339 SetAccess(SymbolAccess::public_);
1340 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
1341 thisParam->SetType(type->AddPointer(span, moduleId));
1342 AddMember(thisParam);
1343 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
1344 thatParam->SetType(type);
1345 AddMember(thatParam);
1346 ComputeName();
1347 }
1348
1349 void RvalueRefefenceCopyCtor::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1350 {
1351 Assert(genObjects.size() == 2, "reference copy constructor needs two objects");
1352 genObjects[1]->Load(emitter, OperationFlags::none);
1353 genObjects[0]->Store(emitter, OperationFlags::none);
1354 }
1355
1356 class RvalueReferenceCopyConstructorOperation : public Operation
1357 {
1358 public:
1359 RvalueReferenceCopyConstructorOperation(BoundCompileUnit& boundCompileUnit_);
1360 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1361 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 2, boundCompileUnit_)
1368 {
1369 }
1370
1371 void RvalueReferenceCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1372 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(span, moduleId);
1382 if (rvalueRefType->PlainType(span, moduleId)->IsClassTypeSymbol()) return;
1383 FunctionSymbol* function = functionMap[rvalueRefType];
1384 if (!function)
1385 {
1386 function = new RvalueRefefenceCopyCtor(rvalueRefType, span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1399 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1400 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) :
1408 FunctionSymbol(span, moduleId, U"operator="), type(type_)
1409 {
1410 SetGroupName(U"operator=");
1411 SetAccess(SymbolAccess::public_);
1412 ParameterSymbol* thisParam = new ParameterSymbol(span, moduleId, U"this");
1413 thisParam->SetType(type->AddPointer(span, moduleId));
1414 AddMember(thisParam);
1415 ParameterSymbol* thatParam = new ParameterSymbol(span, moduleId, U"that");
1416 thatParam->SetType(type);
1417 AddMember(thatParam);
1418 SetReturnType(voidType_);
1419 ComputeName();
1420 }
1421
1422 void RvalueReferenceCopyAssignment::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1423 {
1424 Assert(genObjects.size() == 2, "copy assignment needs two objects");
1425 genObjects[1]->Load(emitter, OperationFlags::none);
1426 void* rvalueRefValue = emitter.Stack().Pop();
1427 emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
1428 genObjects[0]->Store(emitter, OperationFlags::none);
1429 }
1430
1431 class RvalueReferenceCopyAssignmentOperation : public Operation
1432 {
1433 public:
1434 RvalueReferenceCopyAssignmentOperation(BoundCompileUnit& boundCompileUnit_);
1435 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1436 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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=", 2, boundCompileUnit_)
1443 {
1444 }
1445
1446 void RvalueReferenceCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1447 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1448 {
1449 TypeSymbol* type = arguments[0]->GetType();
1450 if (type->PointerCount() < 1 || !type->IsRvalueReferenceType()) return;
1451 TypeSymbol* rvalueRefType = type->RemovePointer(span, moduleId);
1452 if (rvalueRefType->PlainType(span, moduleId)->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(rvalueRefType, GetSymbolTable()->GetTypeByName(U"void"), span, moduleId);
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& span, const boost::uuids::uuid& moduleId);
1474 SymbolAccess DeclaredAccess() const override { return SymbolAccess::public_; }
1475 void GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::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& span, const boost::uuids::uuid& moduleId) :
1483 FunctionSymbol(span, moduleId, U"@return"), type(type_)
1484 {
1485 SetGroupName(U"@return");
1486 SetAccess(SymbolAccess::public_);
1487 ParameterSymbol* valueParam = new ParameterSymbol(span, moduleId, U"value");
1488 valueParam->SetType(type);
1489 AddMember(valueParam);
1490 SetReturnType(type);
1491 ComputeName();
1492 }
1493
1494 void RvalueReferenceReturn::GenerateCall(Emitter& emitter, std::std::vector<GenObject*>&genObjects, OperationFlagsflags, constSpan&span, constboost::uuids::uuid& moduleId)
1495 {
1496 Assert(genObjects.size() == 1, "return needs one object");
1497 genObjects[0]->Load(emitter, OperationFlags::none);
1498 }
1499
1500 class RvalueReferenceReturnOperation : public Operation
1501 {
1502 public:
1503 RvalueReferenceReturnOperation(BoundCompileUnit& boundCompileUnit_);
1504 void CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1505 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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", 1, boundCompileUnit_)
1512 {
1513 }
1514
1515 void RvalueReferenceReturnOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1516 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(type, span, moduleId);
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>>&arguments, BoundFunction*currentFunction,
1542 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1543 private:
1544 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 1, boundCompileUnit_)
1549 {
1550 }
1551
1552 void ArrayDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1553 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1554 {
1555 TypeSymbol* type = arguments[0]->GetType();
1556 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->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(span, moduleId));
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_parent, containerScope));
1568 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1569 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
1570 std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1571 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddPointer(span, moduleId))));
1572 std::unique_ptr<BoundFunctionCall> elementDefaultConstructor = ResolveOverload(U"@constructor", containerScope, elementLookups, elementArguments, GetBoundCompileUnit(), currentFunction,
1573 span, moduleId);
1574 FunctionSymbol* elementTypeDefaultConstructor = elementDefaultConstructor->GetFunctionSymbol();
1575 ArrayTypeDefaultConstructor* arrayTypeDefaultConstructor = new ArrayTypeDefaultConstructor(arrayType, elementTypeDefaultConstructor);
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>>&arguments, BoundFunction*currentFunction,
1591 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1592 private:
1593 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 2, boundCompileUnit_)
1598 {
1599 }
1600
1601 void ArrayCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1602 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1603 {
1604 TypeSymbol* type = arguments[0]->GetType();
1605 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->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(span, moduleId));
1612 if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none ||
1613 !TypesEqual(arguments[1]->GetType(), arrayType->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) &&
1614 TypesEqual(arguments[1]->GetType()->PlainType(span, moduleId), 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_parent, containerScope));
1621 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1622 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
1623 std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1624 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddPointer(span, moduleId))));
1625 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddConst(span, moduleId)->AddLvalueReference(span, moduleId))));
1626 std::unique_ptr<BoundFunctionCall> elementCopyConstructor = ResolveOverload(U"@constructor", containerScope, elementLookups, elementArguments, GetBoundCompileUnit(), currentFunction,
1627 span, moduleId);
1628 FunctionSymbol* elementTypeCopyConstructor = elementCopyConstructor->GetFunctionSymbol();
1629 ArrayTypeCopyConstructor* arrayTypeCopyConstructor = new ArrayTypeCopyConstructor(arrayType, elementTypeCopyConstructor);
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>>&arguments, BoundFunction*currentFunction,
1646 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1647 private:
1648 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 2, boundCompileUnit_)
1653 {
1654 }
1655
1656 void ArrayMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1657 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1658 {
1659 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1660 TypeSymbol* type = arguments[0]->GetType();
1661 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->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(span, moduleId));
1668 if (TypesEqual(arguments[1]->GetType(), arrayType->AddRvalueReference(span, moduleId)) || 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_parent, containerScope));
1675 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1676 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
1677 std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1678 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddPointer(span, moduleId))));
1679 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddRvalueReference(span, moduleId))));
1680 elementArguments.back()->SetFlag(BoundExpressionFlags::bindToRvalueReference);
1681 std::unique_ptr<BoundFunctionCall> elementMoveConstructor = ResolveOverload(U"@constructor", containerScope, elementLookups, elementArguments, GetBoundCompileUnit(), currentFunction,
1682 span, moduleId);
1683 FunctionSymbol* elementTypeMoveConstructor = elementMoveConstructor->GetFunctionSymbol();
1684 ArrayTypeMoveConstructor* arrayTypeMoveConstructor = new ArrayTypeMoveConstructor(arrayType, elementTypeMoveConstructor);
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>>&arguments, BoundFunction*currentFunction,
1701 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1702 private:
1703 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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=", 2, boundCompileUnit_)
1708 {
1709 }
1710
1711 void ArrayCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1712 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1713 {
1714 TypeSymbol* type = arguments[0]->GetType();
1715 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->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(span, moduleId));
1722 if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none && TypesEqual(arguments[1]->GetType()->PlainType(span, moduleId), arrayType) ||
1723 !TypesEqual(arguments[1]->GetType(), arrayType->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) &&
1724 TypesEqual(arguments[1]->GetType()->PlainType(span, moduleId), 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_parent, containerScope));
1731 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1732 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
1733 std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1734 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddPointer(span, moduleId))));
1735 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddConst(span, moduleId)->AddLvalueReference(span, moduleId))));
1736 std::unique_ptr<BoundFunctionCall> elementCopyAssignment = ResolveOverload(U"operator=", containerScope, elementLookups, elementArguments, GetBoundCompileUnit(), currentFunction,
1737 span, moduleId);
1738 FunctionSymbol* elementTypeCopyAssignment = elementCopyAssignment->GetFunctionSymbol();
1739 ArrayTypeCopyAssignment* arrayTypeCopyAssignment = new ArrayTypeCopyAssignment(arrayType, elementTypeCopyAssignment);
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>>&arguments, BoundFunction*currentFunction,
1756 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1757 private:
1758 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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=", 2, boundCompileUnit_)
1763 {
1764 }
1765
1766 void ArrayMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1767 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1768 {
1769 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1770 TypeSymbol* type = arguments[0]->GetType();
1771 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->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(span, moduleId));
1778 if (TypesEqual(arguments[1]->GetType(), arrayType->AddRvalueReference(span, moduleId)) || 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_parent, containerScope));
1785 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, arrayType->ElementType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
1786 elementLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
1787 std::vector<std::std::unique_ptr<BoundExpression>>elementArguments;
1788 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddPointer(span, moduleId))));
1789 elementArguments.push_back(std::unique_ptr<BoundExpression>(new BoundTypeExpression(span, moduleId, arrayType->ElementType()->AddRvalueReference(span, moduleId))));
1790 elementArguments.back()->SetFlag(BoundExpressionFlags::bindToRvalueReference);
1791 std::unique_ptr<BoundFunctionCall> elementMoveAssignment = ResolveOverload(U"operator=", containerScope, elementLookups, elementArguments, GetBoundCompileUnit(), currentFunction,
1792 span, moduleId);
1793 FunctionSymbol* elementTypeMoveAssignment = elementMoveAssignment->GetFunctionSymbol();
1794 ArrayTypeMoveAssignment* arrayTypeMoveAssignment = new ArrayTypeMoveAssignment(arrayType, elementTypeMoveAssignment);
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>>&arguments, BoundFunction*currentFunction,
1811 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1812 private:
1813 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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[]", 2, boundCompileUnit_)
1818 {
1819 }
1820
1821 void ArrayElementAccessOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1822 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1823 {
1824 TypeSymbol* leftType = arguments[0]->GetType();
1825 if (!leftType->PlainType(span, moduleId)->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(span, moduleId));
1832 TypeSymbol* rightType = arguments[1]->GetType();
1833 if (!rightType->PlainType(span, moduleId)->IsIntegralType())
1834 {
1835 ArgumentMatch argumentMatch;
1836 if (!GetBoundCompileUnit().GetConversion(rightType, GetSymbolTable()->GetTypeByName(U"long"), containerScope, currentFunction, span, moduleId, argumentMatch))
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>>&arguments, BoundFunction*currentFunction,
1858 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1859 private:
1860 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 1, boundCompileUnit_)
1865 {
1866 }
1867
1868 void InterfaceDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1869 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1870 {
1871 TypeSymbol* type = arguments[0]->GetType();
1872 if (type->PointerCount() != 1 || type->RemovePointer(span, moduleId)->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(span, moduleId));
1879 FunctionSymbol* function = functionMap[interfaceType->TypeId()];
1880 if (!function)
1881 {
1882 function = new InterfaceTypeDefaultConstructor(interfaceType, span, moduleId);
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>>&arguments, BoundFunction*currentFunction,
1896 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1897 private:
1898 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 2, boundCompileUnit_)
1903 {
1904 }
1905
1906 void InterfaceCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1907 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1908 {
1909 TypeSymbol* type = arguments[0]->GetType();
1910 if (type->PointerCount() != 1 || type->RemovePointer(span, moduleId)->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(span, moduleId));
1917
1918 if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none ||
1919 !TypesEqual(arguments[1]->GetType(), interfaceType->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) &&
1920 (TypesEqual(arguments[1]->GetType()->PlainType(span, moduleId), interfaceType) || arguments[1]->GetType()->PlainType(span, moduleId)->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(interfaceType, span, moduleId);
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>>&arguments, BoundFunction*currentFunction,
1946 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1947 private:
1948 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 2, boundCompileUnit_)
1953 {
1954 }
1955
1956 void InterfaceMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1957 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
1958 {
1959 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
1960 TypeSymbol* type = arguments[0]->GetType();
1961 if (type->PointerCount() != 1 || type->RemovePointer(span, moduleId)->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(span, moduleId));
1968 if (TypesEqual(arguments[1]->GetType(), interfaceType->AddRvalueReference(span, moduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1969 {
1970 FunctionSymbol* function = functionMap[interfaceType->TypeId()];
1971 if (!function)
1972 {
1973 function = new InterfaceTypeMoveConstructor(interfaceType, span, moduleId);
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>>&arguments, BoundFunction*currentFunction,
1988 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
1989 private:
1990 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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=", 2, boundCompileUnit_)
1995 {
1996 }
1997
1998 void InterfaceCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
1999 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2000 {
2001 TypeSymbol* type = arguments[0]->GetType();
2002 if (type->PointerCount() != 1 || type->RemovePointer(span, moduleId)->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(span, moduleId));
2009 if (((flags & CollectFlags::noRvalueRef) != CollectFlags::none ||
2010 !TypesEqual(arguments[1]->GetType(), interfaceType->AddRvalueReference(span, moduleId)) && !arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference)) &&
2011 TypesEqual(arguments[1]->GetType()->PlainType(span, moduleId), interfaceType))
2012 {
2013 FunctionSymbol* function = functionMap[interfaceType->TypeId()];
2014 if (!function)
2015 {
2016 function = new InterfaceTypeCopyAssignment(interfaceType, span, moduleId);
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>>&arguments, BoundFunction*currentFunction,
2031 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
2032 private:
2033 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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=", 2, boundCompileUnit_)
2038 {
2039 }
2040
2041 void InterfaceMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2042 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2043 {
2044 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
2045 TypeSymbol* type = arguments[0]->GetType();
2046 if (type->PointerCount() != 1 || type->RemovePointer(span, moduleId)->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(span, moduleId));
2053 if (TypesEqual(arguments[1]->GetType(), interfaceType->AddRvalueReference(span, moduleId)) || arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference))
2054 {
2055 FunctionSymbol* function = functionMap[interfaceType->TypeId()];
2056 if (!function)
2057 {
2058 function = new InterfaceTypeMoveAssignment(interfaceType, span, moduleId);
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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2096 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
2097 bool GenerateImplementation(ClassDefaultConstructor* defaultConstructor, ContainerScope* containerScope, BoundFunction* currentFunction, std::std::unique_ptr<Exception>&exception,
2098 const Span& span, const boost::uuids::uuid& moduleId);
2099 private:
2100 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 1, boundCompileUnit_)
2105 {
2106 }
2107
2108 void ClassDefaultConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2109 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2110 {
2111 TypeSymbol* type = arguments[0]->GetType();
2112 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->PlainType(span, moduleId)->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", span, moduleId, classType->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(), containerScope, currentFunction, exception, span, moduleId))
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* defaultConstructor, ContainerScope* containerScope, BoundFunction* currentFunction,
2153 std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::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(span, moduleId)));
2165 if (classType->StaticConstructor())
2166 {
2167 boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(
2168 new BoundFunctionCall(span, moduleId, classType->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_parent, containerScope));
2175 baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
2176 baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2181 if (!thisToBaseConversion)
2182 {
2183 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2184 }
2185 BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), thisToBaseConversion);
2186 baseConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
2187 std::unique_ptr<BoundFunctionCall> baseConstructorCall = ResolveOverload(U"@constructor", containerScope, baseConstructorCallLookups, baseConstructorCallArguments, GetBoundCompileUnit(),
2188 boundFunction.get(), span, moduleId);
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(span, moduleId, thisParam);
2200 }
2201 else
2202 {
2203 ArgumentMatch argumentMatch;
2204 FunctionSymbol* thisToHolderConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType(), vmtPtrHolderClass->AddPointer(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2205 if (!thisToHolderConversion)
2206 {
2207 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2208 }
2209 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), 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_parent, containerScope));
2219 memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2220 memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
2221 std::vector<std::std::unique_ptr<BoundExpression>>memberConstructorCallArguments;
2222 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
2223 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, defaultConstructor->GetThisParam())));
2224 memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
2225 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
2226 std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor", containerScope, memberConstructorCallLookups, memberConstructorCallArguments,
2227 GetBoundCompileUnit(), boundFunction.get(), span, moduleId);
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<Span, boost::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(), span, moduleId, references));
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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2280 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
2281 bool GenerateImplementation(ClassCopyConstructor* copyConstructor, ContainerScope* containerScope, BoundFunction* currentFunction, std::std::unique_ptr<Exception>&exception,
2282 const Span& span, const 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::uuid, FunctionSymbol*, 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", 2, boundCompileUnit_)
2290 {
2291 }
2292
2293 void ClassCopyConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2294 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2295 {
2296 TypeSymbol* type = arguments[0]->GetType();
2297 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->PlainType(span, moduleId)->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", span, moduleId, classType->GetSpan(), classType->SourceModuleId()));
2302 return;
2303 }
2304 TypeSymbol* rightType = arguments[1]->GetType()->PlainType(span, moduleId);
2305 bool typesEqual = TypesEqual(rightType, classType);
2306 bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2307 bool conversionFunctionExists = false;
2308 if (!typesEqual)
2309 {
2310 ArgumentMatch argumentMatch;
2311 FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightType, classType, containerScope, currentFunction, span, moduleId, argumentMatch);
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(span, moduleId)) && !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(), containerScope, currentFunction, exception, span, moduleId))
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* copyConstructor, ContainerScope* containerScope, BoundFunction* currentFunction,
2369 std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::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(span, moduleId)));
2377 if (classType->StaticConstructor())
2378 {
2379 boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(new BoundFunctionCall(span, moduleId,
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_parent, containerScope));
2387 baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
2388 baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2393 if (!thisToBaseConversion)
2394 {
2395 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2396 }
2397 BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), 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(span, moduleId)->AddLvalueReference(span, moduleId), containerScope,
2401 currentFunction, span, moduleId, argumentMatch);
2402 if (!thatToBaseConversion)
2403 {
2404 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2405 }
2406 BoundExpression* thatArgumentConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatToBaseConversion);
2407 baseConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(thatArgumentConversion));
2408 std::unique_ptr<BoundFunctionCall> baseConstructorCall = ResolveOverload(U"@constructor", containerScope, baseConstructorCallLookups, baseConstructorCallArguments, GetBoundCompileUnit(),
2409 boundFunction.get(), span, moduleId);
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(span, moduleId, thisParam);
2421 }
2422 else
2423 {
2424 ArgumentMatch argumentMatch;
2425 FunctionSymbol* thisToHolderConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType(), vmtPtrHolderClass->AddPointer(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2426 if (!thisToHolderConversion)
2427 {
2428 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2429 }
2430 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), 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_parent, containerScope));
2440 memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2441 memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
2442 std::vector<std::std::unique_ptr<BoundExpression>>memberConstructorCallArguments;
2443 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
2444 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, copyConstructor->GetThisParam())));
2445 memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
2446 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
2447 ParameterSymbol* thatParam = copyConstructor->Parameters()[1];
2448 BoundMemberVariable* thatBoundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
2449 thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
2450 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatParam->GetType()->BaseType()->AddPointer(span, moduleId))));
2451 memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(thatBoundMemberVariable));
2452 std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor", containerScope, memberConstructorCallLookups, memberConstructorCallArguments,
2453 GetBoundCompileUnit(), boundFunction.get(), span, moduleId);
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<Span, boost::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(), span, moduleId, references));
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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2506 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
2507 bool GenerateImplementation(ClassMoveConstructor* moveConstructor, ContainerScope* containerScope, BoundFunction* currentFunction, std::std::unique_ptr<Exception>&exception, constSpan&span,
2508 const boost::uuids::uuid& moduleId);
2509 private:
2510 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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", 2, boundCompileUnit_)
2515 {
2516 }
2517
2518 void ClassMoveConstructorOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2519 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2520 {
2521 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
2522 TypeSymbol* type = arguments[0]->GetType();
2523 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->PlainType(span, moduleId)->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", span, moduleId, classType->GetSpan(), classType->SourceModuleId()));
2528 return;
2529 }
2530 TypeSymbol* rightType = arguments[1]->GetType()->PlainType(span, moduleId);
2531 bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2532 bool typesEqual = TypesEqual(arguments[1]->GetType(), classType->AddRvalueReference(span, moduleId));
2533 if (!typesEqual)
2534 {
2535 ArgumentMatch argumentMatch;
2536 FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightType, classType, containerScope, currentFunction, span, moduleId, argumentMatch);
2537 if (conversion && conversion->GetSymbolType() == SymbolType::conversionFunctionSymbol)
2538 {
2539 if (conversion->ReturnsClassInterfaceOrClassDelegateByValue())
2540 {
2541 bindToRvalueRef = true;
2542 }
2543 }
2544 else if (!TypesEqual(rightType, classType))
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(), containerScope, currentFunction, exception, span, moduleId))
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* moveConstructor, ContainerScope* containerScope, BoundFunction* currentFunction,
2586 std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::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(span, moduleId)));
2594 if (classType->StaticConstructor())
2595 {
2596 boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(new BoundFunctionCall(span, moduleId,
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_parent, containerScope));
2604 baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
2605 baseConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2610 if (!thisToBaseConversion)
2611 {
2612 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2613 }
2614 std::unique_ptr<BoundExpression> baseClassPointerConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), thisToBaseConversion));
2615 baseConstructorCallArguments.push_back(std::move(baseClassPointerConversion));
2616 ParameterSymbol* thatParam = moveConstructor->Parameters()[1];
2617 FunctionSymbol* thatToBaseConversion = GetBoundCompileUnit().GetConversion(thatParam->GetType(), classType->BaseClass()->AddRvalueReference(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2618 if (!thatToBaseConversion)
2619 {
2620 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2621 }
2622 std::unique_ptr<BoundExpression> thatArgumentConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatToBaseConversion));
2623 baseConstructorCallArguments.push_back(std::move(thatArgumentConversion));
2624 std::unique_ptr<BoundFunctionCall> baseConstructorCall = ResolveOverload(U"@constructor", containerScope, baseConstructorCallLookups, baseConstructorCallArguments, GetBoundCompileUnit(),
2625 boundFunction.get(), span, moduleId);
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(span, moduleId, thisParam);
2637 }
2638 else
2639 {
2640 ArgumentMatch argumentMatch;
2641 FunctionSymbol* thisToHolderConversion = GetBoundCompileUnit().GetConversion(thisParam->GetType(), vmtPtrHolderClass->AddPointer(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2642 if (!thisToHolderConversion)
2643 {
2644 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2645 }
2646 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), 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_parent, containerScope));
2656 memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2657 memberConstructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
2658 std::vector<std::std::unique_ptr<BoundExpression>>memberConstructorCallArguments;
2659 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
2660 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, moveConstructor->GetThisParam())));
2661 memberConstructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
2662 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
2663 ParameterSymbol* thatParam = moveConstructor->Parameters()[1];
2664 std::unique_ptr<BoundMemberVariable> thatBoundMemberVariable(new BoundMemberVariable(span, moduleId, memberVariableSymbol));
2665 thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
2666 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatParam->GetType()->BaseType()->AddPointer(span, moduleId))));
2667 std::vector<FunctionScopeLookup> rvalueLookups;
2668 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
2669 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, containerScope));
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", containerScope, rvalueLookups, rvalueArguments, GetBoundCompileUnit(), boundFunction.get(), span,
2673 moduleId);
2674 memberConstructorCallArguments.push_back(std::move(rvalueMemberCall));
2675 std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor", containerScope, memberConstructorCallLookups, memberConstructorCallArguments,
2676 GetBoundCompileUnit(), boundFunction.get(), span, moduleId);
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<Span, boost::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(), span, moduleId, references));
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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2731 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
2732 bool GenerateImplementation(ClassCopyAssignment* copyAssignment, ContainerScope* containerScope, BoundFunction* currentFunction, std::std::unique_ptr<Exception>&exception, constSpan&span,
2733 const boost::uuids::uuid& moduleId);
2734 private:
2735 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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=", 2, boundCompileUnit_)
2740 {
2741 }
2742
2743 void ClassCopyAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2744 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2745 {
2746 TypeSymbol* type = arguments[0]->GetType();
2747 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->PlainType(span, moduleId)->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", span, moduleId, classType->GetSpan(), classType->SourceModuleId()));
2752 return;
2753 }
2754 TypeSymbol* rightType = arguments[1]->GetType()->PlainType(span, moduleId);
2755 bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2756 bool conversionFunctionExists = false;
2757 bool typesEqual = TypesEqual(rightType, classType);
2758 if (!typesEqual)
2759 {
2760 ArgumentMatch argumentMatch;
2761 FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightType, classType, containerScope, currentFunction, span, moduleId, argumentMatch);
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(span, moduleId)) && !bindToRvalueRef) && (TypesEqual(rightType, classType) || 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(classType, GetBoundCompileUnit().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(), containerScope, currentFunction, exception, span, moduleId))
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* copyAssignment, ContainerScope* containerScope, BoundFunction* currentFunction,
2809 std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::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(span, moduleId)));
2817 if (classType->BaseClass())
2818 {
2819 std::vector<FunctionScopeLookup> baseAssignmentCallLookups;
2820 baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, containerScope));
2821 baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
2822 baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
2827 if (!thisToBaseConversion)
2828 {
2829 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2830 }
2831 BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), 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(span, moduleId)->AddLvalueReference(span, moduleId), containerScope,
2835 currentFunction, span, moduleId, argumentMatch);
2836 if (!thatToBaseConversion)
2837 {
2838 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
2839 }
2840 BoundExpression* thatArgumentConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatToBaseConversion);
2841 baseAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(thatArgumentConversion));
2842 std::unique_ptr<BoundFunctionCall> baseAssignmentCall = ResolveOverload(U"operator=", containerScope, baseAssignmentCallLookups, baseAssignmentCallArguments, GetBoundCompileUnit(),
2843 boundFunction.get(), span, moduleId);
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_parent, containerScope));
2853 memberAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
2854 memberAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
2855 std::vector<std::std::unique_ptr<BoundExpression>>memberAssignmentCallArguments;
2856 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
2857 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, copyAssignment->GetThisParam())));
2858 memberAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(
2859 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
2860 ParameterSymbol* thatParam = copyAssignment->Parameters()[1];
2861 BoundMemberVariable* thatBoundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
2862 thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
2863 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatParam->GetType()->BaseType()->AddPointer(span, moduleId))));
2864 memberAssignmentCallArguments.push_back(std::unique_ptr<BoundExpression>(thatBoundMemberVariable));
2865 std::unique_ptr<BoundFunctionCall> memberAssignmentCall = ResolveOverload(U"operator=", containerScope, memberAssignmentCallLookups, memberAssignmentCallArguments,
2866 GetBoundCompileUnit(), boundFunction.get(), span, moduleId);
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<Span, boost::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(), span, moduleId, references));
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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2921 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags) override;
2922 bool GenerateImplementation(ClassMoveAssignment* moveAssignment, ContainerScope* containerScope, BoundFunction* currentFunction, std::std::unique_ptr<Exception>&exception, constSpan&span,
2923 const boost::uuids::uuid& moduleId);
2924 private:
2925 std::unordered_map<boost::uuids::uuid, FunctionSymbol*, 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=", 2, boundCompileUnit_)
2930 {
2931 }
2932
2933 void ClassMoveAssignmentOperation::CollectViableFunctions(ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
2934 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
2935 {
2936 if ((flags & CollectFlags::noRvalueRef) != CollectFlags::none) return;
2937 TypeSymbol* type = arguments[0]->GetType();
2938 if (type->PointerCount() != 1 || !type->RemovePointer(span, moduleId)->PlainType(span, moduleId)->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", span, moduleId, classType->GetSpan(), classType->SourceModuleId()));
2943 return;
2944 }
2945 TypeSymbol* rightType = arguments[1]->GetType()->PlainType(span, moduleId);
2946 bool bindToRvalueRef = arguments[1]->GetFlag(BoundExpressionFlags::bindToRvalueReference);
2947 bool typesEqual = TypesEqual(arguments[1]->GetType(), classType->AddRvalueReference(span, moduleId));
2948 if (!typesEqual)
2949 {
2950 ArgumentMatch argumentMatch;
2951 FunctionSymbol* conversion = GetBoundCompileUnit().GetConversion(rightType, classType, containerScope, currentFunction, span, moduleId, argumentMatch);
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(classType, GetBoundCompileUnit().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(), containerScope, currentFunction, exception, span, moduleId))
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* moveAssignment, ContainerScope* containerScope, BoundFunction* currentFunction,
2997 std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::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(span, moduleId)));
3005 if (classType->BaseClass())
3006 {
3007 std::vector<FunctionScopeLookup> baseAssignmentCallLookups;
3008 baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, containerScope));
3009 baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3010 baseAssignmentCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
3015 if (!thisToBaseConversion)
3016 {
3017 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
3018 }
3019 std::unique_ptr<BoundExpression> baseClassPointerConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), thisToBaseConversion));
3020 baseAssignmentCallArguments.push_back(std::move(baseClassPointerConversion));
3021 ParameterSymbol* thatParam = moveAssignment->Parameters()[1];
3022 FunctionSymbol* thatToBaseConversion = GetBoundCompileUnit().GetConversion(thatParam->GetType(), classType->BaseClass()->AddRvalueReference(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
3023 if (!thatToBaseConversion)
3024 {
3025 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
3026 }
3027 std::unique_ptr<BoundExpression> thatArgumentConversion(new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatToBaseConversion));
3028 baseAssignmentCallArguments.push_back(std::move(thatArgumentConversion));
3029 std::unique_ptr<BoundFunctionCall> baseAssignmentCall = ResolveOverload(U"operator=", containerScope, baseAssignmentCallLookups, baseAssignmentCallArguments, GetBoundCompileUnit(),
3030 boundFunction.get(), span, moduleId);
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(span, moduleId, memberVariableSymbol));
3039 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, moveAssignment->GetThisParam())));
3040 ParameterSymbol* thatParam = moveAssignment->Parameters()[1];
3041 std::unique_ptr<BoundMemberVariable> thatBoundMemberVariable(new BoundMemberVariable(span, moduleId, memberVariableSymbol));
3042 thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
3043 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thatParam)), thatParam->GetType()->BaseType()->AddPointer(span, moduleId))));
3044 std::vector<FunctionScopeLookup> swapLookups;
3045 swapLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3046 swapLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, containerScope));
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", containerScope, swapLookups, swapArguments, GetBoundCompileUnit(), boundFunction.get(), span, moduleId);
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<Span, boost::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(), span, moduleId, references));
3066 return false;
3067 }
3068 return true;
3069 }
3070
3071 void GenerateDestructorImplementation(BoundClass* boundClass, DestructorSymbol* destructorSymbol, BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope, BoundFunction* currentFunction,
3072 const Span& span, const boost::uuids::uuid& moduleId)
3073 {
3074 ClassTypeSymbol* classType = boundClass->GetClassTypeSymbol();
3075 try
3076 {
3077 std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnit, destructorSymbol));
3078 boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(new BoundCompoundStatement(span, moduleId)));
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(span, moduleId, thisParam);
3087 }
3088 else
3089 {
3090 ArgumentMatch argumentMatch;
3091 FunctionSymbol* thisToHolderConversion = boundCompileUnit.GetConversion(thisParam->GetType(), vmtPtrHolderClass->AddPointer(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
3092 if (!thisToHolderConversion)
3093 {
3094 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
3095 }
3096 classPtr = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), 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_parent, containerScope));
3108 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->ClassInterfaceOrNsScope()));
3109 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3110 std::vector<std::std::unique_ptr<BoundExpression>>memberDestructorCallArguments;
3111 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3112 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, destructorSymbol->GetThisParam())));
3113 memberDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
3114 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
3115 std::unique_ptr<BoundFunctionCall> memberDestructorCall = ResolveOverload(U"@destructor", containerScope, memberDestructorCallLookups, memberDestructorCallArguments,
3116 boundCompileUnit, boundFunction.get(), span, moduleId);
3117 boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(memberDestructorCall), span, moduleId)));
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_parent, containerScope));
3124 baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3125 baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
3130 if (!thisToBaseConversion)
3131 {
3132 throw Exception("base class conversion not found", span, moduleId, classType->GetSpan(), classType->SourceModuleId());
3133 }
3134 BoundExpression* baseClassPointerConversion = new BoundConversion(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)), thisToBaseConversion);
3135 baseDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3136 std::unique_ptr<BoundFunctionCall> baseDestructorCall = ResolveOverload(U"@destructor", containerScope, baseDestructorCallLookups, baseDestructorCallArguments, boundCompileUnit,
3137 boundFunction.get(), span, moduleId);
3138 boundFunction->Body()->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(baseDestructorCall), span, moduleId)));
3139 }
3140 boundClass->AddMember(std::move(boundFunction));
3141 }
3142 catch (const Exception& ex;)
3143 {
3144 std::vector<std::std::pair<Span, boost::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(), span, moduleId, references);
3148 }
3149 }
3150
3151 BoundExpression* MakeExitEntryPtr(BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope, const Span& span, const 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(span, moduleId, Specifiers::private_, new DotNode(span, moduleId, new IdentifierNode(span, moduleId, U"System"),
3166 new IdentifierNode(span, moduleId, U"ExitEntry")),
3167 new IdentifierNode(span, moduleId, U"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(span, moduleId));
3174 }
3175 else
3176 {
3177 throw Exception("System.ExitEntry expected to denote a type", span, moduleId);
3178 }
3179 }
3180 else
3181 {
3182 throw Exception("System.ExitEntry symbol not found", span, moduleId);
3183 }
3184 }
3185
3186 void GenerateStaticClassInitialization(StaticConstructorSymbol* staticConstructorSymbol, StaticConstructorNode* staticConstructorNode, BoundCompileUnit& boundCompileUnit,
3187 BoundCompoundStatement* boundCompoundStatement, BoundFunction* boundFunction, ContainerScope* containerScope, StatementBinder* statementBinder, const Span& span, const 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(span, moduleId, std::unique_ptr<BoundExpression>(new BoundMemberVariable(span, moduleId, classType->InitializedVar())),
3196 std::unique_ptr<BoundStatement>(new BoundReturnStatement(std::unique_ptr<BoundFunctionCall>(nullptr), span, moduleId)), std::unique_ptr<BoundStatement>(nullptr)));
3197 boundCompoundStatement->AddStatement(std::move(ifStatement));
3198 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
3199 {
3200 IdentifierNode staticInitCriticalSection(span, moduleId, U"System.Runtime.StaticInitCriticalSection");
3201 TypeSymbol* staticInitCriticalSectionClassType = ResolveType(&staticInitCriticalSection, boundCompileUnit, containerScope);
3202 std::vector<FunctionScopeLookup> constructorLookups;
3203 constructorLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, containerScope));
3204 constructorLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, staticInitCriticalSectionClassType->ClassInterfaceOrNsScope()));
3205 constructorLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId, staticConstructorSymbol->CreateTemporary(staticInitCriticalSectionClassType, span, moduleId))),
3209 staticInitCriticalSectionClassType->AddPointer(span, moduleId))));
3210 constructorArguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new UuidValue(span, moduleId,
3211 boundCompileUnit.Install(classType->TypeId()))), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3212 std::unique_ptr<BoundConstructionStatement> constructionStatement(new BoundConstructionStatement(
3213 ResolveOverload(U"@constructor", containerScope, constructorLookups, constructorArguments, boundCompileUnit, boundFunction, span, moduleId), span, moduleId));
3214 boundCompoundStatement->AddStatement(std::move(constructionStatement));
3215 std::unique_ptr<BoundIfStatement> ifStatement2(new BoundIfStatement(span, moduleId, std::unique_ptr<BoundExpression>(new BoundMemberVariable(span, moduleId, classType->InitializedVar())),
3216 std::unique_ptr<BoundStatement>(new BoundReturnStatement(std::unique_ptr<BoundFunctionCall>(nullptr), span, moduleId)), 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_parent, containerScope));
3221 assignmentLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId, classType->InitializedVar())),
3224 classType->InitializedVar()->GetType()->AddPointer(span, moduleId))));
3225 assignmentArguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new BoolValue(span, moduleId, true)),
3226 boundCompileUnit.GetSymbolTable().GetTypeByName(U"bool"))));
3227 std::unique_ptr<BoundAssignmentStatement> assignmentStatement(new BoundAssignmentStatement(
3228 ResolveOverload(U"operator=", containerScope, assignmentLookups, assignmentArguments, boundCompileUnit, boundFunction, span, moduleId), span, moduleId));
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(span, moduleId, baseClass->StaticConstructor())))));
3237 }
3238 }
3239 std::unordered_map<std::u32string, MemberInitializerNode*> 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_parent, containerScope));
3275 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3276 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3277 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3278 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3279 std::unique_ptr<BoundExpression> addrOfBoundMemberVariable(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable),
3280 boundMemberVariable->GetType()->AddPointer(span, moduleId)));
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(argumentNode, boundCompileUnit, boundFunction, containerScope, statementBinder);
3294 arguments.push_back(std::move(argument));
3295 }
3296 std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3297 span, moduleId);
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_parent, containerScope));
3306 enqueueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId,
3309 memberVariableClassTypeWithDestructor->Destructor(), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))),
3310 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3311 enqueueArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2),
3312 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3313 const char32_t* enqueueDestructorFunction = U"RtEnqueueDestruction";
3314 std::unique_ptr<BoundFunctionCall> enqueueDestructorCall = ResolveOverload(enqueueDestructorFunction, containerScope, enqueueLookups, enqueueArguments, boundCompileUnit,
3315 boundFunction, span, moduleId);
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_parent, containerScope));
3322 atExitLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3323 std::vector<std::std::unique_ptr<BoundExpression>>atExitArguments;
3324 atExitArguments.push_back(std::unique_ptr<BoundExpression>(MakeExitEntryPtr(boundCompileUnit, containerScope, span, moduleId)));
3325 atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::unique_ptr<BoundExpression>(new BoundFunctionPtr(span, moduleId,
3326 memberVariableClassTypeWithDestructor->Destructor(), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))),
3327 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3328 atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2),
3329 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3330 const char32_t* atExitFunction = U"at_exit";
3331 std::unique_ptr<BoundFunctionCall> atExitCall = ResolveOverload(atExitFunction, containerScope, atExitLookups, atExitArguments, boundCompileUnit,
3332 boundFunction, span, moduleId);
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_parent, containerScope));
3341 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3342 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3343 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3344 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3345 std::unique_ptr<BoundExpression> addrOfBoundMemberVariable(
3346 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId)));
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", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3356 span, moduleId);
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_parent, containerScope));
3365 enqueueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(span, moduleId,
3368 memberVariableClassTypeWithDestructor->Destructor(), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))),
3369 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3370 enqueueArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2),
3371 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3372 const char32_t* enqueueDestructorFunction = U"RtEnqueueDestruction";
3373 std::unique_ptr<BoundFunctionCall> enqueueDestructorCall = ResolveOverload(enqueueDestructorFunction, containerScope, enqueueLookups, enqueueArguments, boundCompileUnit,
3374 boundFunction, span, moduleId);
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_parent, containerScope));
3381 atExitLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3382 std::vector<std::std::unique_ptr<BoundExpression>>atExitArguments;
3383 atExitArguments.push_back(std::unique_ptr<BoundExpression>(MakeExitEntryPtr(boundCompileUnit, containerScope, span, moduleId)));
3384 atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::unique_ptr<BoundExpression>(new BoundFunctionPtr(span, moduleId,
3385 memberVariableClassTypeWithDestructor->Destructor(), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))),
3386 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3387 atExitArguments.push_back(std::unique_ptr<BoundExpression>(new BoundBitCast(std::move(addrOfBoundMemberVariable2),
3388 boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId))));
3389 const char32_t* atExitFunction = U"at_exit";
3390 std::unique_ptr<BoundFunctionCall> atExitCall = ResolveOverload(atExitFunction, containerScope, atExitLookups, atExitArguments, boundCompileUnit,
3391 boundFunction, span, moduleId);
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<Span, boost::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* constructorSymbol, ConstructorNode* constructorNode, BoundCompoundStatement* boundCompoundStatement, BoundFunction* boundFunction,
3409 BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope, StatementBinder* statementBinder, bool generateDefault, const Span& span, const 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", span, moduleId);
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(span, moduleId,
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::u32string, MemberInitializerNode*> 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_parent, containerScope));
3477 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->GetContainerScope()));
3478 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3479 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3480 arguments.push_back(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
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(argumentNode, boundCompileUnit, boundFunction, containerScope, statementBinder);
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", containerScope, lookups, arguments, boundCompileUnit, boundFunction, span, moduleId,
3496 flags, templateArgumentTypes, exception);
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_parent, containerScope));
3509 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3510 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3511 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3512 ArgumentMatch argumentMatch;
3513 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType(), classType->BaseClass()->AddPointer(span, moduleId), containerScope, boundFunction,
3514 span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), 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(argumentNode, boundCompileUnit, boundFunction, containerScope, statementBinder);
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", containerScope, lookups, arguments, boundCompileUnit, boundFunction, span, moduleId,
3536 flags, templateArgumentTypes, exception);
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_parent, containerScope));
3544 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3545 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3546 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3547 ArgumentMatch argumentMatch;
3548 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType(), classType->BaseClass()->AddPointer(span, moduleId), containerScope, boundFunction,
3549 span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), 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(span, moduleId)->AddLvalueReference(span, moduleId), containerScope, boundFunction, span, moduleId, argumentMatch);
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(span, moduleId, thatParam)), 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", containerScope, lookups, arguments, boundCompileUnit, boundFunction, span, moduleId,
3578 flags, templateArgumentTypes, exception);
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(span, moduleId, thisParam);
3589 }
3590 else
3591 {
3592 ArgumentMatch argumentMatch;
3593 FunctionSymbol* thisToHolderConversion = boundCompileUnit.GetConversion(thisParam->GetType(), vmtPtrHolderClass->AddPointer(span, moduleId), containerScope, boundFunction,
3594 span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), 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_parent, containerScope));
3614 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3615 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3616 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3617 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3618 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
3619 arguments.push_back(std::unique_ptr<BoundExpression>(
3620 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
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(argumentNode, boundCompileUnit, boundFunction, containerScope, statementBinder);
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", containerScope, lookups, arguments, boundCompileUnit, boundFunction, span, moduleId,
3632 flags, templateArgumentTypes, exception);
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_parent, containerScope));
3642 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3643 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3644 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3645 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3646 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
3647 arguments.push_back(std::unique_ptr<BoundExpression>(
3648 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
3649 CloneContext cloneContext;
3650 DotNode thatMemberVarNode(span, moduleId, constructorNode->Parameters()[0]->Clone(cloneContext),
3651 new IdentifierNode(span, moduleId, memberVariableSymbol->Name()));
3652 std::unique_ptr<BoundExpression> thatMemberVarArgument = BindExpression(&thatMemberVarNode, boundCompileUnit, boundFunction, containerScope, statementBinder);
3653 arguments.push_back(std::move(thatMemberVarArgument));
3654 std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3655 span, moduleId);
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_parent, containerScope));
3663 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3664 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3665 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3666 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3667 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
3668 arguments.push_back(std::unique_ptr<BoundExpression>(
3669 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
3670 ParameterSymbol* thatParam = constructorSymbol->Parameters()[1];
3671 std::unique_ptr<BoundMemberVariable> thatBoundMemberVariable(new BoundMemberVariable(span, moduleId, memberVariableSymbol));
3672 thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(
3673 new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(
3674 new BoundParameter(span, moduleId, thatParam)), thatParam->GetType()->BaseType()->AddPointer(span, moduleId))));
3675 std::vector<FunctionScopeLookup> rvalueLookups;
3676 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3677 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, containerScope));
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", containerScope, rvalueLookups, rvalueArguments, boundCompileUnit, boundFunction,
3681 span, moduleId);
3682 arguments.push_back(std::move(rvalueMemberCall));
3683 std::unique_ptr<BoundFunctionCall> memberConstructorCall = ResolveOverload(U"@constructor", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3684 span, moduleId);
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_parent, containerScope));
3692 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3693 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3694 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3695 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3696 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
3697 arguments.push_back(std::unique_ptr<BoundExpression>(
3698 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
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", containerScope, lookups, arguments, boundCompileUnit, boundFunction, span, moduleId,
3707 flags, templateArgumentTypes, exception);
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<Span, boost::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* assignmentFunctionSymbol, MemberFunctionNode* assignmentNode, BoundCompoundStatement* boundCompoundStatement, BoundFunction* boundFunction,
3731 BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope, StatementBinder* statementBinder, bool generateDefault, const Span& span, const 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", span, moduleId);
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_parent, containerScope));
3753 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3754 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3755 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3756 ArgumentMatch argumentMatch;
3757 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType(), classType->BaseClass()->AddPointer(span, moduleId), containerScope, boundFunction,
3758 span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), 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(span, moduleId)->AddLvalueReference(span, moduleId), containerScope, boundFunction, span, moduleId, argumentMatch);
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(span, moduleId, thatParam)), thatToBaseConversion);
3773 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassReferenceConversion));
3774 std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator=", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3775 span, moduleId);
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_parent, containerScope));
3787 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3788 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3789 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3790 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3791 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
3792 arguments.push_back(std::unique_ptr<BoundExpression>(
3793 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
3794 CloneContext cloneContext;
3795 DotNode thatMemberVarNode(span, moduleId, assignmentNode->Parameters()[0]->Clone(cloneContext),
3796 new IdentifierNode(span, moduleId, memberVariableSymbol->Name()));
3797 std::unique_ptr<BoundExpression> thatMemberVarArgument = BindExpression(&thatMemberVarNode, boundCompileUnit, boundFunction, containerScope, statementBinder);
3798 arguments.push_back(std::move(thatMemberVarArgument));
3799 std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator=", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3800 span, moduleId);
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_parent, containerScope));
3812 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3813 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3814 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3815 ArgumentMatch argumentMatch;
3816 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType(), classType->BaseClass()->AddPointer(span, moduleId), containerScope,
3817 boundFunction, span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), 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(span, moduleId), containerScope, boundFunction, span, moduleId, argumentMatch);
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(span, moduleId, thatParam)), thatToBaseConversion);
3832 arguments.push_back(std::unique_ptr<BoundExpression>(baseClassReferenceConversion));
3833 std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator=", containerScope, lookups, arguments, boundCompileUnit, boundFunction,
3834 span, moduleId);
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_parent, containerScope));
3846 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->GetContainerScope()));
3847 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3848 std::vector<std::std::unique_ptr<BoundExpression>>arguments;
3849 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3850 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, thisParam)));
3851 arguments.push_back(std::unique_ptr<BoundExpression>(boundMemberVariable));
3852 BoundMemberVariable* thatBoundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3853 ParameterSymbol* thatParam = assignmentFunctionSymbol->Parameters()[1];
3854 TypeSymbol* thatPtrType = thatParam->GetType()->RemoveReference(span, moduleId)->AddPointer(span, moduleId);
3855 thatBoundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(
3856 new BoundParameter(span, moduleId, thatParam)), thatPtrType)));
3857 arguments.push_back(std::unique_ptr<BoundExpression>(thatBoundMemberVariable));
3858 std::unique_ptr<BoundFunctionCall> swapCall = ResolveOverload(U"System.Swap", containerScope, lookups, arguments, boundCompileUnit, boundFunction, span, moduleId);
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<Span, boost::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* destructorSymbol, DestructorNode* destructorNode, BoundCompoundStatement* boundCompoundStatement, BoundFunction* boundFunction,
3874 BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope, StatementBinder* statementBinder, const Span& span, const 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(span, moduleId, thisParam);
3891 }
3892 else
3893 {
3894 ArgumentMatch argumentMatch;
3895 FunctionSymbol* thisToHolderConversion = boundCompileUnit.GetConversion(thisParam->GetType(), vmtPtrHolderClass->AddPointer(span, moduleId), containerScope, boundFunction,
3896 span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), 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_parent, containerScope));
3913 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, memberVariableSymbol->GetType()->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
3914 memberDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3915 std::vector<std::std::unique_ptr<BoundExpression>>memberDestructorCallArguments;
3916 BoundMemberVariable* boundMemberVariable = new BoundMemberVariable(span, moduleId, memberVariableSymbol);
3917 boundMemberVariable->SetClassPtr(std::unique_ptr<BoundExpression>(new BoundParameter(span, moduleId, destructorSymbol->GetThisParam())));
3918 memberDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(
3919 new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(boundMemberVariable), boundMemberVariable->GetType()->AddPointer(span, moduleId))));
3920 std::unique_ptr<BoundFunctionCall> memberDestructorCall = ResolveOverload(U"@destructor", containerScope, memberDestructorCallLookups, memberDestructorCallArguments,
3921 boundCompileUnit, boundFunction, span, moduleId);
3922 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(memberDestructorCall), span, moduleId)));
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_parent, containerScope));
3929 baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->BaseClass()->GetContainerScope()));
3930 baseDestructorCallLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
3931 std::vector<std::std::unique_ptr<BoundExpression>>baseDestructorCallArguments;
3932 ArgumentMatch argumentMatch;
3933 FunctionSymbol* thisToBaseConversion = boundCompileUnit.GetConversion(thisParam->GetType(), classType->BaseClass()->AddPointer(span, moduleId), containerScope, boundFunction,
3934 span, moduleId, argumentMatch);
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(span, moduleId, thisParam)), thisToBaseConversion);
3940 baseDestructorCallArguments.push_back(std::unique_ptr<BoundExpression>(baseClassPointerConversion));
3941 std::unique_ptr<BoundFunctionCall> baseDestructorCall = ResolveOverload(U"@destructor", containerScope, baseDestructorCallLookups, baseDestructorCallArguments, boundCompileUnit,
3942 boundFunction, span, moduleId);
3943 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundExpressionStatement(std::move(baseDestructorCall), span, moduleId)));
3944 }
3945 }
3946 catch (const Exception& ex;)
3947 {
3948 std::vector<std::std::pair<Span, boost::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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
3979 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
3980 {
3981 for (Operation* operation : operations)
3982 {
3983 operation->CollectViableFunctions(containerScope, arguments, currentFunction, viableFunctions, exception, span, moduleId, flags);
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* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundFunction*currentFunction,
4004 ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags 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(containerScope, arguments, currentFunction, viableFunctions, exception, span, moduleId, flags);
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& groupName, ContainerScope* containerScope, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments,
4077 BoundFunction* currentFunction, ViableFunctionSet& viableFunctions, std::std::unique_ptr<Exception>&exception, constSpan&span, constboost::uuids::uuid&moduleId, CollectFlags flags)
4078 {
4079 auto it = operationGroupMap.find(groupName);
4080 if (it != operationGroupMap.cend())
4081 {
4082 OperationGroup* operationGroup = it->second;
4083 operationGroup->CollectViableFunctions(containerScope, arguments, currentFunction, viableFunctions, exception, span, moduleId, flags);
4084 }
4085 }
4086
4087 void OperationRepository::GenerateCopyConstructorFor(ClassTypeSymbol* classTypeSymbol, ContainerScope* containerScope, BoundFunction* currentFunction, const Span& span, const 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(), containerScope, currentFunction, exception, span, moduleId))
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()) + "'", span, moduleId);
4111 }
4112 }
4113 }
4114
4115 void OperationRepository::GenerateCopyConstructorFor(InterfaceTypeSymbol* interfaceTypeSymbol, ContainerScope* containerScope, BoundFunction* currentFunction, const Span& span, const boost::uuids::uuid& moduleId)
4116 {
4117 if (boundCompileUnit.HasCopyConstructorFor(interfaceTypeSymbol->TypeId())) return;
4118 std::unique_ptr<InterfaceTypeCopyConstructor> copyConstructor(new InterfaceTypeCopyConstructor(interfaceTypeSymbol, span, moduleId));
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 } }