| 1043 | } |
| 1044 | |
| 1045 | void AddReturnNode(const char* pos, bool yield) |
| 1046 | { |
| 1047 | bool localReturn = currDefinedFunc.size() != 0; |
| 1048 | |
| 1049 | // If new function is returned, convert it to pointer |
| 1050 | ConvertFunctionToPointer(pos, currDefinedFunc.size() ? currDefinedFunc.back()->retType : NULL); |
| 1051 | |
| 1052 | // Type that is being returned |
| 1053 | TypeInfo *realRetType = CodeInfo::nodeList.back()->typeInfo; |
| 1054 | |
| 1055 | // Type that should be returned |
| 1056 | TypeInfo *expectedType = NULL; |
| 1057 | if(currDefinedFunc.size() != 0) |
| 1058 | { |
| 1059 | // If return type is auto, set it to type that is being returned |
| 1060 | if(!currDefinedFunc.back()->retType) |
| 1061 | { |
| 1062 | currDefinedFunc.back()->retType = realRetType; |
| 1063 | currDefinedFunc.back()->funcType = CodeInfo::GetFunctionType(currDefinedFunc.back()->retType, currDefinedFunc.back()->firstParam, currDefinedFunc.back()->paramCount); |
| 1064 | }else{ |
| 1065 | ConvertArrayToUnsized(pos, currDefinedFunc.back()->retType); |
| 1066 | HandlePointerToObject(pos, currDefinedFunc.back()->retType); |
| 1067 | realRetType = CodeInfo::nodeList.back()->typeInfo; |
| 1068 | } |
| 1069 | // Take expected return type |
| 1070 | expectedType = currDefinedFunc.back()->retType; |
| 1071 | if(expectedType->refLevel || (expectedType->arrLevel && expectedType->arrSize == TypeInfo::UNSIZED_ARRAY)) |
| 1072 | { |
| 1073 | if(CodeInfo::nodeList.back()->nodeType != typeNodeZeroOp) |
| 1074 | { |
| 1075 | CodeInfo::nodeList.push_back(new NodeUnaryOp(cmdCheckedRet, expectedType->arrLevel ? expectedType->typeIndex : expectedType->subType->typeIndex)); |
| 1076 | ((NodeUnaryOp*)CodeInfo::nodeList.back())->SetParentFunc(currDefinedFunc.back()); |
| 1077 | } |
| 1078 | } |
| 1079 | // Check for errors |
| 1080 | if(((expectedType->type == TypeInfo::TYPE_COMPLEX || realRetType->type == TypeInfo::TYPE_COMPLEX || expectedType->firstVariable || realRetType->firstVariable) && expectedType != realRetType) || expectedType->subType != realRetType->subType) |
| 1081 | ThrowError(pos, "ERROR: function returns %s but supposed to return %s", realRetType->GetFullTypeName(), expectedType->GetFullTypeName()); |
| 1082 | if(expectedType == typeVoid && realRetType != typeVoid) |
| 1083 | ThrowError(pos, "ERROR: 'void' function returning a value"); |
| 1084 | if(expectedType != typeVoid && realRetType == typeVoid) |
| 1085 | ThrowError(pos, "ERROR: function should return %s", expectedType->GetFullTypeName()); |
| 1086 | if(yield && currDefinedFunc.back()->type != FunctionInfo::COROUTINE) |
| 1087 | ThrowError(pos, "ERROR: yield can only be used inside a coroutine"); |
| 1088 | #ifdef NULLC_ENABLE_C_TRANSLATION |
| 1089 | if(yield) |
| 1090 | currDefinedFunc.back()->yieldCount++; |
| 1091 | #endif |
| 1092 | currDefinedFunc.back()->explicitlyReturned = true; |
| 1093 | }else{ |
| 1094 | // Check for errors |
| 1095 | if(realRetType == typeVoid) |
| 1096 | ThrowError(pos, "ERROR: global return cannot accept void"); |
| 1097 | else if(realRetType->type == TypeInfo::TYPE_COMPLEX) |
| 1098 | ThrowError(pos, "ERROR: global return cannot accept complex types"); |
| 1099 | // Global return return type is auto, so we take type that is being returned |
| 1100 | expectedType = realRetType; |
| 1101 | } |
| 1102 | // Add node and link source to instruction |
no test coverage detected