1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

Address-of immutable is now a warning instead of error, added [NoSplat]

This commit is contained in:
Brian Fiete 2020-10-07 11:07:10 -07:00
parent 557b13070c
commit 808a4438d7
7 changed files with 69 additions and 41 deletions

View file

@ -230,6 +230,12 @@ namespace System
} }
[AttributeUsage(.Method /*2*/)]
public struct NoSplatAttribute : Attribute
{
}
[AttributeUsage(.Method /*2*/)] [AttributeUsage(.Method /*2*/)]
public struct SkipCallAttribute : Attribute public struct SkipCallAttribute : Attribute
{ {

View file

@ -795,13 +795,15 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
} }
} }
else if (typeRefName == "NoReturn") else if (typeRefName == "NoReturn")
methodDef->mNoReturn = true; methodDef->mIsNoReturn = true;
else if (typeRefName == "SkipCall") else if (typeRefName == "SkipCall")
methodDef->mIsSkipCall = true; methodDef->mIsSkipCall = true;
else if (typeRefName == "NoShow") else if (typeRefName == "NoShow")
methodDef->mIsNoShow = true; methodDef->mIsNoShow = true;
else if (typeRefName == "NoDiscard") else if (typeRefName == "NoDiscard")
methodDef->mIsNoDiscard = true; methodDef->mIsNoDiscard = true;
else if (typeRefName == "NoSplat")
methodDef->mIsNoSplat = true;
else if (typeRefName == "Commutable") else if (typeRefName == "Commutable")
{ {
if (methodDef->mParams.size() != 2) if (methodDef->mParams.size() != 2)
@ -1122,12 +1124,12 @@ BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType
else if (methodType == BfMethodType_CtorNoBody) else if (methodType == BfMethodType_CtorNoBody)
{ {
methodDef->mName = "__BfCtorNoBody"; methodDef->mName = "__BfCtorNoBody";
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
} }
else if (methodType == BfMethodType_CtorClear) else if (methodType == BfMethodType_CtorClear)
{ {
methodDef->mName = "__BfCtorClear"; methodDef->mName = "__BfCtorClear";
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
} }
else if (methodType == BfMethodType_Dtor) else if (methodType == BfMethodType_Dtor)
{ {
@ -1191,7 +1193,7 @@ void BfDefBuilder::AddDynamicCastMethods(BfTypeDef* typeDef)
paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef; paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
methodDef->mParams.push_back(paramDef); methodDef->mParams.push_back(paramDef);
methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef; methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
} }
// //
@ -1212,7 +1214,7 @@ void BfDefBuilder::AddDynamicCastMethods(BfTypeDef* typeDef)
paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef; paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
methodDef->mParams.push_back(paramDef); methodDef->mParams.push_back(paramDef);
methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef; methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
} }
} }
@ -2048,13 +2050,13 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if ((hasStaticField) && (!hasStaticMarkMethod)) if ((hasStaticField) && (!hasStaticMarkMethod))
{ {
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC); auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC);
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
} }
if (hasThreadStatics) if (hasThreadStatics)
{ {
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_FIND_TLS_MEMBERS); auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_FIND_TLS_MEMBERS);
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
} }
if ((hasNonStaticField) && (!hasMarkMethod)) if ((hasNonStaticField) && (!hasMarkMethod))
@ -2062,7 +2064,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS); auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS);
methodDef->mIsVirtual = true; methodDef->mIsVirtual = true;
methodDef->mIsOverride = true; methodDef->mIsOverride = true;
methodDef->mNoReflect = true; methodDef->mIsNoReflect = true;
methodDef->mCallingConvention = BfCallingConvention_Cdecl; methodDef->mCallingConvention = BfCallingConvention_Cdecl;
mCurTypeDef->mHasOverrideMethods = true; mCurTypeDef->mHasOverrideMethods = true;
} }

View file

