Browse Source

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

Brian Fiete 5 years ago
parent
commit
808a4438d7

+ 6 - 0
BeefLibs/corlib/src/Attribute.bf

@@ -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
 	{
 	{

+ 10 - 8
IDEHelper/Compiler/BfDefBuilder.cpp

@@ -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;
 		}
 		}

+ 36 - 23
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -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);
 		}
 		}

+ 1 - 1
IDEHelper/Compiler/BfExprEvaluator.h

@@ -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);

+ 2 - 2
IDEHelper/Compiler/BfModule.cpp

@@ -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)

+ 4 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -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();
 }
 }
 
 

+ 10 - 7
IDEHelper/Compiler/BfSystem.h

@@ -720,9 +720,10 @@ public:
 	bool mCLink;
 	bool mCLink;
 	bool mHasAppend;
 	bool mHasAppend;
 	bool mAlwaysInline;	
 	bool mAlwaysInline;	
-	bool mNoReturn;
-	bool mIsMutating;	
-	bool mNoReflect;
+	bool mIsNoReturn;
+	bool mIsMutating;
+	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;
-		mIsMutating = false;		
-		mNoReflect = false;
+		mIsNoReturn = false;
+		mIsMutating = 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
 };
 };