| 670 | bool ShouldAllowGameSpecificVirtual(FName name, unsigned index, PType* arg, PType* varg); |
| 671 | |
| 672 | int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType, bool ignorePointerReadOnly) |
| 673 | { |
| 674 | auto proto = variant->Proto; |
| 675 | for (unsigned i = 0; i < Virtuals.Size(); i++) |
| 676 | { |
| 677 | if (Virtuals[i]->Name == name) |
| 678 | { |
| 679 | auto vproto = Virtuals[i]->Proto; |
| 680 | if (vproto->ReturnTypes.Size() != proto->ReturnTypes.Size() || |
| 681 | vproto->ArgumentTypes.Size() < proto->ArgumentTypes.Size()) |
| 682 | { |
| 683 | |
| 684 | continue; // number of parameters does not match, so it's incompatible |
| 685 | } |
| 686 | bool fail = false; |
| 687 | // The first argument is self and will mismatch so just skip it. |
| 688 | for (unsigned a = 1; a < proto->ArgumentTypes.Size(); a++) |
| 689 | { |
| 690 | if (proto->ArgumentTypes[a] != vproto->ArgumentTypes[a]) |
| 691 | { |
| 692 | if(ignorePointerReadOnly && proto->ArgumentTypes[a]->isPointer() && vproto->ArgumentTypes[a]->isPointer()) |
| 693 | { |
| 694 | PPointer *ppa = proto->ArgumentTypes[a]->toPointer(); |
| 695 | PPointer *ppb = vproto->ArgumentTypes[a]->toPointer(); |
| 696 | |
| 697 | if(ppa->PointedType != ppb->PointedType) |
| 698 | { |
| 699 | fail = true; |
| 700 | break; |
| 701 | } |
| 702 | } |
| 703 | else if(!ShouldAllowGameSpecificVirtual(name, a, proto->ArgumentTypes[a], vproto->ArgumentTypes[a])) |
| 704 | { |
| 705 | fail = true; |
| 706 | break; |
| 707 | } |
| 708 | } |
| 709 | } |
| 710 | if (fail) continue; |
| 711 | |
| 712 | for (unsigned a = 0; a < proto->ReturnTypes.Size(); a++) |
| 713 | { |
| 714 | PType* expected = vproto->ReturnTypes[a]; |
| 715 | PType* actual = proto->ReturnTypes[a]; |
| 716 | |
| 717 | if (expected != actual && (exactReturnType || !AreCompatiblePointerTypes(expected, actual))) |
| 718 | { |
| 719 | fail = true; |
| 720 | break; |
| 721 | } |
| 722 | } |
| 723 | if (!fail) |
| 724 | { |
| 725 | if (vproto->ArgumentTypes.Size() > proto->ArgumentTypes.Size() && parentfunc) |
| 726 | { |
| 727 | // Check if the difference between both functions is only some optional arguments. |
| 728 | for (unsigned a = proto->ArgumentTypes.Size(); a < vproto->ArgumentTypes.Size(); a++) |
| 729 | { |
no test coverage detected