@ -4638,7 +4638,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
mModule->mCurMethodState->mCancelledDeferredCall = true; mModule->mCurMethodState->mCancelledDeferredCall = true;
} }
if (methodDef->mNoReturn) if (methodDef->mIsNoReturn)
{ {
mModule->mCurMethodState->SetHadReturn(true); mModule->mCurMethodState->SetHadReturn(true);
mModule->mCurMethodState->mLeftBlockUncond = true; mModule->mCurMethodState->mLeftBlockUncond = true;
@ -4984,7 +4984,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
if ((expectCallingConvention != BfIRCallingConv_CDecl) && (!methodInstance->mIsIntrinsic)) if ((expectCallingConvention != BfIRCallingConv_CDecl) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->SetCallCallingConv(callInst, expectCallingConvention); mModule->mBfIRBuilder->SetCallCallingConv(callInst, expectCallingConvention);
if ((methodDef->mNoReturn) && (!methodInstance->mIsIntrinsic)) if ((methodDef->mIsNoReturn) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->Call_AddAttribute(callInst, -1, BfIRAttribute_NoReturn); mModule->mBfIRBuilder->Call_AddAttribute(callInst, -1, BfIRAttribute_NoReturn);
bool hadAttrs = false; bool hadAttrs = false;
@ -5146,7 +5146,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
if (isTailCall) if (isTailCall)
mModule->mBfIRBuilder->SetTailCall(callInst); mModule->mBfIRBuilder->SetTailCall(callInst);
if (methodDef->mNoReturn) if (methodDef->mIsNoReturn)
{ {
mModule->mBfIRBuilder->CreateUnreachable(); mModule->mBfIRBuilder->CreateUnreachable();
// For debuggability when looking back at stack trace // For debuggability when looking back at stack trace
@ -15737,7 +15737,7 @@ bool BfExprEvaluator::CheckIsBase(BfAstNode* checkNode)
return true; return true;
} }
bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut) bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut, bool emitWarning)
{ {
BfLocalVariable* localVar = NULL; BfLocalVariable* localVar = NULL;
bool isCapturedLocal = false; bool isCapturedLocal = false;
@ -15774,10 +15774,18 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
bool canModify = typedVal.CanModify(); bool canModify = typedVal.CanModify();
auto _Fail = [&](const StringImpl& error, BfAstNode* refNode)
{
if (emitWarning)
return mModule->Warn(BfWarning_BF4204_AddressOfReadOnly, error, refNode);
else
return mModule->Fail(error, refNode);
};
if (localVar != NULL) if (localVar != NULL)
{ {
if (!canModify) if (!canModify)
{ {
BfError* error = NULL; BfError* error = NULL;
if (localVar->mIsThis) if (localVar->mIsThis)
{ {
@ -15807,18 +15815,18 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
if (isClosure) if (isClosure)
{ {
if (!mModule->mCurMethodState->mClosureState->mDeclaringMethodIsMutating) if (!mModule->mCurMethodState->mClosureState->mDeclaringMethodIsMutating)
error = mModule->Fail(StrFormat("Cannot %s 'this' within struct lambda. Consider adding 'mut' specifier to this method.", modifyType), refNode); error = _Fail(StrFormat("Cannot %s 'this' within struct lambda. Consider adding 'mut' specifier to this method.", modifyType), refNode);
else else
error = mModule->Fail(StrFormat("Cannot %s 'this' within struct lambda. Consider adding by-reference capture specifier [&] to lambda.", modifyType), refNode); error = _Fail(StrFormat("Cannot %s 'this' within struct lambda. Consider adding by-reference capture specifier [&] to lambda.", modifyType), refNode);
} }
else if (localVar->mResolvedType->IsValueType()) else if (localVar->mResolvedType->IsValueType())
{ {
error = mModule->Fail(StrFormat("Cannot %s 'this' within struct method '%s'. Consider adding 'mut' specifier to this method.", modifyType, error = _Fail(StrFormat("Cannot %s 'this' within struct method '%s'. Consider adding 'mut' specifier to this method.", modifyType,
mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
} }
else else
{ {
error = mModule->Fail(StrFormat("Cannot %s 'this' because '%s' is a reference type.", modifyType, error = _Fail(StrFormat("Cannot %s 'this' because '%s' is a reference type.", modifyType,
mModule->TypeToString(localVar->mResolvedType).c_str()), refNode); mModule->TypeToString(localVar->mResolvedType).c_str()), refNode);
} }
return false; return false;
@ -15827,21 +15835,21 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
{ {
if (isCapturedLocal) if (isCapturedLocal)
{ {
error = mModule->Fail(StrFormat("Cannot %s read-only captured local variable '%s'. Consider adding by-reference capture specifier [&] to lambda and ensuring that captured value is not read-only.", modifyType, error = _Fail(StrFormat("Cannot %s read-only captured local variable '%s'. Consider adding by-reference capture specifier [&] to lambda and ensuring that captured value is not read-only.", modifyType,
mResultFieldInstance->GetFieldDef()->mName.c_str()), refNode); mResultFieldInstance->GetFieldDef()->mName.c_str()), refNode);
} }
else if (isClosure) else if (isClosure)
{ {
if (!mModule->mCurMethodState->mClosureState->mDeclaringMethodIsMutating) if (!mModule->mCurMethodState->mClosureState->mDeclaringMethodIsMutating)
error = mModule->Fail(StrFormat("Cannot %s field '%s.%s' within struct lambda. Consider adding 'mut' specifier to this method.", modifyType, error = _Fail(StrFormat("Cannot %s field '%s.%s' within struct lambda. Consider adding 'mut' specifier to this method.", modifyType,
mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str()), refNode); mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str()), refNode);
else else
error = mModule->Fail(StrFormat("Cannot %s field '%s.%s' within struct lambda. Consider adding by-reference capture specifier [&] to lambda.", modifyType, error = _Fail(StrFormat("Cannot %s field '%s.%s' within struct lambda. Consider adding by-reference capture specifier [&] to lambda.", modifyType,
mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str()), refNode); mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str()), refNode);
} }
else if (mResultFieldInstance->GetFieldDef()->mIsReadOnly) else if (mResultFieldInstance->GetFieldDef()->mIsReadOnly)
{ {
error = mModule->Fail(StrFormat("Cannot %s readonly field '%s.%s' within method '%s'", modifyType, error = _Fail(StrFormat("Cannot %s readonly field '%s.%s' within method '%s'", modifyType,
mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str(), mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str(),
mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
} }
@ -15851,12 +15859,12 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
if (propertyDeclaration->mNameNode != NULL) if (propertyDeclaration->mNameNode != NULL)
propertyDeclaration->mNameNode->ToString(propNam); propertyDeclaration->mNameNode->ToString(propNam);
error = mModule->Fail(StrFormat("Cannot %s auto-implemented property '%s.%s' without set accessor", modifyType, error = _Fail(StrFormat("Cannot %s auto-implemented property '%s.%s' without set accessor", modifyType,
mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), propNam.c_str()), refNode); mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), propNam.c_str()), refNode);
} }
else else
{ {
error = mModule->Fail(StrFormat("Cannot %s field '%s.%s' within struct method '%s'. Consider adding 'mut' specifier to this method.", modifyType, error = _Fail(StrFormat("Cannot %s field '%s.%s' within struct method '%s'. Consider adding 'mut' specifier to this method.", modifyType,
mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str(), mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str(),
mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
} }
@ -15868,13 +15876,13 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
if (!mModule->mCurMethodInstance->IsMixin()) if (!mModule->mCurMethodInstance->IsMixin())
{ {
if (mModule->mCurMethodState->mMixinState != NULL) if (mModule->mCurMethodState->mMixinState != NULL)
error = mModule->Fail(StrFormat("Cannot %s mixin parameter '%s'", modifyType, error = _Fail(StrFormat("Cannot %s mixin parameter '%s'", modifyType,
localVar->mName.c_str(), mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); localVar->mName.c_str(), mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
else if ((localVar->mResolvedType->IsGenericParam()) && (onlyNeedsMut)) else if ((localVar->mResolvedType->IsGenericParam()) && (onlyNeedsMut))
error = mModule->Fail(StrFormat("Cannot %s parameter '%s'. Consider adding 'mut' or 'ref' specifier to parameter or copying to a local variable.", modifyType, error = _Fail(StrFormat("Cannot %s parameter '%s'. Consider adding 'mut' or 'ref' specifier to parameter or copying to a local variable.", modifyType,
localVar->mName.c_str(), mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); localVar->mName.c_str(), mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
else else
error = mModule->Fail(StrFormat("Cannot %s parameter '%s'. Consider adding 'ref' specifier to parameter or copying to a local variable.", modifyType, error = _Fail(StrFormat("Cannot %s parameter '%s'. Consider adding 'ref' specifier to parameter or copying to a local variable.", modifyType,
localVar->mName.c_str(), mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); localVar->mName.c_str(), mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
return false; return false;
} }
@ -15891,7 +15899,7 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
{ {
if (field.mDataIdx == dataIdx) if (field.mDataIdx == dataIdx)
{ {
error = mModule->Fail(StrFormat("Cannot %s readonly field '%s.%s'.", modifyType, error = _Fail(StrFormat("Cannot %s readonly field '%s.%s'.", modifyType,
mModule->TypeToString(typeInst).c_str(), mModule->TypeToString(typeInst).c_str(),
field.GetFieldDef()->mName.c_str()), refNode); field.GetFieldDef()->mName.c_str()), refNode);
break; break;
@ -15904,7 +15912,7 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
if (error == NULL) if (error == NULL)
{ {
error = mModule->Fail(StrFormat("Cannot %s read-only local variable '%s'.", modifyType, error = _Fail(StrFormat("Cannot %s read-only local variable '%s'.", modifyType,
localVar->mName.c_str()), refNode); localVar->mName.c_str()), refNode);
} }
return false; return false;
@ -15919,14 +15927,13 @@ bool BfExprEvaluator::CheckModifyResult(BfTypedValue typedVal, BfAstNode* refNod
if ((mResultFieldInstance != NULL) && (mResultFieldInstance->GetFieldDef()->mIsReadOnly) && (!canModify)) if ((mResultFieldInstance != NULL) && (mResultFieldInstance->GetFieldDef()->mIsReadOnly) && (!canModify))
{ {
auto error = mModule->Fail(StrFormat("Cannot %s static readonly field '%s.%s' within method '%s'", modifyType, auto error = _Fail(StrFormat("Cannot %s static readonly field '%s.%s' within method '%s'", modifyType,
mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str(), mModule->TypeToString(mResultFieldInstance->mOwner).c_str(), mResultFieldInstance->GetFieldDef()->mName.c_str(),
mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode); mModule->MethodToString(mModule->mCurMethodInstance).c_str()), refNode);
return false; return false;
} }
return mModule->CheckModifyValue(typedVal, refNode, modifyType); return mModule->CheckModifyValue(typedVal, refNode, modifyType);
} }
@ -18367,12 +18374,18 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
mModule->FixIntUnknown(mResult); mModule->FixIntUnknown(mResult);
mModule->PopulateType(mResult.mType); mModule->PopulateType(mResult.mType);
auto ptrType = mModule->CreatePointerType(mResult.mType); auto ptrType = mModule->CreatePointerType(mResult.mType);
if ((!CheckModifyResult(mResult, unaryOpExpr, "take address of")) || (mResult.mType->IsValuelessType())) if (mResult.mType->IsValuelessType())
{ {
// Sentinel value // Sentinel value
auto val = mModule->mBfIRBuilder->CreateIntToPtr(mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1), mModule->mBfIRBuilder->MapType(ptrType)); auto val = mModule->mBfIRBuilder->CreateIntToPtr(mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1), mModule->mBfIRBuilder->MapType(ptrType));
mResult = BfTypedValue(val, ptrType); mResult = BfTypedValue(val, ptrType);
} }
else if (!CheckModifyResult(mResult, unaryOpExpr, "take address of", false, true))
{
if (!mResult.IsAddr())
mResult = mModule->MakeAddressable(mResult);
mResult = BfTypedValue(mResult.mValue, ptrType, false);
}
else else
mResult = BfTypedValue(mResult.mValue, ptrType, false); mResult = BfTypedValue(mResult.mValue, ptrType, false);
} }

View file

@ -377,7 +377,7 @@ public:
void MarkResultAssigned(); void MarkResultAssigned();
void MakeResultAsValue(); void MakeResultAsValue();
bool CheckIsBase(BfAstNode* checkNode); bool CheckIsBase(BfAstNode* checkNode);
bool CheckModifyResult(BfTypedValue typeValue, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut = false); bool CheckModifyResult(BfTypedValue typeValue, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut = false, bool emitWarning = false);
bool CheckGenericCtor(BfGenericParamType* genericParamType, BfResolvedArgs& argValues, BfAstNode* targetSrc); bool CheckGenericCtor(BfGenericParamType* genericParamType, BfResolvedArgs& argValues, BfAstNode* targetSrc);
BfTypedValue LookupField(BfAstNode* targetSrc, BfTypedValue target, const StringImpl& fieldName, BfLookupFieldFlags flags = BfLookupFieldFlag_None); BfTypedValue LookupField(BfAstNode* targetSrc, BfTypedValue target, const StringImpl& fieldName, BfLookupFieldFlags flags = BfLookupFieldFlag_None);
void CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode* afterNode); void CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode* afterNode);

View file

@ -6113,7 +6113,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if (!methodInstanceGroup->IsImplemented()) if (!methodInstanceGroup->IsImplemented())
continue; continue;
auto methodDef = typeDef->mMethods[methodIdx]; auto methodDef = typeDef->mMethods[methodIdx];
if (methodDef->mNoReflect) if (methodDef->mIsNoReflect)
continue; continue;
auto defaultMethod = methodInstanceGroup->mDefault; auto defaultMethod = methodInstanceGroup->mDefault;
@ -15146,7 +15146,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
if (methodDef->mImportKind == BfImportKind_Export) if (methodDef->mImportKind == BfImportKind_Export)
mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport); mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport);
if (methodDef->mNoReturn) if (methodDef->mIsNoReturn)
mBfIRBuilder->Func_AddAttribute(func, -1, BfIRAttribute_NoReturn); mBfIRBuilder->Func_AddAttribute(func, -1, BfIRAttribute_NoReturn);
auto callingConv = GetIRCallingConvention(methodInstance); auto callingConv = GetIRCallingConvention(methodInstance);
if (callingConv != BfIRCallingConv_CDecl) if (callingConv != BfIRCallingConv_CDecl)

View file

@ -764,6 +764,8 @@ bool BfMethodInstance::AllowsSplatting()
{ {
if (mCallingConvention != BfCallingConvention_Unspecified) if (mCallingConvention != BfCallingConvention_Unspecified)
return false; return false;
if (mMethodDef->mIsNoSplat)
return false;
return true; return true;
} }
@ -771,6 +773,8 @@ bool BfMethodInstance::AllowsThisSplatting()
{ {
if (mCallingConvention != BfCallingConvention_Unspecified) if (mCallingConvention != BfCallingConvention_Unspecified)
return false; return false;
if (mMethodDef->mIsNoSplat)
return false;
return !mMethodDef->HasNoThisSplat(); return !mMethodDef->HasNoThisSplat();
} }

View file

@ -720,9 +720,10 @@ public:
bool mCLink; bool mCLink;
bool mHasAppend; bool mHasAppend;
bool mAlwaysInline; bool mAlwaysInline;
bool mNoReturn; bool mIsNoReturn;
bool mIsMutating; bool mIsMutating;
bool mNoReflect; bool mIsNoSplat;
bool mIsNoReflect;
bool mIsSkipCall; bool mIsSkipCall;
bool mIsOperator; bool mIsOperator;
bool mIsExtern; bool mIsExtern;
@ -747,9 +748,10 @@ public:
mIsNew = false; mIsNew = false;
mIsPartial = false; mIsPartial = false;
mCLink = false; mCLink = false;
mNoReturn = false; mIsNoReturn = false;
mIsMutating = false; mIsMutating = false;
mNoReflect = false; mIsNoSplat = false;
mIsNoReflect = false;
mIsSkipCall = false; mIsSkipCall = false;
mIsOperator = false; mIsOperator = false;
mIsExtern = false; mIsExtern = false;
@ -774,7 +776,7 @@ public:
virtual ~BfMethodDef(); virtual ~BfMethodDef();
static BfImportKind GetImportKindFromPath(const StringImpl& filePath); static BfImportKind GetImportKindFromPath(const StringImpl& filePath);
bool HasNoThisSplat() { return mIsMutating; } bool HasNoThisSplat() { return mIsMutating || mIsNoSplat; }
void Reset(); void Reset();
void FreeMembers(); void FreeMembers();
BfMethodDeclaration* GetMethodDeclaration(); BfMethodDeclaration* GetMethodDeclaration();
@ -1103,6 +1105,7 @@ enum BfWarning
BfWarning_BF4201_Only7Hex = 4201, BfWarning_BF4201_Only7Hex = 4201,
BfWarning_BF4202_TooManyHexForInt = 4202, BfWarning_BF4202_TooManyHexForInt = 4202,
BfWarning_BF4203_UnnecessaryDynamicCast = 4203, BfWarning_BF4203_UnnecessaryDynamicCast = 4203,
BfWarning_BF4204_AddressOfReadOnly = 4204,
BfWarning_C4554_PossiblePrecedenceError = 4554 BfWarning_C4554_PossiblePrecedenceError = 4554
}; };