diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 3ea8e3ec..2ba202b3 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -782,6 +782,8 @@ void BfAutoComplete::AddCurrentTypes(BfTypeInstance* typeInst, const StringImpl& void BfAutoComplete::AddField(BfTypeInstance* typeInst, BfFieldDef* fieldDef, BfFieldInstance* fieldInstance, const StringImpl& filter) { + if (fieldDef->mName.IsEmpty()) + return; int wantPrefixCount = 0; const char* filterStr = filter.c_str(); while (filterStr[0] == '@') @@ -1662,6 +1664,8 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress for (auto field : showAttrTypeDef->mFields) { + if (field->mName.IsEmpty()) + continue; if (auto entryAdded = AddEntry(AutoCompleteEntry("field", field->mName + "="), filter)) { auto fieldDeclaration = field->GetFieldDeclaration(); @@ -3663,7 +3667,7 @@ void BfAutoComplete::FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, auto parser = typeInst->mTypeDef->GetDefinition()->mSource->ToParser(); if (parser == NULL) return; - + String fullName = typeInst->mTypeDef->mFullName.ToString(); String fieldStr; diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 698e43ad..156ebb0d 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -1202,6 +1202,10 @@ void BfDefBuilder::Visit(BfFieldDeclaration* fieldDeclaration) else fieldDef->mUsingProtection = fieldDef->mProtection; } + else if (fieldDeclaration->mNameNode == NULL) + { + fieldDef->mUsingProtection = fieldDef->mProtection; + } fieldDef->mIsStatic = (fieldDeclaration->mStaticSpecifier != NULL) || fieldDef->mIsConst; fieldDef->mIsVolatile = (fieldDeclaration->mVolatileSpecifier != NULL); diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 97801e14..00c8e212 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -3220,265 +3220,282 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type) diFieldTypes.push_back(memberType); } - bool isPayloadEnum = (typeInstance->IsEnum()) && (!typeInstance->IsTypedPrimitive()); - for (int fieldIdx = 0; fieldIdx < typeInstance->mFieldInstances.mSize; fieldIdx++) + std::function _AddFields = [&](BfType* type, int depth, int byteOffset) { - auto fieldInstance = &typeInstance->mFieldInstances[fieldIdx]; - if (!fieldInstance->mFieldIncluded) - continue; - auto fieldDef = fieldInstance->GetFieldDef(); + typeInstance = type->ToTypeInstance(); + if (typeInstance == NULL) + return; - if ((fieldInstance->mResolvedType == NULL) || (typeInstance->IsBoxed())) - continue; - - auto resolvedFieldType = fieldInstance->GetResolvedType(); - mModule->PopulateType(resolvedFieldType, BfPopulateType_Declaration); - BfIRType resolvedFieldIRType = MapType(resolvedFieldType); - BfIRMDNode resolvedFieldDIType; - - if ((fieldDef != NULL) && (!fieldDef->mIsStatic) && (resolvedFieldType->IsStruct())) - PopulateType(resolvedFieldType, BfIRPopulateType_Eventually_Full); - resolvedFieldDIType = DbgGetType(resolvedFieldType); - - if (fieldInstance->IsAppendedObject()) - resolvedFieldDIType = DbgGetTypeInst(resolvedFieldType->ToTypeInstance()); - - if ((fieldDef == NULL) && (typeInstance->IsPayloadEnum())) + bool isPayloadEnum = (typeInstance->IsEnum()) && (!typeInstance->IsTypedPrimitive()); + for (int fieldIdx = 0; fieldIdx < typeInstance->mFieldInstances.mSize; fieldIdx++) { - orderedFields.push_back(fieldInstance); + auto fieldInstance = &typeInstance->mFieldInstances[fieldIdx]; + if (!fieldInstance->mFieldIncluded) + continue; + auto fieldDef = fieldInstance->GetFieldDef(); - int lineNum = 0; - int flags = llvm::DINode::FlagPublic; - auto fieldType = fieldInstance->mResolvedType; - String fieldName = "__bftag"; - auto memberType = DbgCreateMemberType(diForwardDecl, fieldName, fileDIScope, lineNum, - resolvedFieldType->mSize * 8, resolvedFieldType->mAlign * 8, fieldInstance->mDataOffset * 8, - flags, resolvedFieldDIType); - diFieldTypes.push_back(memberType); - } + if ((fieldInstance->mResolvedType == NULL) || (typeInstance->IsBoxed())) + continue; - if ((!typeInstance->IsBoxed()) && (fieldDef != NULL)) - { - if (fieldDef->mIsConst) + auto resolvedFieldType = fieldInstance->GetResolvedType(); + mModule->PopulateType(resolvedFieldType, BfPopulateType_Declaration); + BfIRType resolvedFieldIRType = MapType(resolvedFieldType); + BfIRMDNode resolvedFieldDIType; + + if ((fieldDef != NULL) && (!fieldDef->mIsStatic) && (resolvedFieldType->IsStruct())) + PopulateType(resolvedFieldType, BfIRPopulateType_Eventually_Full); + resolvedFieldDIType = DbgGetType(resolvedFieldType); + + if (fieldInstance->IsAppendedObject()) + resolvedFieldDIType = DbgGetTypeInst(resolvedFieldType->ToTypeInstance()); + + if ((fieldDef == NULL) && (typeInstance->IsPayloadEnum())) { - if (isDefiningModule) + orderedFields.push_back(fieldInstance); + + int lineNum = 0; + int flags = llvm::DINode::FlagPublic; + auto fieldType = fieldInstance->mResolvedType; + String fieldName = "__bftag"; + auto memberType = DbgCreateMemberType(diForwardDecl, fieldName, fileDIScope, lineNum, + resolvedFieldType->mSize * 8, resolvedFieldType->mAlign * 8, fieldInstance->mDataOffset * 8, + flags, resolvedFieldDIType); + diFieldTypes.push_back(memberType); + } + + if ((!typeInstance->IsBoxed()) && (fieldDef != NULL)) + { + if (fieldDef->mIsConst) { - if ((isPayloadEnum) && (fieldDef->IsEnumCaseEntry())) + if ((isDefiningModule) && (depth == 0)) { - auto payloadType = fieldInstance->mResolvedType; - if (payloadType == NULL) - payloadType = mModule->CreateTupleType(BfTypeVector(), Array()); - - String fieldName = StrFormat("_%d_%s", -fieldInstance->mDataIdx - 1, fieldDef->mName.c_str()); - - int flags = 0; - auto memberType = DbgCreateMemberType(diForwardDecl, fieldName, fileDIScope, 0, - BF_ALIGN(payloadType->mSize, payloadType->mAlign) * 8, payloadType->mAlign * 8, 0, - flags, DbgGetType(payloadType)); - diFieldTypes.push_back(memberType); - } - else - { - BfConstant* constant = NULL; - BfIRValue staticValue; - - if (fieldInstance->mConstIdx != -1) + if ((isPayloadEnum) && (fieldDef->IsEnumCaseEntry())) { - constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); - if (!resolvedFieldType->IsValuelessType()) - staticValue = mModule->ConstantToCurrent(constant, typeInstance->mConstHolder, resolvedFieldType); - } + auto payloadType = fieldInstance->mResolvedType; + if (payloadType == NULL) + payloadType = mModule->CreateTupleType(BfTypeVector(), Array()); - if (fieldInstance->mResolvedType->IsComposite()) - PopulateType(fieldInstance->mResolvedType); - - BfIRMDNode constDIType = DbgCreateConstType(resolvedFieldDIType); - if ((fieldDef->mIsExtern) && (resolvedFieldType->IsPointer())) - { - auto underlyingType = resolvedFieldType->GetUnderlyingType(); - auto staticTypedValue = mModule->ReferenceStaticField(fieldInstance); - staticValue = staticTypedValue.mValue; + String fieldName = StrFormat("_%d_%s", -fieldInstance->mDataIdx - 1, fieldDef->mName.c_str()); int flags = 0; - auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldDef->mName, fileDIScope, 0, - constDIType, flags, CreateConst(BfTypeCode_Int32, 0)); - diFieldTypes.push_back(memberType); - - StringT<128> staticVarName; - BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); - if (!staticVarName.StartsWith("#")) - { - String fieldName = DbgGetStaticFieldName(fieldInstance); - DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, - constDIType, false, staticValue, memberType); - } - } - else if (resolvedFieldType->IsValuelessType()) - { - // Do nothing - } - else if ((resolvedFieldType->IsObjectOrInterface()) || (resolvedFieldType->IsPointer()) || (resolvedFieldType->IsSizedArray())) - { - bool useIntConstant = false; - - bool wasMadeAddr = false; - - StringT<128> staticVarName; - BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); - - String fieldName = fieldDef->mName; - BfIRValue intConstant; - if (constant != NULL) - { - // This constant debug info causes linking errors on Linux - if (isOptimized) - continue; - - if ((constant->mConstType == BfConstType_Agg) || - (constant->mConstType == BfConstType_AggZero) || - (constant->mTypeCode == BfTypeCode_NullPtr)) - { - staticValue = ConstToMemory(staticValue); - wasMadeAddr = true; - } - else if (constant->mTypeCode == BfTypeCode_StringId) - { - int stringId = constant->mInt32; - const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString; - if (resolvedFieldType->IsPointer()) - staticValue = mModule->GetStringCharPtr(str); - else - staticValue = mModule->GetStringObjectValue(str); - } - else - { - // Ignore other types (for now) - continue; - } - } - - if (!useIntConstant) - { - auto useType = resolvedFieldType; - if (wasMadeAddr) - useType = mModule->CreatePointerType(useType); - staticValue = CreateGlobalVariable(mModule->mBfIRBuilder->MapType(useType), true, BfIRLinkageType_Internal, staticValue, staticVarName); - GlobalVar_SetAlignment(staticValue, useType->mAlign); - } - - int flags = 0; - auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldName, fileDIScope, 0, - constDIType, flags, useIntConstant ? intConstant : BfIRValue()); - diFieldTypes.push_back(memberType); - - if (fieldDef->mUsingProtection != BfProtection_Hidden) - { - auto memberType = DbgCreateStaticMemberType(diForwardDecl, "$using$" + fieldName, fileDIScope, 0, - constDIType, flags, useIntConstant ? intConstant : BfIRValue()); - diFieldTypes.push_back(memberType); - } - - if (staticValue) - { - String qualifiedName = DbgGetStaticFieldName(fieldInstance); - DbgCreateGlobalVariable(diForwardDecl, qualifiedName, staticVarName, fileDIScope, 0, - constDIType, false, staticValue, memberType); - } - } - else if (mModule->mCompiler->mOptions.IsCodeView()) - { - int flags = 0; - String fieldName = fieldDef->mName; - if ((constant != NULL) && - ((IsIntable(constant->mTypeCode)) || (IsFloat(constant->mTypeCode)))) - { - int64 writeVal = constant->mInt64; - if (constant->mTypeCode == BfTypeCode_Float) - { - // We need to do this because Singles are stored in mDouble, so we need to reduce here - float floatVal = (float)constant->mDouble; - writeVal = *(uint32*)&floatVal; - } - if (writeVal < 0) - fieldName += StrFormat("$_%llu", -writeVal); - else - fieldName += StrFormat("$%llu", writeVal); - } - auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldName, fileDIScope, 0, - constDIType, flags, staticValue); + auto memberType = DbgCreateMemberType(diForwardDecl, fieldName, fileDIScope, 0, + BF_ALIGN(payloadType->mSize, payloadType->mAlign) * 8, payloadType->mAlign * 8, 0, + flags, DbgGetType(payloadType)); diFieldTypes.push_back(memberType); } else { - int flags = 0; - String fieldName = DbgGetStaticFieldName(fieldInstance); - auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldName, fileDIScope, 0, - constDIType, flags, staticValue); + BfConstant* constant = NULL; + BfIRValue staticValue; + + if (fieldInstance->mConstIdx != -1) + { + constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); + if (!resolvedFieldType->IsValuelessType()) + staticValue = mModule->ConstantToCurrent(constant, typeInstance->mConstHolder, resolvedFieldType); + } + + if (fieldInstance->mResolvedType->IsComposite()) + PopulateType(fieldInstance->mResolvedType); + + BfIRMDNode constDIType = DbgCreateConstType(resolvedFieldDIType); + if ((fieldDef->mIsExtern) && (resolvedFieldType->IsPointer())) + { + auto underlyingType = resolvedFieldType->GetUnderlyingType(); + auto staticTypedValue = mModule->ReferenceStaticField(fieldInstance); + staticValue = staticTypedValue.mValue; + + int flags = 0; + auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldDef->mName, fileDIScope, 0, + constDIType, flags, CreateConst(BfTypeCode_Int32, 0)); + diFieldTypes.push_back(memberType); + + StringT<128> staticVarName; + BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); + if (!staticVarName.StartsWith("#")) + { + String fieldName = DbgGetStaticFieldName(fieldInstance); + DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, + constDIType, false, staticValue, memberType); + } + } + else if (resolvedFieldType->IsValuelessType()) + { + // Do nothing + } + else if ((resolvedFieldType->IsObjectOrInterface()) || (resolvedFieldType->IsPointer()) || (resolvedFieldType->IsSizedArray())) + { + bool useIntConstant = false; + + bool wasMadeAddr = false; + + StringT<128> staticVarName; + BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); + + String fieldName = fieldDef->mName; + BfIRValue intConstant; + if (constant != NULL) + { + // This constant debug info causes linking errors on Linux + if (isOptimized) + continue; + + if ((constant->mConstType == BfConstType_Agg) || + (constant->mConstType == BfConstType_AggZero) || + (constant->mTypeCode == BfTypeCode_NullPtr)) + { + staticValue = ConstToMemory(staticValue); + wasMadeAddr = true; + } + else if (constant->mTypeCode == BfTypeCode_StringId) + { + int stringId = constant->mInt32; + const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString; + if (resolvedFieldType->IsPointer()) + staticValue = mModule->GetStringCharPtr(str); + else + staticValue = mModule->GetStringObjectValue(str); + } + else + { + // Ignore other types (for now) + continue; + } + } + + if (!useIntConstant) + { + auto useType = resolvedFieldType; + if (wasMadeAddr) + useType = mModule->CreatePointerType(useType); + staticValue = CreateGlobalVariable(mModule->mBfIRBuilder->MapType(useType), true, BfIRLinkageType_Internal, staticValue, staticVarName); + GlobalVar_SetAlignment(staticValue, useType->mAlign); + } + + BfIRMDNode memberType; + int flags = 0; + if (!fieldDef->mName.IsEmpty()) + { + memberType = DbgCreateStaticMemberType(diForwardDecl, fieldName, fileDIScope, 0, + constDIType, flags, useIntConstant ? intConstant : BfIRValue()); + diFieldTypes.push_back(memberType); + } + + if (fieldDef->mUsingProtection != BfProtection_Hidden) + { + auto memberType = DbgCreateStaticMemberType(diForwardDecl, "$using$" + fieldName, fileDIScope, 0, + constDIType, flags, useIntConstant ? intConstant : BfIRValue()); + diFieldTypes.push_back(memberType); + } + + if ((staticValue) && (!fieldDef->mName.IsEmpty())) + { + String qualifiedName = DbgGetStaticFieldName(fieldInstance); + DbgCreateGlobalVariable(diForwardDecl, qualifiedName, staticVarName, fileDIScope, 0, + constDIType, false, staticValue, memberType); + } + } + else if (mModule->mCompiler->mOptions.IsCodeView()) + { + int flags = 0; + String fieldName = fieldDef->mName; + if ((constant != NULL) && + ((IsIntable(constant->mTypeCode)) || (IsFloat(constant->mTypeCode)))) + { + int64 writeVal = constant->mInt64; + if (constant->mTypeCode == BfTypeCode_Float) + { + // We need to do this because Singles are stored in mDouble, so we need to reduce here + float floatVal = (float)constant->mDouble; + writeVal = *(uint32*)&floatVal; + } + if (writeVal < 0) + fieldName += StrFormat("$_%llu", -writeVal); + else + fieldName += StrFormat("$%llu", writeVal); + } + auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldName, fileDIScope, 0, + constDIType, flags, staticValue); + diFieldTypes.push_back(memberType); + } + else + { + int flags = 0; + String fieldName = DbgGetStaticFieldName(fieldInstance); + auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldName, fileDIScope, 0, + constDIType, flags, staticValue); + diFieldTypes.push_back(memberType); + } + } + } + } + else if (fieldDef->mIsStatic) + { + if ((isDefiningModule) && (depth == 0)) + { + BfIRMDNode memberType; + int flags = 0; + if (!fieldDef->mName.IsEmpty()) + { + memberType = DbgCreateStaticMemberType(diForwardDecl, fieldDef->mName, fileDIScope, 0, + resolvedFieldDIType, flags, BfIRValue()); + diFieldTypes.push_back(memberType); + } + + if (fieldDef->mUsingProtection != BfProtection_Hidden) + { + auto memberType = DbgCreateStaticMemberType(diForwardDecl, "$using$" + fieldDef->mName, fileDIScope, 0, + resolvedFieldDIType, flags, BfIRValue()); + diFieldTypes.push_back(memberType); + } + + StringT<128> staticVarName; + BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); + if ((!staticVarName.StartsWith('#')) && (!fieldDef->mName.IsEmpty())) + { + auto staticValue = mModule->ReferenceStaticField(fieldInstance); + if (staticValue.mValue) + { + String fieldName = DbgGetStaticFieldName(fieldInstance); + DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, + resolvedFieldDIType, false, staticValue.mValue, memberType); + } + } + } + } + else + { + bool useForUnion = false; + + BF_ASSERT(!fieldInstance->mIsEnumPayloadCase); + + if (wantDIData) + { + if ((fieldDef->mUsingProtection != BfProtection_Hidden) && (depth < 10)) + { + _AddFields(fieldInstance->mResolvedType, depth + 1, byteOffset + fieldInstance->mDataOffset); + } + + int lineNum = 0; + + int flags = 0; + String fieldName = fieldDef->mName; + if (!fieldDef->mName.IsEmpty()) + { + if (fieldDef->mHasMultiDefs) + fieldName += "$" + fieldDef->mDeclaringType->mProject->mName; + auto memberType = DbgCreateMemberType(diForwardDecl, fieldName, fileDIScope, lineNum, + fieldInstance->mDataSize * 8, resolvedFieldType->mAlign * 8, (byteOffset + fieldInstance->mDataOffset) * 8, + flags, resolvedFieldDIType); diFieldTypes.push_back(memberType); } } } } - else if (fieldDef->mIsStatic) - { - if (isDefiningModule) - { - int flags = 0; - auto memberType = DbgCreateStaticMemberType(diForwardDecl, fieldDef->mName, fileDIScope, 0, - resolvedFieldDIType, flags, BfIRValue()); - diFieldTypes.push_back(memberType); - - if (fieldDef->mUsingProtection != BfProtection_Hidden) - { - auto memberType = DbgCreateStaticMemberType(diForwardDecl, "$using$" + fieldDef->mName, fileDIScope, 0, - resolvedFieldDIType, flags, BfIRValue()); - diFieldTypes.push_back(memberType); - } - - StringT<128> staticVarName; - BfMangler::Mangle(staticVarName, mModule->mCompiler->GetMangleKind(), fieldInstance); - if (!staticVarName.StartsWith('#')) - { - auto staticValue = mModule->ReferenceStaticField(fieldInstance); - if (staticValue.mValue) - { - String fieldName = DbgGetStaticFieldName(fieldInstance); - DbgCreateGlobalVariable(diForwardDecl, fieldName, staticVarName, fileDIScope, 0, - resolvedFieldDIType, false, staticValue.mValue, memberType); - } - } - } - } - else - { - bool useForUnion = false; - - BF_ASSERT(!fieldInstance->mIsEnumPayloadCase); - - if (wantDIData) - { - int lineNum = 0; - - int flags = 0; - String fieldName = fieldDef->mName; - if (fieldDef->mHasMultiDefs) - fieldName += "$" + fieldDef->mDeclaringType->mProject->mName; - auto memberType = DbgCreateMemberType(diForwardDecl, fieldName, fileDIScope, lineNum, - fieldInstance->mDataSize * 8, resolvedFieldType->mAlign * 8, fieldInstance->mDataOffset * 8, - flags, resolvedFieldDIType); - diFieldTypes.push_back(memberType); - - if (fieldDef->mUsingProtection != BfProtection_Hidden) - { - auto memberType = DbgCreateMemberType(diForwardDecl, "$using$" + fieldName, fileDIScope, lineNum, - fieldInstance->mDataSize * 8, resolvedFieldType->mAlign * 8, fieldInstance->mDataOffset * 8, - flags, resolvedFieldDIType); - diFieldTypes.push_back(memberType); - } - } - } } - } + }; + + _AddFields(typeInstance, 0, 0); int dataPos = 0; if (typeInstance->mBaseType != NULL) diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 5df85405..00f356f9 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -5472,9 +5472,22 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy { auto resolvedFieldType = fieldInstance->GetResolvedType(); if ((!typeInstance->IsBoxed()) && (fieldDef != NULL)) - { - if ((fieldDef->mUsingProtection != BfProtection_Hidden) && (!resolvedFieldType->IsGenericParam()) && (!resolvedFieldType->IsObject()) && (!resolvedFieldType->IsStruct())) - Warn(0, StrFormat("Field type '%s' is not applicable for 'using'", TypeToString(resolvedFieldType).c_str()), fieldDef->GetFieldDeclaration()->mConstSpecifier); + { + if (fieldDef->mUsingProtection != BfProtection_Hidden) + { + auto fieldDecl = fieldDef->GetFieldDeclaration(); + BfAstNode* refNode = fieldDecl->mConstSpecifier; + if (refNode == NULL) + refNode = fieldDef->GetRefNode(); + if ((!resolvedFieldType->IsGenericParam()) && (!resolvedFieldType->IsObject()) && (!resolvedFieldType->IsStruct())) + { + Warn(0, StrFormat("Field type '%s' is not applicable for 'using'", TypeToString(resolvedFieldType).c_str()), refNode); + } + else if ((fieldDecl->mConstSpecifier == NULL) && (!BfNodeIsA(fieldDecl->mTypeRef))) + { + Warn(0, "Field needs either a name or a 'using' declaration", refNode); + } + } if (fieldInstance->mIsEnumPayloadCase) { diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 15df5385..fd3ea754 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -6309,11 +6309,13 @@ BfFieldDeclaration* BfReducer::CreateFieldDeclaration(BfTokenNode* tokenNode, Bf else { ReplaceNode(typeRef, fieldDeclaration); - fieldDeclaration->mTypeRef = typeRef; - fieldDeclaration->mNameNode = nameIdentifier; + fieldDeclaration->mTypeRef = typeRef; fieldDeclaration->mInitializer = NULL; - MoveNode(fieldDeclaration->mNameNode, fieldDeclaration); - //mVisitorPos.MoveNext(); + if (nameIdentifier != NULL) + { + fieldDeclaration->mNameNode = nameIdentifier; + MoveNode(fieldDeclaration->mNameNode, fieldDeclaration); + } } CheckMultiuseAttributeTypeRef(fieldDeclaration->mTypeRef); @@ -7407,7 +7409,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept } else if (auto nextToken = BfNodeDynCast(nextNode)) { - if (nextToken->GetToken() == BfToken_Operator) + if (nextToken->mToken == BfToken_Operator) { auto operatorDecl = mAlloc->Alloc(); BfDeferredAstSizedArray params(operatorDecl->mParams, mAlloc); @@ -7493,7 +7495,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept return operatorDecl; } - else if (nextToken->GetToken() == BfToken_LParen) + else if (nextToken->mToken == BfToken_LParen) { Fail("Method return type expected", node); @@ -7505,6 +7507,10 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept typeRef = NULL; } } + else if (nextToken->mToken == BfToken_Semicolon) + { + forceIsMethod = true; + } } if ((nameIdentifier != NULL) || (forceIsMethod) || (indexerThisToken != NULL)) diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index f81bdcef..2136386b 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -679,6 +679,8 @@ public: { if (fieldDeclaration->mNameNode != NULL) return fieldDeclaration->mNameNode; + if (fieldDeclaration->mTypeRef != NULL) + return fieldDeclaration->mTypeRef; } if (auto paramDeclaration = BfNodeDynCast(mFieldDeclaration)) diff --git a/IDEHelper/Tests/src/Anonymous.bf b/IDEHelper/Tests/src/Anonymous.bf index 588c1008..0caeff07 100644 --- a/IDEHelper/Tests/src/Anonymous.bf +++ b/IDEHelper/Tests/src/Anonymous.bf @@ -23,11 +23,11 @@ class Anonymous struct StructB { [Union] - public using struct + public struct { public int mX; public int mY; - } mCoords; + }; } struct StructC @@ -91,4 +91,4 @@ class Anonymous Test.Assert(sValA.x == 3); Test.Assert(sValA.y == 4); } -} \ No newline at end of file +} diff --git a/IDEHelper/Tests/src/UsingField.bf b/IDEHelper/Tests/src/UsingField.bf index 6fef581b..29ff70ec 100644 --- a/IDEHelper/Tests/src/UsingField.bf +++ b/IDEHelper/Tests/src/UsingField.bf @@ -48,14 +48,25 @@ namespace Tests [Union] struct Vector2 { - public struct Coords - { - public float mX; - public float mY; - } + public struct Coords : this(float mX, float mY); public float[2] mValues; - public using Coords mCoords; + using public Coords mCoords; + + public this(float x, float y) + { + mX = x; + mY = y; + } + } + + [Union] + struct Vector2b + { + public struct Coords : this(float mX, float mY); + + public float[2] mValues; + public using Coords; public this(float x, float y) { @@ -80,8 +91,16 @@ namespace Tests Test.Assert(sizeof(Vector2) == 8); Test.Assert(vec.mX == 1.2f); Test.Assert(vec.mY == 2.3f); + Test.Assert(vec.mCoords == .(1.2f, 2.3f)); Test.Assert(vec.mValues[0] == 1.2f); Test.Assert(vec.mValues[1] == 2.3f); + + Vector2b vecb = .(1.2f, 2.3f); + Test.Assert(sizeof(Vector2b) == 8); + Test.Assert(vecb.mX == 1.2f); + Test.Assert(vecb.mY == 2.3f); + Test.Assert(vecb.mValues[0] == 1.2f); + Test.Assert(vecb.mValues[1] == 2.3f); } } } \ No newline at end of file diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index 327d0849..d2419b55 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -5991,6 +5991,8 @@ String WinDebugger::MaybeQuoteFormatInfoParam(const StringImpl& str) DbgTypedValue WinDebugger::EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo, String* outReferenceId, String* outErrors) { DbgEvaluationContext dbgEvaluationContext(this, dbgCompileUnit->mDbgModule, subExpr, formatInfo, contextTypedValue); + if (dbgEvaluationContext.mDbgExprEvaluator == NULL) + return DbgTypedValue(); dbgEvaluationContext.mDbgExprEvaluator->mDbgCompileUnit = dbgCompileUnit; if (formatInfo != NULL) {