From 348625125424bbd2322f3aa7136769d824a84165 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 18 Jan 2020 14:43:42 -0800 Subject: [PATCH] Fixed errors for circular data references in member attributes --- IDEHelper/Compiler/BfContext.h | 2 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 51 ++++++++- IDEHelper/Compiler/BfExprEvaluator.h | 1 + IDEHelper/Compiler/BfModule.cpp | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 129 +++++++++++++---------- 5 files changed, 124 insertions(+), 61 deletions(-) diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 8f0043fa..a4a51984 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -119,7 +119,7 @@ public: BfPopulateType mPopulateType; BfTypeReference* mCurBaseTypeRef; BfTypeReference* mCurAttributeTypeRef; - BfFieldDef* mCurFieldDef; + BfFieldDef* mCurFieldDef; BfTypeDef* mCurTypeDef; bool mBuildingGenericParams; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 1d108a5c..209019ca 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2066,6 +2066,7 @@ BfExprEvaluator::BfExprEvaluator(BfModule* module) mIsHeapReference = false; mResultIsTempComposite = false; mAllowReadOnlyReference = false; + mInsidePendingNullable = false; mReceivingValue = NULL; } @@ -2167,6 +2168,7 @@ void BfExprEvaluator::Evaluate(BfAstNode* astNode, bool propogateNullConditional if (!propogateNullConditional) mModule->mCurMethodState->mPendingNullConditional = NULL; } + mInsidePendingNullable = pendingNullCond != NULL; astNode->Accept(this); GetResult(); @@ -5634,6 +5636,11 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType bool isLet = variableDeclaration->mTypeRef->IsExact(); bool isVar = variableDeclaration->mTypeRef->IsExact(); + if (mModule->mCurMethodState->mPendingNullConditional != NULL) + { + mModule->Fail("Variables cannot be declared in method arguments inside null conditional expressions", variableDeclaration); + } + if ((!isLet) && (!isVar)) { mModule->Fail("Only 'ref' or 'var' variables can be declared in method arguments", variableDeclaration); @@ -12237,7 +12244,8 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo argExprEvaluators.push_back(new BfExprEvaluator(mModule)); BfExprEvaluator* exprEvaluator = argExprEvaluators.back(); - exprEvaluator->mResolveGenericParam = false; + exprEvaluator->mResolveGenericParam = false; + exprEvaluator->mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator->mBfEvalExprFlags | BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr); if (argExpr != NULL) exprEvaluator->Evaluate(argExpr, false, false, true); auto argValue = exprEvaluator->mResult; @@ -12634,6 +12642,37 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo { // Already handled } + else if (newLocalVar->mIsSplat) + { + bool found = false; + + auto checkMethodState = mModule->mCurMethodState; + while ((checkMethodState != NULL) && (!found)) + { + for (auto localVar : checkMethodState->mLocals) + { + if (localVar == newLocalVar) + continue; + if (newLocalVar->mValue != localVar->mValue) + continue; + + String name = newLocalVar->mName; + name += "$alias$"; + name += localVar->mName; + + auto fakeValue = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0); + auto diType = mModule->mBfIRBuilder->DbgGetType(mModule->GetPrimitiveType(BfTypeCode_Int32)); + auto diVariable = mModule->mBfIRBuilder->DbgCreateAutoVariable(mModule->mCurMethodState->mCurScope->mDIScope, + newLocalVar->mName, mModule->mCurFilePosition.mFileInstance->mDIFile, mModule->mCurFilePosition.mCurLine, diType); + mModule->mBfIRBuilder->DbgInsertValueIntrinsic(fakeValue, diVariable); + + found = true; + break; + } + + checkMethodState = checkMethodState->mPrevMethodState; + } + } else if (mModule->IsTargetingBeefBackend()) { mModule->UpdateSrcPos(methodDeclaration->mNameNode); @@ -12707,7 +12746,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo if (!mModule->mBfIRBuilder->mIgnoreWrites) { if (newLocalVar->mIsSplat) - { + { //TODO: Implement } else @@ -16635,7 +16674,13 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, return; } - MarkResultAssigned(); + if (mInsidePendingNullable) + { + // 'out' inside null conditionals never actually causes a definite assignment... + } + else + MarkResultAssigned(); + MarkResultUsed(); ResolveGenericType(); mResult = BfTypedValue(mResult.mValue, mModule->CreateRefType(mResult.mType, BfRefType::RefKind_Out)); diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index f41c540c..ceba7bcd 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -308,6 +308,7 @@ public: bool mIsHeapReference; bool mResultIsTempComposite; bool mAllowReadOnlyReference; + bool mInsidePendingNullable; public: BfExprEvaluator(BfModule* module); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index b7d8b28e..61160106 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -14327,7 +14327,7 @@ void BfModule::EmitCtorBody(bool& skipBody) } else { - AssertErrorState(); + // Failed } auto assignValue = GetFieldInitializerValue(fieldInst); if ((fieldAddr) && (assignValue)) diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index d032b74a..c6559ea4 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -57,6 +57,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan } BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; typeState.mTypeInstance = genericTypeInst; typeState.mCurTypeDef = partialTypeDef; SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); @@ -101,6 +102,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan bool BfModule::BuildGenericParams(BfType* resolvedTypeRef) { BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; typeState.mBuildingGenericParams = true; SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); @@ -1500,6 +1502,12 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy // into an errored state SetAndRestoreValue prevReportErrors(mReportErrors, reportErrors); + if (typeInstance->mIsFinishingType) + { + // This type already failed + return true; + } + CheckCircularDataError(); bool underlyingTypeDeferred = false; @@ -2095,7 +2103,9 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (partialTypeDef->mTypeDeclaration->mAttributes == NULL) continue; BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; typeState.mCurTypeDef = partialTypeDef; + typeState.mTypeInstance = typeInstance; SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); if (typeInstance->mCustomAttributes == NULL) @@ -2186,61 +2196,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy BfFieldDef* mFieldDef; int mTypeArrayIdx; }; - - for (auto propDef : typeDef->mProperties) - { - if (!typeInstance->IsTypeMemberIncluded(propDef->mDeclaringType)) - continue; - - if (propDef->mFieldDeclaration != NULL) - { - BfTypeState typeState; - typeState.mCurTypeDef = propDef->mDeclaringType; - SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); - - if (propDef->mFieldDeclaration->mAttributes != NULL) - { - auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property); - delete customAttrs; - } - - if (propDef->mFieldDeclaration->mAttributes != NULL) - { - auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property); - delete customAttrs; - } - - auto propDecl = (BfPropertyDeclaration*)propDef->mFieldDeclaration; - if (propDecl->mExplicitInterface != NULL) - { - if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) - mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(propDecl->mExplicitInterface, false); - auto explicitInterface = ResolveTypeRef(propDecl->mExplicitInterface, BfPopulateType_Declaration); - if (explicitInterface != NULL) - { - bool interfaceFound = false; - for (auto ifaceInst : typeInstance->mInterfaces) - interfaceFound |= ifaceInst.mInterfaceType == explicitInterface; - if (!interfaceFound) - { - Fail("Containing class has not declared to implement this interface", propDecl->mExplicitInterface, true); - } - } - } - } - - if (propDef->mMethods.IsEmpty()) - { - auto nameNode = ((BfPropertyDeclaration*)propDef->mFieldDeclaration)->mNameNode; - - if (nameNode != NULL) - { - Fail(StrFormat("Property or indexer '%s.%s' must have at least one accessor", TypeToString(typeInstance).c_str(), propDef->mName.c_str()), - nameNode, true); // CS0548 - } - } - } - + BfSizedVector deferredVarResolves; for (auto field : typeDef->mFields) @@ -2417,7 +2373,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy BF_ASSERT(mContext->mCurTypeState == &typeState); - BF_ASSERT(!typeInstance->mIsFinishingType); + //BF_ASSERT(!typeInstance->mIsFinishingType); typeInstance->mIsFinishingType = true; // No re-entry is allowed below here -- we will run all the way to the end at this point @@ -2427,6 +2383,63 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (!resolvedTypeRef->IsBoxed()) { + for (auto propDef : typeDef->mProperties) + { + if (!typeInstance->IsTypeMemberIncluded(propDef->mDeclaringType)) + continue; + + if (propDef->mFieldDeclaration != NULL) + { + BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; + typeState.mCurTypeDef = propDef->mDeclaringType; + typeState.mCurFieldDef = propDef; + typeState.mTypeInstance = typeInstance; + SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); + + if (propDef->mFieldDeclaration->mAttributes != NULL) + { + auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property); + delete customAttrs; + } + + if (propDef->mFieldDeclaration->mAttributes != NULL) + { + auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property); + delete customAttrs; + } + + auto propDecl = (BfPropertyDeclaration*)propDef->mFieldDeclaration; + if (propDecl->mExplicitInterface != NULL) + { + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) + mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(propDecl->mExplicitInterface, false); + auto explicitInterface = ResolveTypeRef(propDecl->mExplicitInterface, BfPopulateType_Declaration); + if (explicitInterface != NULL) + { + bool interfaceFound = false; + for (auto ifaceInst : typeInstance->mInterfaces) + interfaceFound |= ifaceInst.mInterfaceType == explicitInterface; + if (!interfaceFound) + { + Fail("Containing class has not declared to implement this interface", propDecl->mExplicitInterface, true); + } + } + } + } + + if (propDef->mMethods.IsEmpty()) + { + auto nameNode = ((BfPropertyDeclaration*)propDef->mFieldDeclaration)->mNameNode; + + if (nameNode != NULL) + { + Fail(StrFormat("Property or indexer '%s.%s' must have at least one accessor", TypeToString(typeInstance).c_str(), propDef->mName.c_str()), + nameNode, true); // CS0548 + } + } + } + bool isGlobalContainer = typeDef->IsGlobalsContainer(); if (typeInstance->mBaseType != NULL) @@ -2478,7 +2491,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL)) { BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; + typeState.mCurFieldDef = fieldDef; typeState.mCurTypeDef = fieldDef->mDeclaringType; + typeState.mTypeInstance = typeInstance; SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field); @@ -2959,6 +2975,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy continue; BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; typeState.mCurTypeDef = propDef->mDeclaringType; typeState.mTypeInstance = typeInstance; SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState);