1
2
3
4
5
6 #include <cmajor/binder/OverloadResolution.hpp>
7 #include <cmajor/binder/BoundCompileUnit.hpp>
8 #include <cmajor/binder/BoundFunction.hpp>
9 #include <cmajor/binder/BoundConstraint.hpp>
10 #include <cmajor/binder/Concept.hpp>
11 #include <cmajor/binder/TypeBinder.hpp>
12 #include <cmajor/binder/BoundClass.hpp>
13 #include <cmajor/symbols/TemplateSymbol.hpp>
14 #include <cmajor/symbols/InterfaceTypeSymbol.hpp>
15 #include <cmajor/symbols/GlobalFlags.hpp>
16 #include <cmajor/symbols/Warning.hpp>
17 #include <cmajor/symbols/DebugFlags.hpp>
18 #include <soulng/util/Unicode.hpp>
19 #include <soulng/util/Log.hpp>
20 #include <soulng/util/Time.hpp>
21 #include <algorithm>
22
23 namespace cmajor { namespace binder {
24
25 using namespace soulng::unicode;
26
27 bool BetterFunctionMatch::operator()(const FunctionMatch& left, const FunctionMatch& right) const
28 {
29 int leftBetterArgumentMatches = 0;
30 int rightBetterArgumentMatches = 0;
31 int n = std::max(int(left.argumentMatches.size()), int(right.argumentMatches.size()));
32 for (int i = 0; i < n; ++i)
33 {
34 ArgumentMatch leftMatch;
35 if (i < int(left.argumentMatches.size()))
36 {
37 leftMatch = left.argumentMatches[i];
38 }
39 ArgumentMatch rightMatch;
40 if (i < int(right.argumentMatches.size()))
41 {
42 rightMatch = right.argumentMatches[i];
43 }
44 if (BetterArgumentMatch(leftMatch, rightMatch))
45 {
46 ++leftBetterArgumentMatches;
47 }
48 else if (BetterArgumentMatch(rightMatch, leftMatch))
49 {
50 ++rightBetterArgumentMatches;
51 }
52 }
53 if (leftBetterArgumentMatches > rightBetterArgumentMatches)
54 {
55 return true;
56 }
57 if (rightBetterArgumentMatches > leftBetterArgumentMatches)
58 {
59 return false;
60 }
61 if (left.numConversions < right.numConversions)
62 {
63 return true;
64 }
65 if (left.numConversions > right.numConversions)
66 {
67 return false;
68 }
69 if (left.numQualifyingConversions < right.numQualifyingConversions)
70 {
71 return true;
72 }
73 if (left.numQualifyingConversions > right.numQualifyingConversions)
74 {
75 return false;
76 }
77 if (!left.fun->IsFunctionTemplate() && right.fun->IsFunctionTemplate())
78 {
79 return true;
80 }
81 if (left.fun->IsFunctionTemplate() && !right.fun->IsFunctionTemplate())
82 {
83 return false;
84 }
85 if (!left.fun->IsTemplateSpecialization() && right.fun->IsTemplateSpecialization())
86 {
87 return true;
88 }
89 if (left.fun->IsTemplateSpecialization() && !right.fun->IsTemplateSpecialization())
90 {
91 return false;
92 }
93 if (left.boundConstraint && !right.boundConstraint)
94 {
95 return true;
96 }
97 if (!left.boundConstraint && right.boundConstraint)
98 {
99 return false;
100 }
101 if (left.boundConstraint && right.boundConstraint)
102 {
103 bool leftSubsumeRight = left.boundConstraint->Subsume(right.boundConstraint);
104 bool rightSubsumeLeft = right.boundConstraint->Subsume(left.boundConstraint);
105 if (leftSubsumeRight && !rightSubsumeLeft)
106 {
107 return true;
108 }
109 if (rightSubsumeLeft && !leftSubsumeRight)
110 {
111 return false;
112 }
113 }
114 return false;
115 }
116
117 bool FindQualificationConversion(TypeSymbol* sourceType, TypeSymbol* targetType, BoundExpression* argument, ConversionType conversionType, const Span& span, const boost::uuids::uuid& moduleId,
118 FunctionMatch& functionMatch, ArgumentMatch& argumentMatch)
119 {
120 int distance = 0;
121 if (argumentMatch.conversionFun)
122 {
123 distance = argumentMatch.conversionFun->ConversionDistance();
124 }
125 if (targetType->IsRvalueReferenceType() && !sourceType->IsRvalueReferenceType())
126 {
127 ++functionMatch.numQualifyingConversions;
128 }
129 if (sourceType->IsConstType())
130 {
131 if (targetType->IsConstType() || !targetType->IsReferenceType())
132 {
133 ++distance;
134 }
135 else if (conversionType == ConversionType::implicit_)
136 {
137 if (sourceType->PointerCount() < 1)
138 {
139 functionMatch.cannotBindConstArgToNonConstParam = true;
140 functionMatch.sourceType = sourceType;
141 functionMatch.targetType = targetType;
142 return false;
143 }
144 else
145 {
146 ++distance;
147 }
148 }
149 else
150 {
151 distance = 255;
152 }
153 }
154 else
155 {
156 if (targetType->IsConstType())
157 {
158 distance += 2;
159 }
160 else
161 {
162 distance += 3;
163 }
164 }
165 if (sourceType->IsReferenceType() && !targetType->IsReferenceType())
166 {
167 argumentMatch.postReferenceConversionFlags = OperationFlags::deref;
168 argumentMatch.conversionDistance = distance;
169 ++functionMatch.numQualifyingConversions;
170 return true;
171 }
172 else if (!sourceType->IsReferenceType() && (targetType->IsReferenceType() || targetType->IsClassTypeSymbol() || targetType->GetSymbolType() == SymbolType::classDelegateTypeSymbol))
173 {
174 if (targetType->IsConstType() || targetType->IsClassTypeSymbol() || targetType->GetSymbolType() == SymbolType::classDelegateTypeSymbol)
175 {
176 argumentMatch.postReferenceConversionFlags = OperationFlags::addr;
177 argumentMatch.conversionDistance = distance;
178 ++functionMatch.numQualifyingConversions;
179 return true;
180 }
181 else if ((!sourceType->IsConstType() || sourceType->PointerCount() >= 1) && argument->IsLvalueExpression())
182 {
183 if (targetType->IsRvalueReferenceType() && !sourceType->IsRvalueReferenceType())
184 {
185 if (argument->GetFlag(BoundExpressionFlags::bindToRvalueReference))
186 {
187 distance = 0;
188 }
189 else
190 {
191 distance += 10;
192 }
193 }
194 argumentMatch.postReferenceConversionFlags = OperationFlags::addr;
195 argumentMatch.conversionDistance = distance;
196 ++functionMatch.numQualifyingConversions;
197 return true;
198 }
199 else
200 {
201 functionMatch.cannotBindConstArgToNonConstParam = true;
202 functionMatch.sourceType = sourceType;
203 functionMatch.targetType = targetType;
204 }
205 }
206 else if (sourceType->IsConstType() && !targetType->IsConstType())
207 {
208 ++functionMatch.numQualifyingConversions;
209 ++distance;
210 if (sourceType->IsLvalueReferenceType() && targetType->IsRvalueReferenceType())
211 {
212 ++distance;
213 ++functionMatch.numQualifyingConversions;
214 }
215 argumentMatch.conversionDistance = distance;
216 return true;
217 }
218 else if (!sourceType->IsConstType() && targetType->IsConstType())
219 {
220 ++functionMatch.numQualifyingConversions;
221 ++distance;
222 if (sourceType->IsLvalueReferenceType() && targetType->IsRvalueReferenceType())
223 {
224 ++distance;
225 ++functionMatch.numQualifyingConversions;
226 }
227 argumentMatch.conversionDistance = distance;
228 return true;
229 }
230 else if (sourceType->IsLvalueReferenceType() && targetType->IsRvalueReferenceType())
231 {
232 ++distance;
233 ++functionMatch.numQualifyingConversions;
234 argumentMatch.conversionDistance = distance;
235 return true;
236 }
237 else if (sourceType->IsRvalueReferenceType() && targetType->IsLvalueReferenceType())
238 {
239 ++distance;
240 ++functionMatch.numQualifyingConversions;
241 argumentMatch.conversionDistance = distance;
242 return true;
243 }
244 else if (argumentMatch.conversionFun)
245 {
246 argumentMatch.conversionDistance = distance;
247 return true;
248 }
249 return false;
250 }
251
252 bool FindTemplateParameterMatch(TypeSymbol* sourceType, TypeSymbol* targetType, ConversionType conversionType, BoundExpression* argument,
253 BoundCompileUnit& boundCompileUnit, FunctionMatch& functionMatch, ContainerScope* containerScope, BoundFunction* currentFunction, const Span& span, const boost::uuids::uuid& moduleId)
254 {
255 if (targetType->BaseType()->GetSymbolType() != SymbolType::templateParameterSymbol) return false;
256 TemplateParameterSymbol* templateParameter = static_cast<TemplateParameterSymbol*>(targetType->BaseType());
257 TypeSymbol* templateArgumentType = nullptr;
258 auto it = functionMatch.templateParameterMap.find(templateParameter);
259 if (it == functionMatch.templateParameterMap.cend())
260 {
261 templateArgumentType = sourceType->RemoveDerivations(targetType->DerivationRec(), span, moduleId);
262 if (templateArgumentType)
263 {
264 functionMatch.templateParameterMap[templateParameter] = templateArgumentType;
265 }
266 else
267 {
268 return false;
269 }
270 }
271 else
272 {
273 templateArgumentType = it->second;
274 }
275 targetType = targetType->Unify(templateArgumentType, span, moduleId);
276 if (!targetType)
277 {
278 return false;
279 }
280 if (TypesEqual(sourceType, targetType))
281 {
282 functionMatch.argumentMatches.push_back(ArgumentMatch());
283 return true;
284 }
285 else
286 {
287 bool qualificationConversionMatch = false;
288 ArgumentMatch argumentMatch;
289 if (TypesEqual(sourceType->PlainType(span, moduleId), targetType->PlainType(span, moduleId)))
290 {
291 qualificationConversionMatch = FindQualificationConversion(sourceType, targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch);
292 }
293 if (qualificationConversionMatch)
294 {
295 functionMatch.argumentMatches.push_back(argumentMatch);
296 return true;
297 }
298 else
299 {
300 FunctionSymbol* conversionFun = boundCompileUnit.GetConversion(sourceType, targetType, containerScope, currentFunction, span, moduleId, argumentMatch);
301 if (conversionFun)
302 {
303 if (conversionFun->GetConversionType() == conversionType || conversionFun->GetConversionType() == ConversionType::implicit_)
304 {
305 ++functionMatch.numConversions;
306 argumentMatch.conversionFun = conversionFun;
307
308 if (argumentMatch.preReferenceConversionFlags == OperationFlags::none)
309 {
310 if (FindQualificationConversion(sourceType, targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch))
311 {
312 functionMatch.argumentMatches.push_back(argumentMatch);
313 return true;
314 }
315 else
316 {
317 return false;
318 }
319 }
320 else
321 {
322 if (FindQualificationConversion(conversionFun->ConversionSourceType(), targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch))
323 {
324 functionMatch.argumentMatches.push_back(argumentMatch);
325 return true;
326 }
327 else
328 {
329 return false;
330 }
331 }
332 }
333 else
334 {
335 return false;
336 }
337 }
338 else
339 {
340 return false;
341 }
342 }
343 }
344 return false;
345 }
346
347 bool FindClassTemplateSpecializationMatch(TypeSymbol* sourceType, TypeSymbol* targetType, ConversionType conversionType, BoundExpression* argument,
348 BoundCompileUnit& boundCompileUnit, FunctionMatch& functionMatch, ContainerScope* containerScope, BoundFunction* currentFunction, const Span& span, const boost::uuids::uuid& moduleId)
349 {
350 if (targetType->BaseType()->GetSymbolType() != SymbolType::classTemplateSpecializationSymbol)
351 {
352 return false;
353 }
354 ClassTemplateSpecializationSymbol* targetClassTemplateSpecialization = static_cast<ClassTemplateSpecializationSymbol*>(targetType->BaseType());
355 int n = targetClassTemplateSpecialization->TemplateArgumentTypes().size();
356 int numArgumentMatches = functionMatch.argumentMatches.size();
357 if (sourceType->BaseType()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
358 {
359 ClassTemplateSpecializationSymbol* sourceClassTemplateSpecialization = static_cast<ClassTemplateSpecializationSymbol*>(sourceType->BaseType());
360 int m = sourceClassTemplateSpecialization->TemplateArgumentTypes().size();
361 if (n != m) return false;
362 for (int i = 0; i < n; ++i)
363 {
364 TypeSymbol* sourceArgumentType = sourceClassTemplateSpecialization->TemplateArgumentTypes()[i];
365 TypeSymbol* targetArgumentType = targetClassTemplateSpecialization->TemplateArgumentTypes()[i];
366 if (FindTemplateParameterMatch(sourceArgumentType, targetArgumentType, conversionType, argument, boundCompileUnit, functionMatch, containerScope, currentFunction, span, moduleId))
367 {
368 continue;
369 }
370 else if (FindClassTemplateSpecializationMatch(sourceArgumentType, targetArgumentType, conversionType, argument, boundCompileUnit, functionMatch, containerScope, currentFunction, span, moduleId))
371 {
372 continue;
373 }
374 else
375 {
376 return false;
377 }
378 }
379 }
380 functionMatch.argumentMatches.resize(numArgumentMatches);
381 std::vector<TypeSymbol*> targetTemplateArguments;
382 for (int i = 0; i < n; ++i)
383 {
384 TypeSymbol* templateArgumentType = targetClassTemplateSpecialization->TemplateArgumentTypes()[i]->BaseType()->UnifyTemplateArgumentType(
385 boundCompileUnit.GetSymbolTable(), functionMatch.templateParameterMap, span, moduleId);
386 if (templateArgumentType)
387 {
388 targetTemplateArguments.push_back(templateArgumentType);
389 }
390 else
391 {
392 return false;
393 }
394 }
395 TypeSymbol* plainTargetType = boundCompileUnit.GetSymbolTable().MakeClassTemplateSpecialization(targetClassTemplateSpecialization->GetClassTemplate(), targetTemplateArguments, span,
396 GetRootModuleForCurrentThread()->Id());
397 targetType = boundCompileUnit.GetSymbolTable().MakeDerivedType(plainTargetType, targetType->DerivationRec(), span, moduleId);
398 if (TypesEqual(sourceType, targetType))
399 {
400 functionMatch.argumentMatches.push_back(ArgumentMatch());
401 return true;
402 }
403 else
404 {
405 bool qualificationConversionMatch = false;
406 ArgumentMatch argumentMatch;
407 if (TypesEqual(sourceType->PlainType(span, moduleId), targetType->PlainType(span, moduleId)))
408 {
409 qualificationConversionMatch = FindQualificationConversion(sourceType, targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch);
410 }
411 if (qualificationConversionMatch)
412 {
413 functionMatch.argumentMatches.push_back(argumentMatch);
414 return true;
415 }
416 else
417 {
418 FunctionSymbol* conversionFun = boundCompileUnit.GetConversion(sourceType, targetType, containerScope, currentFunction, span, moduleId, argumentMatch);
419 if (conversionFun)
420 {
421 if (conversionFun->GetConversionType() == conversionType || conversionFun->GetConversionType() == ConversionType::implicit_)
422 {
423 argumentMatch.conversionFun = conversionFun;
424 ++functionMatch.numConversions;
425 if (argumentMatch.preReferenceConversionFlags == OperationFlags::none)
426 {
427 if (FindQualificationConversion(sourceType, targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch))
428 {
429 functionMatch.argumentMatches.push_back(argumentMatch);
430 return true;
431 }
432 else
433 {
434 return false;
435 }
436 }
437 else
438 {
439 if (FindQualificationConversion(conversionFun->ConversionSourceType(), targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch))
440 {
441 functionMatch.argumentMatches.push_back(argumentMatch);
442 return true;
443 }
444 else
445 {
446 return false;
447 }
448 }
449 }
450 else
451 {
452 return false;
453 }
454 }
455 else
456 {
457 return false;
458 }
459 }
460 }
461 return false;
462 }
463
464 bool FindConversions(BoundCompileUnit& boundCompileUnit, FunctionSymbol* function, std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, FunctionMatch&functionMatch,
465 ConversionType conversionType, ContainerScope* containerScope, BoundFunction* currentFunction, const Span& span, const boost::uuids::uuid& moduleId)
466 {
467 if (!currentFunction)
468 {
469 if (function->IsProject() && !function->IsBound())
470 {
471 Node* node = boundCompileUnit.GetSymbolTable().GetNodeNoThrow(function);
472 if (node)
473 {
474 TypeBinder typeBinder(boundCompileUnit);
475 typeBinder.SetContainerScope(containerScope);
476 typeBinder.SetCurrentFunctionSymbol(function);
477 node->Accept(typeBinder);
478 }
479 }
480 }
481 int arity = arguments.size();
482 if (arity == 1 && function->GroupName() == U"@constructor" && arguments[0]->GetType()->IsReferenceType())
483 {
484 functionMatch.referenceMustBeInitialized = true;
485 return false;
486 }
487 int n = std::min(arity, function->Arity());
488 if (!function->IsVarArg())
489 {
490 Assert(arity == function->Arity(), "wrong arity");
491 }
492 for (int i = 0; i < n; ++i)
493 {
494 BoundExpression* argument = arguments[i].get();
495 TypeSymbol* sourceType = argument->GetType();
496 if (sourceType->RemoveConst(span, moduleId)->IsBasicTypeSymbol())
497 {
498 sourceType = sourceType->RemoveConst(span, moduleId);
499 }
500 ParameterSymbol* parameter = function->Parameters()[i];
501 TypeSymbol* targetType = parameter->GetType();
502 if (arity == 2 && function->GroupName() == U"operator=")
503 {
504 if (targetType->IsRvalueReferenceType() && !sourceType->IsRvalueReferenceType() && !argument->GetFlag(BoundExpressionFlags::bindToRvalueReference))
505 {
506 ++functionMatch.numQualifyingConversions;
507 }
508 if (i == 0)
509 {
510 if (targetType->IsConstType() && targetType->PointerCount() <= 1)
511 {
512 functionMatch.cannotAssignToConstObject = true;
513 return false;
514 }
515 }
516 if (i == 0 && TypesEqual(sourceType, targetType))
517 {
518 if (sourceType->IsReferenceType() && !function->IsConstructorDestructorOrNonstaticMemberFunction())
519 {
520 functionMatch.argumentMatches.push_back(ArgumentMatch(OperationFlags::none, nullptr, OperationFlags::deref, 1));
521 ++functionMatch.numConversions;
522 continue;
523 }
524 }
525 else if (i == 1 && sourceType->IsReferenceType() && targetType->IsLvalueReferenceType() && TypesEqual(sourceType->RemoveReference(span, moduleId)->RemoveConst(span, moduleId), targetType->RemoveReference(span, moduleId)))
526 {
527 if (!function->IsConstructorDestructorOrNonstaticMemberFunction())
528 {
529 functionMatch.argumentMatches.push_back(ArgumentMatch(OperationFlags::none, nullptr, OperationFlags::deref, 1));
530 ++functionMatch.numConversions;
531 continue;
532 }
533 }
534 else if (i == 1 && sourceType->IsReferenceType() && targetType->IsRvalueReferenceType() && TypesEqual(sourceType->RemoveReference(span, moduleId), targetType->RemoveReference(span, moduleId)))
535 {
536 if (!function->IsConstructorDestructorOrNonstaticMemberFunction())
537 {
538 functionMatch.argumentMatches.push_back(ArgumentMatch(OperationFlags::none, nullptr, OperationFlags::none, 0));
539 continue;
540 }
541 }
542 else if (i == 1 && !sourceType->IsReferenceType() && argument->IsLvalueExpression() && targetType->IsReferenceType() && TypesEqual(sourceType, targetType->RemoveReference(span, moduleId)))
543 {
544 if (!function->IsConstructorDestructorOrNonstaticMemberFunction())
545 {
546 functionMatch.argumentMatches.push_back(ArgumentMatch(OperationFlags::none, nullptr, OperationFlags::none, 0));
547 continue;
548 }
549 }
550 else if (i == 1 && function->IsLvalueReferenceCopyAssignment() && TypesEqual(sourceType, targetType->RemoveReference(span, moduleId)))
551 {
552 functionMatch.argumentMatches.push_back(ArgumentMatch(OperationFlags::none, nullptr, OperationFlags::none, 0));
553 continue;
554 }
555 else if (i == 1 && function->IsLvalueReferenceCopyAssignment())
556 {
557 ArgumentMatch argumentMatch;
558 FunctionSymbol* conversionFun = boundCompileUnit.GetConversion(sourceType, targetType->RemoveReference(span, moduleId), containerScope, currentFunction, span, moduleId, argumentMatch);
559 if (conversionFun&&( conversionFun->GetConversionType() == conversionType || conversionFun->GetConversionType() == ConversionType::implicit_))
560 {
561 ++functionMatch.numConversions;
562 functionMatch.argumentMatches.push_back(ArgumentMatch(OperationFlags::none, conversionFun, OperationFlags::none, 1));
563 continue;
564 }
565 }
566 }
567 if (TypesEqual(sourceType, targetType))
568 {
569 functionMatch.argumentMatches.push_back(ArgumentMatch());
570 }
571 else
572 {
573 if (arity == 2 && (function->GroupName() == U"@constructor" || function->GroupName() == U"operator="))
574 {
575 if (i == 0)
576 {
577 return false;
578 }
579 }
580 bool qualificationConversionMatch = false;
581 ArgumentMatch argumentMatch;
582 if (TypesEqual(sourceType->PlainType(span, moduleId), targetType->PlainType(span, moduleId)))
583 {
584 qualificationConversionMatch = FindQualificationConversion(sourceType, targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch);
585 functionMatch.argumentMatches.push_back(argumentMatch);
586 }
587 if (!qualificationConversionMatch)
588 {
589 FunctionSymbol* conversionFun = boundCompileUnit.GetConversion(sourceType, targetType, containerScope, currentFunction, span, moduleId, argumentMatch);
590 if (conversionFun)
591 {
592 if (conversionFun->GetConversionType() == conversionType || conversionFun->GetConversionType() == ConversionType::implicit_)
593 {
594 argumentMatch.conversionFun = conversionFun;
595 ++functionMatch.numConversions;
596 if (argumentMatch.preReferenceConversionFlags == OperationFlags::none)
597 {
598 if (FindQualificationConversion(sourceType, targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch))
599 {
600 functionMatch.argumentMatches.push_back(argumentMatch);
601 continue;
602 }
603 else
604 {
605 return false;
606 }
607 }
608 else
609 {
610 if (FindQualificationConversion(conversionFun->ConversionSourceType(), targetType, argument, conversionType, span, moduleId, functionMatch, argumentMatch))
611 {
612 functionMatch.argumentMatches.push_back(argumentMatch);
613 continue;
614 }
615 else
616 {
617 return false;
618 }
619 }
620 }
621 else
622 {
623 if (arity == 2 && i == 1 && conversionType == ConversionType::implicit_ && conversionFun->GetConversionType() == ConversionType::explicit_)
624 {
625 functionMatch.castRequired = true;
626 functionMatch.sourceType = sourceType;
627 functionMatch.targetType = targetType;
628 }
629 return false;
630 }
631 }
632 else
633 {
634 if (function->IsFunctionTemplate())
635 {
636 if (FindTemplateParameterMatch(sourceType, targetType, conversionType, argument, boundCompileUnit, functionMatch, containerScope, currentFunction, span, moduleId))
637 {
638 continue;
639 }
640 if (FindClassTemplateSpecializationMatch(sourceType, targetType, conversionType, argument, boundCompileUnit, functionMatch, containerScope, currentFunction, span, moduleId))
641 {
642 continue;
643 }
644 }
645 return false;
646 }
647 }
648 }
649 }
650 return true;
651 }
652
653 std::string MakeOverloadName(const std::u32string& groupName, const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, constSpan&span, constboost::uuids::uuid&moduleId)
654 {
655 std::string overloadName = ToUtf8(groupName);
656 overloadName.append(1, '(');
657 bool first = true;
658 for (const std::std::unique_ptr<BoundExpression>&argument : arguments)
659 {
660 bool wasFirst = first;
661 if (first)
662 {
663 first = false;
664 }
665 else
666 {
667 overloadName.append(", ");
668 }
669 if (wasFirst&&( groupName == U"@constructor" || groupName == U"operator="))
670 {
671 overloadName.append(ToUtf8(argument->GetType()->RemovePointer(span, moduleId)->FullName()));
672 }
673 else
674 {
675 overloadName.append(ToUtf8(argument->GetType()->FullName()));
676 }
677 }
678 overloadName.append(1, ')');
679 return overloadName;
680 }
681
682 std::std::unique_ptr<BoundFunctionCall>FailWithNoViableFunction(conststd::u32string&groupName, conststd::std::vector<std::std::unique_ptr<BoundExpression>>&arguments,
683 const Span& span, const boost::uuids::uuid& moduleId, OverloadResolutionFlags flags, std::std::unique_ptr<Exception>&exception)
684 {
685 std::string overloadName = MakeOverloadName(groupName, arguments, span, moduleId);
686 int arity = arguments.size();
687 if (groupName == U"@constructor" && arity == 1 && arguments[0]->GetType()->IsReferenceType())
688 {
689 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
690 {
691 exception.reset(new NoViableFunctionException("overload resolution failed: '" + overloadName + "' not found. Note: reference must be initialized.", span, moduleId,
692 arguments[0]->GetSpan(), arguments[0]->ModuleId()));
693 return std::unique_ptr<BoundFunctionCall>();
694 }
695 else
696 {
697 throw NoViableFunctionException("overload resolution failed: '" + overloadName + "' not found. Note: reference must be initialized.", span, moduleId,
698 arguments[0]->GetSpan(), arguments[0]->ModuleId());
699 }
700 }
701 else
702 {
703 std::string note;
704 if (exception)
705 {
706 note.append(": Note: ").append(exception->Message());
707 }
708 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
709 {
710 exception.reset(new NoViableFunctionException("overload resolution failed: '" + overloadName + "' not found. " +
711 "No viable functions taking " + std::to_string(arity) + " arguments found in function group '" + ToUtf8(groupName) + "'" + note, span, moduleId));
712 return std::unique_ptr<BoundFunctionCall>();
713 }
714 else
715 {
716 throw NoViableFunctionException("overload resolution failed: '" + overloadName + "' not found. " +
717 "No viable functions taking " + std::to_string(arity) + " arguments found in function group '" + ToUtf8(groupName) + "'" + note, span, moduleId);
718 }
719 }
720 }
721
722 std::std::unique_ptr<BoundFunctionCall>FailWithOverloadNotFound(Module*module, constViableFunctionSet&viableFunctions, conststd::u32string& groupName,
723 const std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, conststd::std::vector<FunctionMatch>&failedFunctionMatches, constSpan&span, constboost::uuids::uuid&moduleId,
724 OverloadResolutionFlags flags, std::std::unique_ptr<Exception>&exception)
725 {
726 std::string overloadName = MakeOverloadName(groupName, arguments, span, moduleId);
727 bool referenceMustBeInitialized = false;
728 bool castRequired = false;
729 bool cannotBindConstArgToNonConstParam = false;
730 bool cannotAssignToConstObject = false;
731 TypeSymbol* sourceType = nullptr;
732 TypeSymbol* targetType = nullptr;
733 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
734 std::string note;
735 if (exception)
736 {
737 note.append(" Note: ").append(exception->What());
738 }
739 if (!failedFunctionMatches.empty())
740 {
741 int n = failedFunctionMatches.size();
742 for (int i = 0; i < n; ++i)
743 {
744 if (failedFunctionMatches[i].referenceMustBeInitialized)
745 {
746 referenceMustBeInitialized = true;
747 break;
748 }
749 }
750 if (!referenceMustBeInitialized)
751 {
752 for (int i = 0; i < n; ++i)
753 {
754 if (failedFunctionMatches[i].castRequired)
755 {
756 castRequired = true;
757 sourceType = failedFunctionMatches[i].sourceType;
758 targetType = failedFunctionMatches[i].targetType;
759 references.push_back(std::make_pair(failedFunctionMatches[i].fun->GetSpan(), failedFunctionMatches[i].fun->SourceModuleId()));
760 break;
761 }
762 }
763 }
764 if (!referenceMustBeInitialized && !castRequired)
765 {
766 for (int i = 0; i < n; ++i)
767 {
768 if (failedFunctionMatches[i].cannotBindConstArgToNonConstParam)
769 {
770 cannotBindConstArgToNonConstParam = true;
771 sourceType = failedFunctionMatches[i].sourceType;
772 targetType = failedFunctionMatches[i].targetType;
773 references.push_back(std::make_pair(failedFunctionMatches[i].fun->GetSpan(), failedFunctionMatches[i].fun->SourceModuleId()));
774 break;
775 }
776 }
777 }
778 if (!referenceMustBeInitialized && !castRequired && !cannotBindConstArgToNonConstParam)
779 {
780 for (int i = 0; i < n; ++i)
781 {
782 if (failedFunctionMatches[i].cannotAssignToConstObject)
783 {
784 cannotAssignToConstObject = true;
785 references.push_back(std::make_pair(failedFunctionMatches[i].fun->GetSpan(), failedFunctionMatches[i].fun->SourceModuleId()));
786 break;
787 }
788 }
789 }
790 if (!referenceMustBeInitialized && !castRequired && !cannotBindConstArgToNonConstParam && !cannotAssignToConstObject)
791 {
792 for (int i = 0; i < n; ++i)
793 {
794 if (failedFunctionMatches[i].conceptCheckException)
795 {
796 if (!note.empty())
797 {
798 note.append(".");
799 }
800 note.append(" Note: concept check failed: " + failedFunctionMatches[i].conceptCheckException->Message());
801 references.insert(references.end(), failedFunctionMatches[i].conceptCheckException->References().begin(), failedFunctionMatches[i].conceptCheckException->References().end());
802 break;
803 }
804 }
805 }
806 }
807 if (referenceMustBeInitialized || groupName == U"@constructor" && arguments.size() == 1 && arguments[0]->GetType()->IsReferenceType())
808 {
809 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
810 {
811 references.push_back(std::make_pair(arguments[0]->GetSpan(), arguments[0]->ModuleId()));
812 exception.reset(new Exception("overload resolution failed: '" + overloadName + "' not found. Note: reference must be initialized.", span, moduleId, references));
813 return std::unique_ptr<BoundFunctionCall>();
814 }
815 else
816 {
817 references.push_back(std::make_pair(arguments[0]->GetSpan(), arguments[0]->ModuleId()));
818 throw Exception("overload resolution failed: '" + overloadName + "' not found. Note: reference must be initialized.", span, moduleId, references);
819 }
820 }
821 else if (castRequired)
822 {
823 Assert(sourceType, "source type not set");
824 Assert(targetType, "target type not set");
825 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
826 {
827 exception.reset(new CastOverloadException("overload resolution failed: '" + overloadName + "' not found, or there are no acceptable conversions for all argument types. " +
828 std::to_string(viableFunctions.Get().size()) + " viable functions examined. Note: cannot convert implicitly from '" +
829 ToUtf8(sourceType->FullName()) + "' to '" + ToUtf8(targetType->FullName()) + "' but explicit conversion (cast) exists.", span, moduleId, references));
830 return std::unique_ptr<BoundFunctionCall>();
831 }
832 else
833 {
834 throw CastOverloadException("overload resolution failed: '" + overloadName + "' not found, or there are no acceptable conversions for all argument types. " +
835 std::to_string(viableFunctions.Get().size()) + " viable functions examined. Note: cannot convert implicitly from '" +
836 ToUtf8(sourceType->FullName()) + "' to '" + ToUtf8(targetType->FullName()) + "' but explicit conversion (cast) exists.", span, moduleId, references);
837 }
838 }
839 else if (cannotBindConstArgToNonConstParam)
840 {
841 Assert(sourceType, "source type not set");
842 Assert(targetType, "target type not set");
843 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
844 {
845 exception.reset(new CannotBindConstToNonconstOverloadException("overload resolution failed: '" + overloadName +
846 "' not found, or there are no acceptable conversions for all argument types. " +
847 std::to_string(viableFunctions.Get().size()) + " viable functions examined. Note: cannot bind constant '" + ToUtf8(sourceType->FullName()) + "' argument " +
848 " to nonconstant '" + ToUtf8(targetType->FullName()) + "' parameter", span, moduleId, references));
849 return std::unique_ptr<BoundFunctionCall>();
850 }
851 else
852 {
853 throw CannotBindConstToNonconstOverloadException("overload resolution failed: '" + overloadName + "' not found, or there are no acceptable conversions for all argument types. " +
854 std::to_string(viableFunctions.Get().size()) + " viable functions examined. Note: cannot bind constant '" + ToUtf8(sourceType->FullName()) + "' argument " +
855 " to nonconstant '" + ToUtf8(targetType->FullName()) + "' parameter", span, moduleId, references);
856 }
857 }
858 else if (cannotAssignToConstObject)
859 {
860 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
861 {
862 exception.reset(new CannotAssignToConstOverloadException("overload resolution failed: '" + overloadName +
863 "' not found, or there are no acceptable conversions for all argument types. " +
864 std::to_string(viableFunctions.Get().size()) + " viable functions examined. Note: cannot assign to const object.", span, moduleId, references));
865 return std::unique_ptr<BoundFunctionCall>();
866 }
867 else
868 {
869 throw CannotAssignToConstOverloadException("overload resolution failed: '" + overloadName + "' not found, or there are no acceptable conversions for all argument types. " +
870 std::to_string(viableFunctions.Get().size()) + " viable functions examined. Note: cannot assign to const object. ", span, moduleId, references);
871 }
872 }
873 else
874 {
875 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
876 {
877 exception.reset(new Exception("overload resolution failed: '" + overloadName + "' not found, or there are no acceptable conversions for all argument types. " +
878 std::to_string(viableFunctions.Get().size()) + " viable functions examined." + note, span, moduleId, references));
879 return std::unique_ptr<BoundFunctionCall>();
880 }
881 else
882 {
883 throw Exception("overload resolution failed: '" + overloadName + "' not found, or there are no acceptable conversions for all argument types. " +
884 std::to_string(viableFunctions.Get().size()) + " viable functions examined." + note, span, moduleId, references);
885 }
886 }
887 }
888
889 std::std::unique_ptr<BoundFunctionCall>FailWithAmbiguousOverload(conststd::u32string&groupName, std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments,
890 std::std::vector<FunctionMatch>&functionMatches, constSpan&span, constboost::uuids::uuid&moduleId, OverloadResolutionFlags flags, std::std::unique_ptr<Exception>&exception)
891 {
892 std::string overloadName = MakeOverloadName(groupName, arguments, span, moduleId);
893 std::string matchedFunctionNames;
894 bool first = true;
895 FunctionMatch equalMatch = std::move(functionMatches[0]);
896 std::vector<FunctionMatch> equalMatches;
897 equalMatches.push_back(std::move(equalMatch));
898 int n = int(functionMatches.size());
899 for (int i = 1; i < n; ++i)
900 {
901 FunctionMatch match = std::move(functionMatches[i]);
902 if (!BetterFunctionMatch()(equalMatches[0], match))
903 {
904 equalMatches.push_back(std::move(match));
905 }
906 }
907 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
908 for (const FunctionMatch& match : equalMatches)
909 {
910 if (first)
911 {
912 first = false;
913 }
914 else
915 {
916 matchedFunctionNames.append(", or ");
917 }
918 matchedFunctionNames.append(ToUtf8(match.fun->FullName()));
919 references.push_back(std::make_pair(match.fun->GetSpan(), match.fun->SourceModuleId()));
920 }
921 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
922 {
923 exception.reset(new Exception("overload resolution for overload name '" + overloadName + "' failed: call is ambiguous: \n" + matchedFunctionNames, span, moduleId, references));
924 return std::unique_ptr<BoundFunctionCall>();
925 }
926 else
927 {
928 throw Exception("overload resolution for overload name '" + overloadName + "' failed: call is ambiguous: \n" + matchedFunctionNames, span, moduleId, references);
929 }
930 }
931
932 std::std::unique_ptr<BoundFunctionCall>CreateBoundFunctionCall(FunctionSymbol*bestFun, std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundCompileUnit&boundCompileUnit,
933 BoundFunction* boundFunction, const FunctionMatch& bestMatch, ContainerScope* containerScope, const Span& span, const boost::uuids::uuid& moduleId)
934 {
935 std::unique_ptr<BoundFunctionCall> boundFunctionCall(new BoundFunctionCall(span, moduleId, bestFun));
936 int arity = arguments.size();
937 int n = std::min(arity, bestFun->Arity());
938 for (int i = 0; i < n; ++i)
939 {
940 std::std::unique_ptr<BoundExpression>&argument=arguments[i];
941 if (i == 0 && !bestFun->IsConstructorDestructorOrNonstaticMemberFunction() &&
942 (bestFun->GroupName() == U"@constructor" || bestFun->GroupName() == U"operator=" || bestFun->GroupName() == U"operator->"))
943 {
944 if (argument->GetBoundNodeType() == BoundNodeType::boundAddressOfExpression)
945 {
946 BoundAddressOfExpression* addrOf = static_cast<BoundAddressOfExpression*>(argument.get());
947 std::unique_ptr<BoundExpression> subject(std::move(addrOf->Subject()));
948 addrOf->MoveTemporaryDestructorCallsTo(*subject);
949 argument.reset(subject.release());
950 }
951 }
952 const ArgumentMatch& argumentMatch = bestMatch.argumentMatches[i];
953 if (argumentMatch.preReferenceConversionFlags != OperationFlags::none)
954 {
955 if (argumentMatch.preReferenceConversionFlags == OperationFlags::addr)
956 {
957 if (!argument->IsLvalueExpression())
958 {
959 BoundLocalVariable* backingStore = nullptr;
960 if (boundFunction)
961 {
962 backingStore = new BoundLocalVariable(span, moduleId, boundFunction->GetFunctionSymbol()->CreateTemporary(argument->GetType(), span, moduleId));
963 }
964 argument.reset(new BoundTemporary(std::move(argument), std::unique_ptr<BoundLocalVariable>(backingStore)));
965 }
966 TypeSymbol* type = nullptr;
967 if (argument->GetType()->IsClassTypeSymbol() && argument->GetFlag(BoundExpressionFlags::bindToRvalueReference))
968 {
969 type = argument->GetType()->AddRvalueReference(span, moduleId);
970 }
971 else
972 {
973 type = argument->GetType()->AddLvalueReference(span, moduleId);
974 }
975 BoundAddressOfExpression* addressOfExpression = new BoundAddressOfExpression(std::move(argument), type);
976 argument.reset(addressOfExpression);
977 }
978 else if (argumentMatch.preReferenceConversionFlags == OperationFlags::deref)
979 {
980 TypeSymbol* type = argument->GetType()->RemoveReference(span, moduleId);
981 BoundDereferenceExpression* dereferenceExpression = new BoundDereferenceExpression(std::move(argument), type);
982 argument.reset(dereferenceExpression);
983 }
984 }
985 if (argumentMatch.conversionFun)
986 {
987 FunctionSymbol* conversionFun = argumentMatch.conversionFun;
988 if (conversionFun->GetSymbolType() == SymbolType::constructorSymbol)
989 {
990 if (!boundFunction)
991 {
992 return std::unique_ptr<BoundFunctionCall>();
993 }
994 BoundFunctionCall* constructorCall = new BoundFunctionCall(span, moduleId, conversionFun);
995 TypeSymbol* conversionTargetType = conversionFun->ConversionTargetType();
996 LocalVariableSymbol* temporary = boundFunction->GetFunctionSymbol()->CreateTemporary(conversionTargetType, span, moduleId);
997 constructorCall->AddArgument(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(new BoundLocalVariable(span, moduleId, temporary)),
998 conversionTargetType->AddPointer(span, moduleId))));
999 if (conversionTargetType->IsClassTypeSymbol())
1000 {
1001 ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(conversionTargetType);
1002 if (classType->Destructor())
1003 {
1004 std::unique_ptr<BoundFunctionCall> destructorCall(new BoundFunctionCall(span, moduleId, classType->Destructor()));
1005 destructorCall->AddArgument(std::unique_ptr<BoundExpression>(constructorCall->Arguments()[0]->Clone()));
1006 boundFunction->AddTemporaryDestructorCall(std::move(destructorCall), boundFunction, containerScope, span, moduleId);
1007 }
1008 }
1009 constructorCall->AddArgument(std::move(argument));
1010 std::vector<LocalVariableSymbol*> temporaryLocalVariables = conversionFun->CreateTemporariesTo(boundFunction->GetFunctionSymbol());
1011 for (LocalVariableSymbol* temporaryLocalVariable : temporaryLocalVariables)
1012 {
1013 constructorCall->AddTemporary(std::unique_ptr<BoundLocalVariable>(new BoundLocalVariable(span, moduleId, temporaryLocalVariable)));
1014 }
1015 BoundConstructAndReturnTemporaryExpression* conversion = new BoundConstructAndReturnTemporaryExpression(std::unique_ptr<BoundExpression>(constructorCall),
1016 std::unique_ptr<BoundExpression>(new BoundLocalVariable(span, moduleId, temporary)));
1017 argument.reset(conversion);
1018 }
1019 else if (conversionFun->GetSymbolType() == SymbolType::conversionFunctionSymbol && conversionFun->ReturnsClassInterfaceOrClassDelegateByValue())
1020 {
1021 if (!boundFunction)
1022 {
1023 return std::unique_ptr<BoundFunctionCall>();
1024 }
1025 BoundFunctionCall* conversionFunctionCall = new BoundFunctionCall(span, moduleId, conversionFun);
1026 conversionFunctionCall->AddArgument(std::move(argument));
1027 TypeSymbol* conversionTargetType = conversionFun->ConversionTargetType();
1028 LocalVariableSymbol* temporary = boundFunction->GetFunctionSymbol()->CreateTemporary(conversionTargetType, span, moduleId);
1029 conversionFunctionCall->AddArgument(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(new BoundLocalVariable(span, moduleId, temporary)),
1030 conversionTargetType->AddPointer(span, moduleId))));
1031 std::vector<LocalVariableSymbol*> temporaryLocalVariables = conversionFun->CreateTemporariesTo(boundFunction->GetFunctionSymbol());
1032 for (LocalVariableSymbol* temporaryLocalVariable : temporaryLocalVariables)
1033 {
1034 conversionFunctionCall->AddTemporary(std::unique_ptr<BoundLocalVariable>(new BoundLocalVariable(span, moduleId, temporaryLocalVariable)));
1035 }
1036 BoundLocalVariable* conversionResult = new BoundLocalVariable(span, moduleId, temporary);
1037 if (conversionTargetType->IsClassTypeSymbol())
1038 {
1039 ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(conversionTargetType);
1040 if (classType->Destructor())
1041 {
1042 std::unique_ptr<BoundFunctionCall> destructorCall(new BoundFunctionCall(span, moduleId, classType->Destructor()));
1043 TypeSymbol* type = conversionResult->GetType()->AddPointer(span, moduleId);
1044 destructorCall->AddArgument(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(conversionResult->Clone()), type)));
1045 boundFunction->AddTemporaryDestructorCall(std::move(destructorCall), boundFunction, containerScope, span, moduleId);
1046 }
1047 }
1048 BoundClassOrClassDelegateConversionResult* conversion = new BoundClassOrClassDelegateConversionResult(std::unique_ptr<BoundExpression>(conversionResult),
1049 std::unique_ptr<BoundFunctionCall>(conversionFunctionCall));
1050 argument.reset(conversion);
1051 }
1052 else
1053 {
1054 BoundConversion* conversion = new BoundConversion(std::move(argument), conversionFun);
1055 std::vector<LocalVariableSymbol*> temporaryLocalVariables = conversionFun->CreateTemporariesTo(boundFunction->GetFunctionSymbol());
1056 for (LocalVariableSymbol* temporaryLocalVariable : temporaryLocalVariables)
1057 {
1058 conversion->AddTemporary(std::unique_ptr<BoundLocalVariable>(new BoundLocalVariable(span, moduleId, temporaryLocalVariable)));
1059 }
1060 argument.reset(conversion);
1061 }
1062 }
1063 if (argumentMatch.postReferenceConversionFlags != OperationFlags::none)
1064 {
1065 if (argumentMatch.postReferenceConversionFlags == OperationFlags::addr)
1066 {
1067 if (!argument->IsLvalueExpression())
1068 {
1069 BoundLocalVariable* backingStore = nullptr;
1070 if (boundFunction)
1071 {
1072 backingStore = new BoundLocalVariable(span, moduleId, boundFunction->GetFunctionSymbol()->CreateTemporary(argument->GetType(), span, moduleId));
1073 }
1074 argument.reset(new BoundTemporary(std::move(argument), std::unique_ptr<BoundLocalVariable>(backingStore)));
1075 }
1076 TypeSymbol* type = nullptr;
1077 if (argument->GetType()->IsClassTypeSymbol() && argument->GetFlag(BoundExpressionFlags::bindToRvalueReference))
1078 {
1079 type = argument->GetType()->AddRvalueReference(span, moduleId);
1080 }
1081 else
1082 {
1083 type = argument->GetType()->AddLvalueReference(span, moduleId);
1084 }
1085 BoundAddressOfExpression* addressOfExpression = new BoundAddressOfExpression(std::move(argument), type);
1086 argument.reset(addressOfExpression);
1087 }
1088 else if (argumentMatch.postReferenceConversionFlags == OperationFlags::deref)
1089 {
1090 TypeSymbol* type = argument->GetType()->RemoveReference(span, moduleId);
1091 BoundDereferenceExpression* dereferenceExpression = new BoundDereferenceExpression(std::move(argument), type);
1092 argument.reset(dereferenceExpression);
1093 }
1094 }
1095 if (argument->GetType()->IsClassTypeSymbol() || argument->GetType()->GetSymbolType() == SymbolType::classDelegateTypeSymbol || argument->GetType()->GetSymbolType() == SymbolType::interfaceTypeSymbol)
1096 {
1097 if (argument->GetType()->IsClassTypeSymbol())
1098 {
1099 ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(argument->GetType());
1100 if (!classType->CopyConstructor())
1101 {
1102 try
1103 {
1104 boundCompileUnit.GenerateCopyConstructorFor(classType, containerScope, boundFunction, span, moduleId);
1105 }
1106 catch (const Exception& ex;)
1107 {
1108 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
1109 references.push_back(std::make_pair(ex.Defined(), ex.DefinedModuleId()));
1110 references.insert(references.end(), ex.References().begin(), ex.References().end());
1111 throw Exception("cannot pass class '" + ToUtf8(classType->FullName()) + "' by value because: " + ex.Message(), argument->GetSpan(), argument->ModuleId(), references);
1112 }
1113 }
1114 TypeSymbol* type = classType->AddConst(span, moduleId)->AddLvalueReference(span, moduleId);
1115 argument.reset(new BoundAddressOfExpression(std::move(argument), type));
1116 }
1117 else if (argument->GetType()->GetSymbolType() == SymbolType::classDelegateTypeSymbol)
1118 {
1119 TypeSymbol* type = argument->GetType()->AddConst(span, moduleId)->AddLvalueReference(span, moduleId);
1120 argument.reset(new BoundAddressOfExpression(std::move(argument), type));
1121 }
1122 else if (argument->GetType()->GetSymbolType() == SymbolType::interfaceTypeSymbol)
1123 {
1124 InterfaceTypeSymbol* interfaceTypeSymbol = static_cast<InterfaceTypeSymbol*>(argument->GetType());
1125 if (!interfaceTypeSymbol->CopyConstructor())
1126 {
1127 boundCompileUnit.GenerateCopyConstructorFor(interfaceTypeSymbol, containerScope, boundFunction, span, moduleId);
1128 }
1129 TypeSymbol* type = argument->GetType()->AddConst(span, moduleId)->AddLvalueReference(span, moduleId);
1130 argument.reset(new BoundAddressOfExpression(std::move(argument), type));
1131 }
1132 }
1133 boundFunctionCall->AddArgument(std::move(argument));
1134 }
1135 for (int i = n; i < arity; ++i)
1136 {
1137 std::std::unique_ptr<BoundExpression>&argument=arguments[i];
1138 boundFunctionCall->AddArgument(std::move(argument));
1139 }
1140 if (boundFunction)
1141 {
1142 std::vector<LocalVariableSymbol*> temporaryLocalVariables = bestFun->CreateTemporariesTo(boundFunction->GetFunctionSymbol());
1143 for (LocalVariableSymbol* temporaryLocalVariable : temporaryLocalVariables)
1144 {
1145 boundFunctionCall->AddTemporary(std::unique_ptr<BoundLocalVariable>(new BoundLocalVariable(span, moduleId, temporaryLocalVariable)));
1146 }
1147 }
1148 FunctionSymbol* functionSymbol = boundFunctionCall->GetFunctionSymbol();
1149 if (functionSymbol->GetSymbolType() == SymbolType::destructorSymbol)
1150 {
1151 DestructorSymbol* destructorSymbol = static_cast<DestructorSymbol*>(functionSymbol);
1152 if (destructorSymbol->IsGeneratedFunction() && !GetGlobalFlag(GlobalFlags::info))
1153 {
1154 if (destructorSymbol->Parent()->IsClassTypeSymbol())
1155 {
1156 ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(destructorSymbol->Parent());
1157 if (!boundCompileUnit.IsGeneratedDestructorInstantiated(destructorSymbol))
1158 {
1159 boundCompileUnit.SetGeneratedDestructorInstantiated(destructorSymbol);
1160 std::unique_ptr<BoundClass> boundClass(new BoundClass(classType));
1161 GenerateDestructorImplementation(boundClass.get(), destructorSymbol, boundCompileUnit, containerScope, boundFunction, span, moduleId);
1162 boundCompileUnit.AddBoundNode(std::move(boundClass));
1163 }
1164 }
1165 }
1166 }
1167 return boundFunctionCall;
1168 }
1169
1170 std::std::unique_ptr<BoundFunctionCall>SelectViableFunction(constViableFunctionSet&viableFunctions, conststd::u32string&groupName,
1171 std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, ContainerScope*containerScope, BoundCompileUnit&boundCompileUnit, BoundFunction*boundFunction,
1172 const Span& span, const boost::uuids::uuid& moduleId,
1173 OverloadResolutionFlags flags, std::std::vector<TypeSymbol*>&templateArgumentTypes, std::std::unique_ptr<Exception>&exception)
1174 {
1175 Module* module = &boundCompileUnit.GetModule();
1176 std::vector<FunctionMatch> functionMatches;
1177 std::vector<FunctionMatch> failedFunctionMatches;
1178 std::vector<std::std::unique_ptr<Exception>>conceptCheckExceptions;
1179 std::vector<std::std::unique_ptr<BoundConstraint>>boundConstraints;
1180 for (FunctionSymbol* viableFunction : viableFunctions.Get())
1181 {
1182 if (viableFunction->GetFlag(FunctionSymbolFlags::dontReuse))
1183 {
1184 if (!boundCompileUnit.CanReuse(viableFunction))
1185 {
1186 continue;
1187 }
1188 }
1189 if (viableFunction->IsSystemDefault())
1190 {
1191 if ((flags & OverloadResolutionFlags::includeSystemDefaultFunctions) == OverloadResolutionFlags::none)
1192 {
1193 continue;
1194 }
1195 }
1196 FunctionMatch functionMatch(viableFunction);
1197 if (viableFunction->IsFunctionTemplate())
1198 {
1199 if ((flags & OverloadResolutionFlags::noTemplates) != OverloadResolutionFlags::none)
1200 {
1201 continue;
1202 }
1203 int n = templateArgumentTypes.size();
1204 if (n > viableFunction->TemplateParameters().size())
1205 {
1206 continue;
1207 }
1208 else
1209 {
1210 for (int i = 0; i < n; ++i)
1211 {
1212 TemplateParameterSymbol* templateParameter = viableFunction->TemplateParameters()[i];
1213 functionMatch.templateParameterMap[templateParameter] = templateArgumentTypes[i];
1214 }
1215 }
1216 }
1217 else
1218 {
1219 if (!templateArgumentTypes.empty())
1220 {
1221 continue;
1222 }
1223 }
1224 if (FindConversions(boundCompileUnit, viableFunction, arguments, functionMatch, ConversionType::implicit_, containerScope, boundFunction, span, moduleId))
1225 {
1226 if (viableFunction->IsFunctionTemplate())
1227 {
1228 bool allTemplateParametersFound = true;
1229 int n = viableFunction->TemplateParameters().size();
1230 for (int i = 0; i < n; ++i)
1231 {
1232 TemplateParameterSymbol* templateParameterSymbol = viableFunction->TemplateParameters()[i];
1233 auto it = functionMatch.templateParameterMap.find(templateParameterSymbol);
1234 if (it == functionMatch.templateParameterMap.cend())
1235 {
1236 allTemplateParametersFound = false;
1237 break;
1238 }
1239 }
1240 if (allTemplateParametersFound)
1241 {
1242 if (!viableFunction->Constraint())
1243 {
1244 Node* node = boundCompileUnit.GetSymbolTable().GetNodeNoThrow(viableFunction);
1245 if (node)
1246 {
1247 Assert(node->GetNodeType() == NodeType::functionNode, "function node expected");
1248 FunctionNode* functionNode = static_cast<FunctionNode*>(node);
1249 ConstraintNode* constraint = functionNode->WhereConstraint();
1250 if (constraint)
1251 {
1252 CloneContext cloneContext;
1253 viableFunction->SetConstraint(static_cast<ConstraintNode*>(constraint->Clone(cloneContext)));
1254 }
1255 }
1256 }
1257 if (viableFunction->Constraint())
1258 {
1259 std::unique_ptr<Exception> conceptCheckException;
1260 std::unique_ptr<BoundConstraint> boundConstraint;
1261 bool candidateFound = CheckConstraint(viableFunction->Constraint(), viableFunction->UsingNodes(), boundCompileUnit, containerScope, boundFunction,
1262 viableFunction->TemplateParameters(), functionMatch.templateParameterMap, boundConstraint, span, moduleId, viableFunction, conceptCheckException);
1263 if (candidateFound)
1264 {
1265 functionMatch.boundConstraint = boundConstraint.get();
1266 functionMatches.push_back(functionMatch);
1267 boundConstraints.push_back(std::move(boundConstraint));
1268 }
1269 else
1270 {
1271 functionMatch.conceptCheckException = conceptCheckException.get();
1272 failedFunctionMatches.push_back(functionMatch);
1273 conceptCheckExceptions.push_back(std::move(conceptCheckException));
1274 }
1275 }
1276 else
1277 {
1278 functionMatches.push_back(functionMatch);
1279 }
1280 }
1281 else
1282 {
1283 failedFunctionMatches.push_back(functionMatch);
1284 }
1285 }
1286 else
1287 {
1288 functionMatches.push_back(functionMatch);
1289 }
1290 }
1291 else
1292 {
1293 failedFunctionMatches.push_back(functionMatch);
1294 }
1295 }
1296 if (functionMatches.empty())
1297 {
1298 if ((flags & OverloadResolutionFlags::includeSystemDefaultFunctions) == OverloadResolutionFlags::none)
1299 {
1300 return SelectViableFunction(viableFunctions, groupName, arguments, containerScope, boundCompileUnit, boundFunction, span, moduleId,
1301 (flags | OverloadResolutionFlags::includeSystemDefaultFunctions), templateArgumentTypes, exception);
1302 }
1303 return FailWithOverloadNotFound(module, viableFunctions, groupName, arguments, failedFunctionMatches, span, moduleId, flags, exception);
1304 }
1305 else if (functionMatches.size() > 1)
1306 {
1307 std::sort(functionMatches.begin(), functionMatches.end(), BetterFunctionMatch());
1308 if (BetterFunctionMatch()(functionMatches[0], functionMatches[1]))
1309 {
1310 const FunctionMatch& bestMatch = functionMatches[0];
1311 FunctionSymbol* bestFun = bestMatch.fun;
1312 if (bestFun->IsSuppressed())
1313 {
1314 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
1315 {
1316 exception.reset(new Exception("cannot call a suppressed member function '" + ToUtf8(bestFun->FullName()) + "'", span, moduleId, bestFun->GetSpan(), bestFun->SourceModuleId()));
1317 return std::unique_ptr<BoundFunctionCall>();
1318 }
1319 else
1320 {
1321 throw Exception("cannot call a suppressed member function '" + ToUtf8(bestFun->FullName()) + "'", span, moduleId, bestFun->GetSpan(), bestFun->SourceModuleId());
1322 }
1323 }
1324 bool instantiate = (flags & OverloadResolutionFlags::dontInstantiate) == OverloadResolutionFlags::none;
1325 if (bestFun->IsFunctionTemplate())
1326 {
1327 if (instantiate)
1328 {
1329 bestFun = boundCompileUnit.InstantiateFunctionTemplate(bestFun, bestMatch.templateParameterMap, span, moduleId);
1330 }
1331 else
1332 {
1333 templateArgumentTypes.clear();
1334 for (TemplateParameterSymbol* templateParameter : bestFun->TemplateParameters())
1335 {
1336 auto it = bestMatch.templateParameterMap.find(templateParameter);
1337 if (it != bestMatch.templateParameterMap.cend())
1338 {
1339 TypeSymbol* templateArgumentType = it->second;
1340 templateArgumentTypes.push_back(templateArgumentType);
1341 }
1342 }
1343 }
1344 }
1345 else if (!bestFun->IsGeneratedFunction() && bestFun->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1346 {
1347 if (instantiate)
1348 {
1349 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(bestFun->Parent());
1350 if (specialization->GetModule() != module)
1351 {
1352 specialization = boundCompileUnit.GetSymbolTable().GetCurrentClassTemplateSpecialization(specialization);
1353 int index = bestFun->GetIndex();
1354 bestFun = specialization->GetFunctionByIndex(index);
1355 }
1356 bool firstTry = boundCompileUnit.InstantiateClassTemplateMemberFunction(bestFun, containerScope, boundFunction, span, moduleId);
1357 if (!firstTry)
1358 {
1359 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(bestFun->Parent());
1360 std::lock_guard<std::recursive_mutex> lock(boundCompileUnit.GetModule().GetLock());
1361 ClassTemplateSpecializationSymbol* copy = boundCompileUnit.GetSymbolTable().CopyClassTemplateSpecialization(specialization);
1362 boundCompileUnit.GetClassTemplateRepository().BindClassTemplateSpecialization(
1363 copy, boundCompileUnit.GetSymbolTable().GlobalNs().GetContainerScope(), span, moduleId);
1364 int index = bestFun->GetIndex();
1365 bestFun = copy->GetFunctionByIndex(index);
1366 bool secondTry = boundCompileUnit.InstantiateClassTemplateMemberFunction(bestFun, containerScope, boundFunction, span, moduleId);
1367 if (!secondTry)
1368 {
1369 throw Exception("internal error: could not instantiate member function of a class template specialization '" + ToUtf8(specialization->FullName()) + "'",
1370 specialization->GetSpan(), specialization->SourceModuleId());
1371 }
1372 }
1373 }
1374 }
1375 else if (!bestFun->IsGeneratedFunction() && GetGlobalFlag(GlobalFlags::release) && bestFun->IsInline())
1376 {
1377 if (instantiate)
1378 {
1379 if (bestFun->IsTemplateSpecialization())
1380 {
1381 FunctionSymbol* functionTemplate = bestFun->FunctionTemplate();
1382 std::unordered_map<TemplateParameterSymbol*, TypeSymbol*> templateParameterMap;
1383 int n = functionTemplate->TemplateParameters().size();
1384 for (int i = 0; i < n; ++i)
1385 {
1386 TemplateParameterSymbol* templateParameter = functionTemplate->TemplateParameters()[i];
1387 TypeSymbol* templateArgumentType = bestFun->TemplateArgumentTypes()[i];
1388 templateParameterMap[templateParameter] = templateArgumentType;
1389 }
1390 bestFun = boundCompileUnit.InstantiateFunctionTemplate(functionTemplate, templateParameterMap, span, moduleId);
1391 }
1392 else
1393 {
1394 bestFun = boundCompileUnit.InstantiateInlineFunction(bestFun, containerScope, span, moduleId);
1395 }
1396 }
1397 }
1398 if (boundFunction && boundFunction->GetFunctionSymbol()->DontThrow() && !boundFunction->GetFunctionSymbol()->HasTry() && !bestFun->DontThrow())
1399 {
1400 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
1401 references.push_back(std::make_pair(boundFunction->GetFunctionSymbol()->GetSpan(), boundFunction->GetFunctionSymbol()->SourceModuleId()));
1402 references.push_back(std::make_pair(bestFun->GetSpan(), bestFun->SourceModuleId()));
1403 if (GetGlobalFlag(GlobalFlags::strictNothrow))
1404 {
1405 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
1406 {
1407 exception.reset(new Exception("a nothrow function cannot call a function that can throw unless it handles exceptions (compiled with --strict-nothrow)", span, moduleId, references));
1408 return std::unique_ptr<BoundFunctionCall>();
1409 }
1410 else
1411 {
1412 throw Exception("a nothrow function cannot call a function that can throw unless it handles exceptions (compiled with --strict-nothrow)", span, moduleId, references);
1413 }
1414 }
1415 else
1416 {
1417 Warning warning(module->GetCurrentProjectName(), "a nothrow function calls a function that can throw and does not handle exceptions");
1418 warning.SetDefined(span, moduleId);
1419 warning.SetReferences(references);
1420 module->WarningCollection().AddWarning(warning);
1421 }
1422 }
1423 return CreateBoundFunctionCall(bestFun, arguments, boundCompileUnit, boundFunction, bestMatch, containerScope, span, moduleId);
1424 }
1425 else
1426 {
1427 return FailWithAmbiguousOverload(groupName, arguments, functionMatches, span, moduleId, flags, exception);
1428 }
1429 }
1430 else
1431 {
1432 const FunctionMatch& bestMatch = functionMatches[0];
1433 FunctionSymbol* singleBest = bestMatch.fun;
1434 if (singleBest->IsSuppressed())
1435 {
1436 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
1437 {
1438 exception.reset(new Exception("cannot call a suppressed member function '" + ToUtf8(singleBest->FullName()) + "'", span, moduleId, singleBest->GetSpan(), singleBest->SourceModuleId()));
1439 return std::unique_ptr<BoundFunctionCall>();
1440 }
1441 else
1442 {
1443 throw Exception("cannot call a suppressed member function '" + ToUtf8(singleBest->FullName()) + "'", span, moduleId, singleBest->GetSpan(), singleBest->SourceModuleId());
1444 }
1445 }
1446 bool instantiate = (flags & OverloadResolutionFlags::dontInstantiate) == OverloadResolutionFlags::none;
1447 if (singleBest->IsFunctionTemplate())
1448 {
1449 if (instantiate)
1450 {
1451 singleBest = boundCompileUnit.InstantiateFunctionTemplate(singleBest, bestMatch.templateParameterMap, span, moduleId);
1452 }
1453 else
1454 {
1455 templateArgumentTypes.clear();
1456 for (TemplateParameterSymbol* templateParameter : singleBest->TemplateParameters())
1457 {
1458 auto it = bestMatch.templateParameterMap.find(templateParameter);
1459 if (it != bestMatch.templateParameterMap.cend())
1460 {
1461 TypeSymbol* templateArgumentType = it->second;
1462 templateArgumentTypes.push_back(templateArgumentType);
1463 }
1464 }
1465 }
1466 }
1467 else if (!singleBest->IsGeneratedFunction() && singleBest->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
1468 {
1469 if (instantiate)
1470 {
1471 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(singleBest->Parent());
1472 if (specialization->GetModule() != module)
1473 {
1474 specialization = boundCompileUnit.GetSymbolTable().GetCurrentClassTemplateSpecialization(specialization);
1475 int index = singleBest->GetIndex();
1476 singleBest = specialization->GetFunctionByIndex(index);
1477 }
1478 bool firstTry = boundCompileUnit.InstantiateClassTemplateMemberFunction(singleBest, containerScope, boundFunction, span, moduleId);
1479 if (!firstTry)
1480 {
1481 std::lock_guard<std::recursive_mutex> lock(boundCompileUnit.GetModule().Lock());
1482 ClassTemplateSpecializationSymbol* copy = boundCompileUnit.GetSymbolTable().CopyClassTemplateSpecialization(specialization);
1483 boundCompileUnit.GetClassTemplateRepository().BindClassTemplateSpecialization(copy, boundCompileUnit.GetSymbolTable().GlobalNs().GetContainerScope(), span, moduleId);
1484 int index = singleBest->GetIndex();
1485 singleBest = copy->GetFunctionByIndex(index);
1486 bool secondTry = boundCompileUnit.InstantiateClassTemplateMemberFunction(singleBest, containerScope, boundFunction, span, moduleId);
1487 if (!secondTry)
1488 {
1489 throw Exception("internal error: could not instantiate member function of a class template specialization '" + ToUtf8(specialization->FullName()) + "'",
1490 specialization->GetSpan(), specialization->SourceModuleId());
1491 }
1492 }
1493 }
1494 }
1495 else if (!singleBest->IsGeneratedFunction() && GetGlobalFlag(GlobalFlags::release) && singleBest->IsInline())
1496 {
1497 if (instantiate)
1498 {
1499 if (singleBest->IsTemplateSpecialization())
1500 {
1501 FunctionSymbol* functionTemplate = singleBest->FunctionTemplate();
1502 std::unordered_map<TemplateParameterSymbol*, TypeSymbol*> templateParameterMap;
1503 int n = functionTemplate->TemplateParameters().size();
1504 for (int i = 0; i < n; ++i)
1505 {
1506 TemplateParameterSymbol* templateParameter = functionTemplate->TemplateParameters()[i];
1507 TypeSymbol* templateArgumentType = singleBest->TemplateArgumentTypes()[i];
1508 templateParameterMap[templateParameter] = templateArgumentType;
1509 }
1510 singleBest = boundCompileUnit.InstantiateFunctionTemplate(functionTemplate, templateParameterMap, span, moduleId);
1511 }
1512 else
1513 {
1514 singleBest = boundCompileUnit.InstantiateInlineFunction(singleBest, containerScope, span, moduleId);
1515 }
1516 }
1517 }
1518 if (boundFunction && boundFunction->GetFunctionSymbol()->DontThrow() && !boundFunction->GetFunctionSymbol()->HasTry() && !singleBest->DontThrow())
1519 {
1520 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
1521 references.push_back(std::make_pair(boundFunction->GetFunctionSymbol()->GetSpan(), boundFunction->GetFunctionSymbol()->SourceModuleId()));
1522 references.push_back(std::make_pair(singleBest->GetSpan(), singleBest->SourceModuleId()));
1523 if (GetGlobalFlag(GlobalFlags::strictNothrow))
1524 {
1525 if ((flags & OverloadResolutionFlags::dontThrow) != OverloadResolutionFlags::none)
1526 {
1527 exception.reset(new Exception("a nothrow function cannot call a function that can throw unless it handles exceptions (compiled with --strict-nothrow)", span, moduleId, references));
1528 return std::unique_ptr<BoundFunctionCall>();
1529 }
1530 else
1531 {
1532 throw Exception("a nothrow function cannot call a function that can throw unless it handles exceptions (compiled with --strict-nothrow)", span, moduleId, references);
1533 }
1534 }
1535 else
1536 {
1537 Warning warning(module->GetCurrentProjectName(), "a nothrow function calls a function that can throw and does not handle exceptions");
1538 warning.SetDefined(span, moduleId);
1539 warning.SetReferences(references);
1540 module->WarningCollection().AddWarning(warning);
1541 }
1542 }
1543 return CreateBoundFunctionCall(singleBest, arguments, boundCompileUnit, boundFunction, bestMatch, containerScope, span, moduleId);
1544 }
1545 }
1546
1547 void CollectViableFunctionsFromSymbolTable(int arity, const std::u32string& groupName, const std::std::vector<FunctionScopeLookup>&functionScopeLookups, BoundCompileUnit&boundCompileUnit,
1548 ViableFunctionSet& viableFunctions)
1549 {
1550 std::unordered_set<ContainerScope*> scopesLookedUp;
1551 bool fileScopesLookedUp = false;
1552 for (const FunctionScopeLookup& functionScopeLookup : functionScopeLookups)
1553 {
1554 if (functionScopeLookup.scopeLookup == ScopeLookup::fileScopes && !fileScopesLookedUp)
1555 {
1556 fileScopesLookedUp = true;
1557 for (const std::std::unique_ptr<FileScope>&fileScope : boundCompileUnit.FileScopes())
1558 {
1559 fileScope->CollectViableFunctions(arity, groupName, scopesLookedUp, viableFunctions, &boundCompileUnit.GetModule());
1560 }
1561 }
1562 else
1563 {
1564 ContainerScope* scope = functionScopeLookup.scope;
1565 scope->CollectViableFunctions(arity, groupName, scopesLookedUp, functionScopeLookup.scopeLookup, viableFunctions, &boundCompileUnit.GetModule());
1566 }
1567 }
1568 }
1569
1570 std::std::unique_ptr<BoundFunctionCall>ResolveOverload(conststd::u32string&groupName, ContainerScope*containerScope, conststd::std::vector<FunctionScopeLookup>&functionScopeLookups,
1571 std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundCompileUnit&boundCompileUnit, BoundFunction*currentFunction, constSpan&span, constboost::uuids::uuid&moduleId)
1572 {
1573 std::unique_ptr<Exception> exception;
1574 std::vector<TypeSymbol*> templateArgumentTypes;
1575 return ResolveOverload(groupName, containerScope, functionScopeLookups, arguments, boundCompileUnit, currentFunction, span, moduleId,
1576 OverloadResolutionFlags::none, templateArgumentTypes, exception);
1577 }
1578
1579 std::std::unique_ptr<BoundFunctionCall>ResolveOverload(conststd::u32string&groupName, ContainerScope*containerScope, conststd::std::vector<FunctionScopeLookup>&functionScopeLookups,
1580 std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundCompileUnit&boundCompileUnit, BoundFunction*currentFunction, constSpan&span, constboost::uuids::uuid&moduleId,
1581 OverloadResolutionFlags flags, std::std::vector<TypeSymbol*>&templateArgumentTypes, std::std::unique_ptr<Exception>&exception)
1582 {
1583 Module* module = &boundCompileUnit.GetModule();
1584 int arity = arguments.size();
1585 ViableFunctionSet viableFunctions;
1586 if (currentFunction)
1587 {
1588 CollectFlags collectFlags = CollectFlags::none;
1589 if ((flags & OverloadResolutionFlags::noRvalueRef) != OverloadResolutionFlags::none)
1590 {
1591 collectFlags = collectFlags | CollectFlags::noRvalueRef;
1592 }
1593 boundCompileUnit.CollectViableFunctions(groupName, containerScope, arguments, currentFunction, viableFunctions, exception, span, moduleId, collectFlags);
1594 }
1595 if (viableFunctions.Get().empty())
1596 {
1597 if ((flags & OverloadResolutionFlags::dontThrow) == OverloadResolutionFlags::none && exception)
1598 {
1599 throw *exception;
1600 }
1601 CollectViableFunctionsFromSymbolTable(arity, groupName, functionScopeLookups, boundCompileUnit, viableFunctions);
1602 }
1603 if (viableFunctions.Get().empty())
1604 {
1605 return FailWithNoViableFunction(groupName, arguments, span, moduleId, flags, exception);
1606 }
1607 else
1608 {
1609 return SelectViableFunction(viableFunctions, groupName, arguments, containerScope, boundCompileUnit, currentFunction, span, moduleId, flags, templateArgumentTypes, exception);
1610 }
1611 }
1612
1613 } }