| 3827 | } |
| 3828 | |
| 3829 | bool AddMemberFunctionCall(const char* pos, const char* funcName, unsigned int callArgCount, bool silent) |
| 3830 | { |
| 3831 | // Check if type has any member functions |
| 3832 | TypeInfo *currentType = CodeInfo::nodeList[CodeInfo::nodeList.size()-callArgCount-1]->typeInfo; |
| 3833 | // For auto ref types, we redirect call to a target type |
| 3834 | if(currentType == CodeInfo::GetReferenceType(typeObject)) |
| 3835 | { |
| 3836 | // We need to know what function overload is called, and this is a long process: |
| 3837 | // Get function name hash |
| 3838 | unsigned int fHash = GetStringHash(funcName); |
| 3839 | |
| 3840 | // Clear function list |
| 3841 | bestFuncList.clear(); |
| 3842 | // Find all functions with called name that are member functions |
| 3843 | for(unsigned int i = 0; i < CodeInfo::funcInfo.size(); i++) |
| 3844 | { |
| 3845 | FunctionInfo *func = CodeInfo::funcInfo[i]; |
| 3846 | if(func->nameHashOrig == fHash && func->parentClass && func->visible && !((func->address & 0x80000000) && (func->address != -1)) && func->funcType) |
| 3847 | bestFuncList.push_back(func); |
| 3848 | } |
| 3849 | unsigned int count = bestFuncList.size(); |
| 3850 | if(count == 0) |
| 3851 | ThrowError(pos, "ERROR: function '%s' is undefined in any of existing classes", funcName); |
| 3852 | |
| 3853 | // Find best function fit |
| 3854 | unsigned minRating = ~0u; |
| 3855 | unsigned minRatingIndex = SelectBestFunction(bestFuncList.size(), callArgCount, minRating); |
| 3856 | if(minRating == ~0u) |
| 3857 | ThrowError(pos, "ERROR: none of the member ::%s functions can handle the supplied parameter list without conversions", funcName); |
| 3858 | FunctionInfo *fInfo = bestFuncList[minRatingIndex]; |
| 3859 | if(fInfo && fInfo->generic) |
| 3860 | CreateGenericFunctionInstance(pos, fInfo, fInfo, ~0u, fInfo->parentClass); |
| 3861 | |
| 3862 | // Get function type |
| 3863 | TypeInfo *fType = fInfo->funcType; |
| 3864 | |
| 3865 | unsigned int lenStr = 5 + (int)strlen(funcName) + 1 + 32; |
| 3866 | char *vtblName = AllocateString(lenStr); |
| 3867 | SafeSprintf(vtblName, lenStr, "$vtbl%010u%s", fType->GetFullNameHash(), funcName); |
| 3868 | unsigned int hash = GetStringHash(vtblName); |
| 3869 | VariableInfo *target = vtblList; |
| 3870 | if(target && target->nameHash != hash) |
| 3871 | target = target->next; |
| 3872 | |
| 3873 | // If vtbl cannot be found, create it |
| 3874 | if(!target) |
| 3875 | { |
| 3876 | // Create array of function pointer (function pointer is an integer index) |
| 3877 | VariableInfo *vInfo = new VariableInfo(0, InplaceStr(vtblName), hash, 500000, CodeInfo::GetArrayType(typeInt, TypeInfo::UNSIZED_ARRAY), true); |
| 3878 | vInfo->next = vtblList; |
| 3879 | vInfo->prev = (VariableInfo*)fType; // $$ not type safe at all |
| 3880 | target = vtblList = vInfo; |
| 3881 | } |
| 3882 | // Take node with auto ref computation |
| 3883 | NodeZeroOP *autoRef = CodeInfo::nodeList[CodeInfo::nodeList.size()-callArgCount-1]; |
| 3884 | // Push it on the top |
| 3885 | CodeInfo::nodeList.push_back(autoRef); |
| 3886 | // We have auto ref ref, so dereference it |
no test coverage detected