| 13438 | } |
| 13439 | |
| 13440 | BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags, BfCastResultFlags* resultFlags) |
| 13441 | { |
| 13442 | bool silentFail = ((castFlags & BfCastFlags_SilentFail) != 0); |
| 13443 | bool explicitCast = (castFlags & BfCastFlags_Explicit) != 0; |
| 13444 | bool ignoreErrors = mIgnoreErrors || ((castFlags & BfCastFlags_SilentFail) != 0); |
| 13445 | bool ignoreWrites = mBfIRBuilder->mIgnoreWrites; |
| 13446 | |
| 13447 | if (typedVal.mType == toType) |
| 13448 | { |
| 13449 | if (resultFlags != NULL) |
| 13450 | { |
| 13451 | if (typedVal.IsAddr()) |
| 13452 | *resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsAddr); |
| 13453 | if (typedVal.mKind == BfTypedValueKind_TempAddr) |
| 13454 | *resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsTemp); |
| 13455 | } |
| 13456 | else if (typedVal.IsAddr()) |
| 13457 | typedVal = LoadValue(typedVal); |
| 13458 | |
| 13459 | return typedVal.mValue; |
| 13460 | } |
| 13461 | |
| 13462 | BF_ASSERT(typedVal.mType->mContext == mContext); |
| 13463 | BF_ASSERT(toType->mContext == mContext); |
| 13464 | |
| 13465 | if ((typedVal.IsAddr()) && (!typedVal.mType->IsValueType())) |
| 13466 | typedVal = LoadValue(typedVal); |
| 13467 | |
| 13468 | //BF_ASSERT(!typedVal.IsAddr() || typedVal.mType->IsGenericParam() || typedVal.mType->IsValueType()); |
| 13469 | |
| 13470 | // Ref X to Ref Y, X* to Y* |
| 13471 | { |
| 13472 | bool checkUnderlying = false; |
| 13473 | bool isRef = false; |
| 13474 | |
| 13475 | if (((typedVal.mType->IsRef()) && (toType->IsRef()))) |
| 13476 | { |
| 13477 | isRef = true; |
| 13478 | auto fromRefType = (BfRefType*)typedVal.mType; |
| 13479 | auto toRefType = (BfRefType*)toType; |
| 13480 | if (fromRefType->mRefKind == toRefType->mRefKind) |
| 13481 | checkUnderlying = true; |
| 13482 | else if ((fromRefType->mRefKind == BfRefType::RefKind_Ref) && (toRefType->mRefKind == BfRefType::RefKind_Mut)) |
| 13483 | checkUnderlying = true; // Allow a ref-to-mut implicit conversion |
| 13484 | } |
| 13485 | |
| 13486 | if ((typedVal.mType->IsPointer()) && (toType->IsPointer())) |
| 13487 | checkUnderlying = true; |
| 13488 | |
| 13489 | if (checkUnderlying) |
| 13490 | { |
| 13491 | auto fromInner = typedVal.mType->GetUnderlyingType(); |
| 13492 | auto toInner = toType->GetUnderlyingType(); |
| 13493 | |
| 13494 | if (fromInner == toInner) |
| 13495 | { |
| 13496 | return typedVal.mValue; |
| 13497 | } |
no test coverage detected