mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Added [IgnoreErrors] block attribute
This commit is contained in:
parent
65d960a6e6
commit
99419097c5
16 changed files with 307 additions and 79 deletions
|
@ -28,11 +28,12 @@ namespace System
|
|||
Alloc = 0x40000,
|
||||
Delete = 0x80000,
|
||||
Alias = 0x100000,
|
||||
Block = 0x200000,
|
||||
|
||||
All = Assembly | Module | Class | Struct | Enum | Constructor |
|
||||
Method | Property | Field | StaticField | Interface | Parameter |
|
||||
Delegate | Function | ReturnValue | GenericParameter | Invocation | MemberAccess |
|
||||
Alloc | Delete | Alias,
|
||||
Alloc | Delete | Alias | Block,
|
||||
}
|
||||
|
||||
public enum ReflectKind
|
||||
|
@ -137,6 +138,14 @@ namespace System
|
|||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Block)]
|
||||
public struct IgnoreErrorsAttribute : Attribute
|
||||
{
|
||||
public this(bool stopOnErrors = false)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method | .Class | .Struct | .Enum)]
|
||||
public struct OptimizeAttribute : Attribute
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace System
|
|||
}
|
||||
|
||||
public enum AttributeTargets
|
||||
{
|
||||
{
|
||||
Assembly = 0x0001,
|
||||
Module = 0x0002,
|
||||
Class = 0x0004,
|
||||
|
@ -28,11 +28,12 @@ namespace System
|
|||
Alloc = 0x40000,
|
||||
Delete = 0x80000,
|
||||
Alias = 0x100000,
|
||||
Block = 0x200000,
|
||||
|
||||
All = Assembly | Module | Class | Struct | Enum | Constructor |
|
||||
Method | Property | Field | StaticField | Interface | Parameter |
|
||||
Delegate | Function | ReturnValue | GenericParameter | Invocation | MemberAccess |
|
||||
Alloc | Delete | Alias,
|
||||
Alloc | Delete | Alias | Block,
|
||||
}
|
||||
|
||||
public enum ReflectKind
|
||||
|
@ -120,33 +121,43 @@ namespace System
|
|||
[AttributeUsage(.Class | .Struct | .Interface | .Method | .Constructor)]
|
||||
public struct AlwaysIncludeAttribute : Attribute
|
||||
{
|
||||
bool mAssumeInstantiated;
|
||||
|
||||
public bool AssumeInstantiated
|
||||
{
|
||||
get { return mAssumeInstantiated; }
|
||||
set mut { mAssumeInstantiated = value; }
|
||||
set { }
|
||||
}
|
||||
|
||||
public bool IncludeAllMethods
|
||||
{
|
||||
set { }
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(.MemberAccess | .Alloc | .Delete)]
|
||||
[AttributeUsage(.MemberAccess | .Alloc)]
|
||||
public struct FriendAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Block)]
|
||||
public struct IgnoreErrorsAttribute : Attribute
|
||||
{
|
||||
public this(bool stopOnErrors = false)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method | .Class | .Struct | .Enum)]
|
||||
public struct OptimizeAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method | .Class | .Struct | .Enum)]
|
||||
public struct UseLLVMAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method | .Class | .Struct | .Enum)]
|
||||
public struct OptimizeAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method /*2*/ | .StaticField)]
|
||||
public struct CLinkAttribute : Attribute
|
||||
{
|
||||
|
@ -165,7 +176,6 @@ namespace System
|
|||
|
||||
public this(String linkName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(MangleKind mangleKind)
|
||||
|
@ -190,7 +200,7 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("Use [CallingConvention(.Stdcall)]", false)]
|
||||
[AttributeUsage(.Method | .Delegate | .Function)]
|
||||
public struct StdCallAttribute : Attribute
|
||||
{
|
||||
|
@ -222,21 +232,6 @@ namespace System
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
public this(String intrinName, Type t0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(String intrinName, Type t0, Type t1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(String intrinName, Type t0, Type t1, Type t2)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(.Class | .Struct /*2*/)]
|
||||
|
@ -268,6 +263,7 @@ namespace System
|
|||
|
||||
}
|
||||
|
||||
/// This attribute is required on constructors that include 'append' allocations.
|
||||
[AttributeUsage(.Constructor)]
|
||||
public struct AllowAppendAttribute : Attribute
|
||||
{
|
||||
|
@ -348,7 +344,7 @@ namespace System
|
|||
|
||||
public struct ExportAttribute : Attribute
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(.StaticField | .Field, .NotInherited)]
|
||||
|
@ -359,28 +355,36 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
/// The [Checked] attribute is used to mark a method or a method invocation as being "checked", meaning
|
||||
/// that the method applies extra runtime checks such as bounds checking or other parameter or state validation.
|
||||
[AttributeUsage(.Invocation | .Method | .Property)]
|
||||
public struct CheckedAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// The [Unchecked] attribute is used to mark a method or a method invocation as being "unchecked", meaning
|
||||
/// that the method omits runtime checks such as bounds checking or other parameter or state validation.
|
||||
[AttributeUsage(.Invocation | .Method | .Property)]
|
||||
public struct UncheckedAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
/// Generally used as a per-method optimization, [DisableChecks] will cause calls within this method to
|
||||
/// call the unchecked version of methods. By default, only debug builds perform checked calls.
|
||||
[AttributeUsage(.Method | .Constructor)]
|
||||
public struct DisableChecksAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
/// Generally used as a per-method optimization, [DisableObjectAccessChecks] will avoid the runtime per-object-access
|
||||
/// checks which by default are only applied in debug builds anyway.
|
||||
[AttributeUsage(.Method | .MemberAccess)]
|
||||
public struct DisableObjectAccessChecksAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method | .Constructor | .Class | .Struct | .Alias)]
|
||||
[AttributeUsage(.Method | .Constructor | .Class | .Struct | .Alias | .Interface)]
|
||||
public struct ObsoleteAttribute : Attribute
|
||||
{
|
||||
public this(bool isError)
|
||||
|
@ -418,17 +422,17 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
/// If [NoDiscard] is used on a method, the the compiler will show a warning if the result is discarded.
|
||||
/// If used on a type, the compiler will show an warning if any method returns that type and the caller discards the result.
|
||||
[AttributeUsage(.Method | .Class | .Struct)]
|
||||
public struct NoDiscardAttribute : Attribute
|
||||
{
|
||||
public this()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public this(String message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,11 @@ void BfStructuralVisitor::Visit(BfStatement* stmt)
|
|||
Visit(stmt->ToBase());
|
||||
}
|
||||
|
||||
void BfStructuralVisitor::Visit(BfAttributedStatement* attribStmt)
|
||||
{
|
||||
Visit(attribStmt->ToBase());
|
||||
}
|
||||
|
||||
void BfStructuralVisitor::Visit(BfLabelableStatement* labelableStmt)
|
||||
{
|
||||
Visit(labelableStmt->ToBase());
|
||||
|
@ -753,8 +758,11 @@ bool BfAstNode::IsMissingSemicolon()
|
|||
else
|
||||
return false;
|
||||
}
|
||||
if (auto attribExpr = BfNodeDynCastExact<BfAttributedStatement>(this))
|
||||
return (attribExpr->mStatement == NULL) || (attribExpr->mStatement->IsMissingSemicolon());
|
||||
|
||||
if (auto stmt = BfNodeDynCast<BfStatement>(this))
|
||||
return stmt->mTrailingSemicolon == NULL;
|
||||
return stmt->mTrailingSemicolon == NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -769,6 +777,7 @@ bool BfAstNode::IsExpression()
|
|||
return false;
|
||||
return block->mChildArr.GetLast()->IsExpression();
|
||||
}
|
||||
|
||||
return IsA<BfExpression>();
|
||||
}
|
||||
|
||||
|
|
|
@ -255,6 +255,7 @@ class BfLabelableStatement;
|
|||
class BfExpression;
|
||||
class BfExpressionStatement;
|
||||
class BfAttributedExpression;
|
||||
class BfAttributedStatement;
|
||||
class BfLiteralExpression;
|
||||
class BfBlock;
|
||||
class BfBlockExtension;
|
||||
|
@ -410,8 +411,9 @@ public:
|
|||
virtual void Visit(BfLabeledBlock* labeledBlock);
|
||||
virtual void Visit(BfExpression* expr);
|
||||
virtual void Visit(BfExpressionStatement* exprStmt);
|
||||
virtual void Visit(BfAttributedExpression* attribExpr);
|
||||
virtual void Visit(BfAttributedExpression* attribExpr);
|
||||
virtual void Visit(BfStatement* stmt);
|
||||
virtual void Visit(BfAttributedStatement* attribStmt);
|
||||
virtual void Visit(BfLabelableStatement* labelableStmt);
|
||||
virtual void Visit(BfTypedValueExpression* typedValueExpr);
|
||||
|
||||
|
@ -2612,6 +2614,15 @@ public:
|
|||
BfExpression* mExpression;
|
||||
}; BF_AST_DECL(BfAttributedExpression, BfExpression);
|
||||
|
||||
class BfAttributedStatement : public BfStatement
|
||||
{
|
||||
public:
|
||||
BF_AST_TYPE(BfAttributedStatement, BfStatement);
|
||||
|
||||
BfAttributeDirective* mAttributes;
|
||||
BfAstNode* mStatement;
|
||||
}; BF_AST_DECL(BfAttributedStatement, BfStatement);
|
||||
|
||||
class BfObjectCreateExpression : public BfMethodBoundExpression
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1499,7 +1499,11 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken
|
|||
BfAttributeState attributeState;
|
||||
attributeState.mTarget = (BfAttributeTargets)(BfAttributeTargets_MemberAccess);
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
isFriend = (attributeState.mCustomAttributes != NULL) && (attributeState.mCustomAttributes->Contains(mModule->mCompiler->mFriendAttributeTypeDef));
|
||||
if ((attributeState.mCustomAttributes != NULL) && (attributeState.mCustomAttributes->Contains(mModule->mCompiler->mFriendAttributeTypeDef)))
|
||||
{
|
||||
isFriend = true;
|
||||
attributeState.mUsed = true;
|
||||
}
|
||||
|
||||
mInsertStartIdx = attrIdentifier->mAttributes->GetSrcEnd();
|
||||
}
|
||||
|
|
|
@ -435,6 +435,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mObsoleteAttributeTypeDef = NULL;
|
||||
mErrorAttributeTypeDef = NULL;
|
||||
mWarnAttributeTypeDef = NULL;
|
||||
mIgnoreErrorsAttributeTypeDef = NULL;
|
||||
|
||||
mLastAutocompleteModule = NULL;
|
||||
}
|
||||
|
@ -6309,6 +6310,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute");
|
||||
mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
|
||||
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
|
||||
mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute");
|
||||
|
||||
for (int i = 0; i < BfTypeCode_Length; i++)
|
||||
mContext->mPrimitiveStructTypes[i] = NULL;
|
||||
|
|
|
@ -401,6 +401,7 @@ public:
|
|||
BfTypeDef* mObsoleteAttributeTypeDef;
|
||||
BfTypeDef* mErrorAttributeTypeDef;
|
||||
BfTypeDef* mWarnAttributeTypeDef;
|
||||
BfTypeDef* mIgnoreErrorsAttributeTypeDef;
|
||||
|
||||
|
||||
int mCurTypeId;
|
||||
|
|
|
@ -114,6 +114,14 @@ void BfElementVisitor::Visit(BfStatement* stmt)
|
|||
VisitChild(stmt->mTrailingSemicolon);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfAttributedStatement* attribStmt)
|
||||
{
|
||||
Visit(attribStmt->ToBase());
|
||||
|
||||
VisitChild(attribStmt->mAttributes);
|
||||
VisitChild(attribStmt->mStatement);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfLabelableStatement* labelableStmt)
|
||||
{
|
||||
Visit(labelableStmt->ToBase());
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
virtual void Visit(BfExpressionStatement* exprStmt);
|
||||
virtual void Visit(BfAttributedExpression* attribExpr);
|
||||
virtual void Visit(BfStatement* stmt);
|
||||
virtual void Visit(BfAttributedStatement* attribStmt);
|
||||
virtual void Visit(BfLabelableStatement* labelableStmt);
|
||||
virtual void Visit(BfTypedValueExpression* typedValueExpr);
|
||||
|
||||
|
|
|
@ -213,16 +213,16 @@ bool BfMethodMatcher::IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* de
|
|||
if (mActiveTypeDef == NULL)
|
||||
mActiveTypeDef = mModule->GetActiveTypeDef();
|
||||
|
||||
// This needs to be outside the `IsInSpecializedSection`. Note that mActiveTypeDef does not pose a constraint here
|
||||
// Note that mActiveTypeDef does not pose a constraint here
|
||||
if (!typeInst->IsTypeMemberIncluded(declaringType, mActiveTypeDef, mModule))
|
||||
return false;
|
||||
|
||||
// This may not be completely correct - BUT if we don't have this then even Dictionary TKey's operator == won't be considered accessible
|
||||
if ((!mModule->IsInSpecializedSection()) && (mActiveTypeDef->mTypeDeclaration != NULL))
|
||||
{
|
||||
if (!typeInst->IsTypeMemberAccessible(declaringType, mActiveTypeDef))
|
||||
return false;
|
||||
auto visibleProjectSet = mModule->GetVisibleProjectSet();
|
||||
if ((visibleProjectSet != NULL) && (!typeInst->IsTypeMemberAccessible(declaringType, visibleProjectSet)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2582,15 +2582,34 @@ void BfExprEvaluator::Visit(BfTypeReference* typeRef)
|
|||
void BfExprEvaluator::Visit(BfAttributedExpression* attribExpr)
|
||||
{
|
||||
BfAttributeState attributeState;
|
||||
attributeState.mTarget = (BfAttributeTargets)(BfAttributeTargets_Invocation | BfAttributeTargets_MemberAccess);
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attribExpr->mAttributes, attributeState.mTarget);
|
||||
|
||||
attributeState.mTarget = (BfAttributeTargets)(BfAttributeTargets_Invocation | BfAttributeTargets_MemberAccess);
|
||||
if (auto block = BfNodeDynCast<BfBlock>(attribExpr->mExpression))
|
||||
attributeState.mTarget = BfAttributeTargets_Block;
|
||||
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attribExpr->mAttributes, attributeState.mTarget);
|
||||
SetAndRestoreValue<BfAttributeState*> prevAttributeState(mModule->mAttributeState, &attributeState);
|
||||
VisitChild(attribExpr->mExpression);
|
||||
|
||||
if (auto ignoreErrorsAttrib = attributeState.mCustomAttributes->Get(mModule->mCompiler->mIgnoreErrorsAttributeTypeDef))
|
||||
{
|
||||
SetAndRestoreValue<bool> ignoreErrors(mModule->mIgnoreErrors, true);
|
||||
if (!ignoreErrorsAttrib->mCtorArgs.IsEmpty())
|
||||
{
|
||||
auto constant = mModule->mCurTypeInstance->mConstHolder->GetConstant(ignoreErrorsAttrib->mCtorArgs[0]);
|
||||
if (constant->mBool)
|
||||
attributeState.mFlags = BfAttributeState::Flag_StopOnError;
|
||||
}
|
||||
VisitChild(attribExpr->mExpression);
|
||||
attributeState.mUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VisitChild(attribExpr->mExpression);
|
||||
}
|
||||
|
||||
if (!attributeState.mUsed)
|
||||
{
|
||||
mModule->Fail("Unused attributes", attribExpr->mAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BfExprEvaluator::Visit(BfBlock* blockExpr)
|
||||
|
@ -4106,9 +4125,15 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL))
|
||||
{
|
||||
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mFriendAttributeTypeDef))
|
||||
{
|
||||
mPropGetMethodFlags = (BfGetMethodInstanceFlags)(mPropGetMethodFlags | BfGetMethodInstanceFlag_Friend);
|
||||
mModule->mAttributeState->mUsed = true;
|
||||
}
|
||||
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mDisableObjectAccessChecksAttributeTypeDef))
|
||||
{
|
||||
mPropGetMethodFlags = (BfGetMethodInstanceFlags)(mPropGetMethodFlags | BfGetMethodInstanceFlag_DisableObjectAccessChecks);
|
||||
mModule->mAttributeState->mUsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPropDef->mIsStatic)
|
||||
|
@ -12740,8 +12765,8 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (attrib.mType->mTypeDef == mModule->mCompiler->mFriendAttributeTypeDef)
|
||||
allocTarget.mIsFriend = true;
|
||||
else if (attrib.mType->mTypeDef == mModule->mCompiler->mFriendAttributeTypeDef)
|
||||
allocTarget.mIsFriend = true;
|
||||
}
|
||||
|
||||
if (outCustomAttributes != NULL)
|
||||
|
@ -14059,7 +14084,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
|
||||
bool allowImplicitThis = false;
|
||||
BfAstNode* methodNodeSrc = target;
|
||||
|
||||
|
||||
BfAttributeState attributeState;
|
||||
attributeState.mTarget = (BfAttributeTargets)(BfAttributeTargets_Invocation | BfAttributeTargets_MemberAccess);
|
||||
|
||||
|
@ -14194,7 +14219,8 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
{
|
||||
if (attrIdentifier->mIdentifier != NULL)
|
||||
methodNodeSrc = attrIdentifier->mIdentifier;
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
attributeState.mSrc = attrIdentifier->mAttributes;
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
if (attrIdentifier->mIdentifier != NULL)
|
||||
targetFunctionName = attrIdentifier->mIdentifier->ToString();
|
||||
}
|
||||
|
@ -14370,7 +14396,8 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
{
|
||||
if (attrIdentifier->mIdentifier != NULL)
|
||||
methodNodeSrc = attrIdentifier->mIdentifier;
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
attributeState.mSrc = attrIdentifier->mAttributes;
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
targetFunctionName = attrIdentifier->mIdentifier->ToString();
|
||||
}
|
||||
else
|
||||
|
@ -14476,7 +14503,8 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
{
|
||||
if (attrIdentifier->mIdentifier != NULL)
|
||||
methodNodeSrc = attrIdentifier->mIdentifier;
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
attributeState.mSrc = attrIdentifier->mAttributes;
|
||||
attributeState.mCustomAttributes = mModule->GetCustomAttributes(attrIdentifier->mAttributes, attributeState.mTarget);
|
||||
}
|
||||
|
||||
allowImplicitThis = true;
|
||||
|
@ -14635,12 +14663,18 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
}
|
||||
|
||||
BfCheckedKind checkedKind = BfCheckedKind_NotSet;
|
||||
if (attributeState.mCustomAttributes != NULL)
|
||||
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL))
|
||||
{
|
||||
if (attributeState.mCustomAttributes->Contains(mModule->mCompiler->mCheckedAttributeTypeDef))
|
||||
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mCheckedAttributeTypeDef))
|
||||
{
|
||||
checkedKind = BfCheckedKind_Checked;
|
||||
if (attributeState.mCustomAttributes->Contains(mModule->mCompiler->mUncheckedAttributeTypeDef))
|
||||
mModule->mAttributeState->mUsed = true;
|
||||
}
|
||||
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mUncheckedAttributeTypeDef))
|
||||
{
|
||||
checkedKind = BfCheckedKind_Unchecked;
|
||||
mModule->mAttributeState->mUsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
SetAndRestoreValue<bool> prevUsedAsStatement(mUsedAsStatement, mUsedAsStatement || isCascade);
|
||||
|
@ -14648,6 +14682,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
mResult = MatchMethod(methodNodeSrc, methodBoundExpr, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, argValues, methodGenericArguments, checkedKind);
|
||||
argValues.HandleFixits(mModule);
|
||||
|
||||
if ((mModule->mAttributeState == &attributeState) && (!attributeState.mUsed))
|
||||
{
|
||||
mModule->Fail("Unused attributes", attributeState.mSrc);
|
||||
}
|
||||
|
||||
if (isCascade)
|
||||
{
|
||||
if (outCascadeValue != NULL)
|
||||
|
@ -16910,7 +16949,7 @@ void BfExprEvaluator::DoMemberReference(BfMemberReferenceExpression* memberRefEx
|
|||
|
||||
BfAutoComplete* autoComplete = GetAutoComplete();
|
||||
if (autoComplete != NULL)
|
||||
{
|
||||
{
|
||||
SetAndRestoreValue<bool> prevFriendSet(autoComplete->mHasFriendSet, (attributeState.mCustomAttributes != NULL) && (attributeState.mCustomAttributes->Contains(mModule->mCompiler->mFriendAttributeTypeDef)));
|
||||
|
||||
if (memberRefExpr->mTarget == NULL)
|
||||
|
@ -19260,7 +19299,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
{
|
||||
auto convertedValue = mModule->CastToValue(otherTypeSrc, *otherTypedValue, resultType, BfCastFlags_NoBox);
|
||||
if (!convertedValue)
|
||||
return;
|
||||
return;
|
||||
if ((binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_StrictEquality))
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateCmpEQ(resultTypedValue->mValue, convertedValue), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
else
|
||||
|
|
|
@ -2226,15 +2226,27 @@ BfProjectSet* BfModule::GetVisibleProjectSet()
|
|||
{
|
||||
auto typeInstance = type->ToTypeInstance();
|
||||
if (typeInstance == NULL)
|
||||
{
|
||||
if (type->IsSizedArray())
|
||||
_AddType(type->GetUnderlyingType());
|
||||
return;
|
||||
}
|
||||
if (typeInstance->IsTuple())
|
||||
{
|
||||
for (auto& fieldInst : typeInstance->mFieldInstances)
|
||||
{
|
||||
if (fieldInst.mDataIdx != -1)
|
||||
_AddType(fieldInst.mResolvedType);
|
||||
}
|
||||
}
|
||||
_AddProject(typeInstance->mTypeDef->mProject);
|
||||
if (typeInstance->mGenericTypeInfo == NULL)
|
||||
return;
|
||||
for (auto type : typeInstance->mGenericTypeInfo->mTypeGenericArguments)
|
||||
{
|
||||
if (seenTypes.Add(type))
|
||||
_AddType(type);
|
||||
}
|
||||
_AddType(type);
|
||||
}
|
||||
};
|
||||
|
||||
if (mCurTypeInstance != NULL)
|
||||
|
@ -2460,7 +2472,10 @@ bool BfModule::CheckProtection(BfProtection protection, bool allowProtected, boo
|
|||
((protection == BfProtection_Private) && (allowPrivate)))
|
||||
return true;
|
||||
if ((mAttributeState != NULL) && (mAttributeState->mCustomAttributes != NULL) && (mAttributeState->mCustomAttributes->Contains(mCompiler->mFriendAttributeTypeDef)))
|
||||
return true;
|
||||
{
|
||||
mAttributeState->mUsed = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2564,7 +2579,10 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me
|
|||
}
|
||||
|
||||
if ((mAttributeState != NULL) && (mAttributeState->mCustomAttributes != NULL) && (mAttributeState->mCustomAttributes->Contains(mCompiler->mFriendAttributeTypeDef)))
|
||||
{
|
||||
mAttributeState->mUsed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2584,7 +2602,9 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
BP_ZONE("BfModule::Fail");
|
||||
|
||||
if (mIgnoreErrors)
|
||||
{
|
||||
{
|
||||
if (mAttributeState != NULL)
|
||||
mAttributeState->mFlags = (BfAttributeState::Flags)(mAttributeState->mFlags | BfAttributeState::Flag_HadError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4167,19 +4187,25 @@ void BfModule::CreateValueTypeEqualsMethod(bool strictEquals)
|
|||
|
||||
auto _SizedIndex = [&](BfIRValue target, BfIRValue index)
|
||||
{
|
||||
BfTypedValue result;
|
||||
if (sizedArrayType->mElementType->IsSizeAligned())
|
||||
{
|
||||
auto ptrType = CreatePointerType(sizedArrayType->mElementType);
|
||||
auto ptrValue = mBfIRBuilder->CreateBitCast(target, mBfIRBuilder->MapType(ptrType));
|
||||
auto gepResult = mBfIRBuilder->CreateInBoundsGEP(ptrValue, index);
|
||||
return BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
|
||||
result = BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
auto indexResult = CreateIndexedValue(sizedArrayType->mElementType, target, index);
|
||||
return BfTypedValue(indexResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
|
||||
result = BfTypedValue(indexResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
|
||||
}
|
||||
|
||||
if (!result.mType->IsValueType())
|
||||
result = LoadValue(result);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
if (sizedArrayType->mElementCount > 6)
|
||||
|
@ -9874,6 +9900,7 @@ static String GetAttributesTargetListString(BfAttributeTargets attrTarget)
|
|||
AddAttributeTargetName(flagsLeft, BfAttributeTargets_MemberAccess, resultStr, "member access");
|
||||
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Alloc, resultStr, "allocations");
|
||||
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Alias, resultStr, "aliases");
|
||||
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Block, resultStr, "blocks");
|
||||
if (resultStr.IsEmpty())
|
||||
return "<nothing>";
|
||||
return resultStr;
|
||||
|
|
|
@ -660,13 +660,25 @@ public:
|
|||
|
||||
class BfAttributeState
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
Flag_None,
|
||||
Flag_StopOnError = 1,
|
||||
Flag_HadError = 2
|
||||
};
|
||||
|
||||
public:
|
||||
Flags mFlags;
|
||||
BfAstNode* mSrc;
|
||||
BfAttributeTargets mTarget;
|
||||
BfCustomAttributes* mCustomAttributes;
|
||||
BfCustomAttributes* mCustomAttributes;
|
||||
bool mUsed;
|
||||
|
||||
BfAttributeState()
|
||||
{
|
||||
mSrc = NULL;
|
||||
mFlags = Flag_None;
|
||||
mTarget = BfAttributeTargets_None;
|
||||
mCustomAttributes = NULL;
|
||||
mUsed = false;
|
||||
|
@ -1553,6 +1565,7 @@ public:
|
|||
virtual void Visit(BfExpressionStatement* expressionStmt) override;
|
||||
virtual void Visit(BfVariableDeclaration* varDecl) override;
|
||||
virtual void Visit(BfLocalMethodDeclaration* methodDecl) override;
|
||||
virtual void Visit(BfAttributedStatement* attribStmt) override;
|
||||
virtual void Visit(BfThrowStatement* throwStmt) override;
|
||||
virtual void Visit(BfDeleteStatement* deleteStmt) override;
|
||||
virtual void Visit(BfSwitchStatement* switchStmt) override;
|
||||
|
|
|
@ -3866,6 +3866,10 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
|
|||
|
||||
return localMethodDecl;
|
||||
}
|
||||
else if (token == BfToken_LBracket)
|
||||
{
|
||||
return CreateAttributedStatement(tokenNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto identifier = BfNodeDynCast<BfIdentifierNode>(node))
|
||||
|
@ -5311,7 +5315,10 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
|
|||
auto nextNode = mVisitorPos.GetNext();
|
||||
tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
|
||||
if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_RBracket))
|
||||
{
|
||||
mVisitorPos.MoveNext();
|
||||
goto Do_RBracket;
|
||||
}
|
||||
return attributeDirective;
|
||||
}
|
||||
MEMBER_SET(attributeDirective, mCtorCloseParen, tokenNode);
|
||||
|
@ -5340,6 +5347,44 @@ Do_RBracket:
|
|||
return attributeDirective;
|
||||
}
|
||||
|
||||
BfStatement* BfReducer::CreateAttributedStatement(BfTokenNode* tokenNode)
|
||||
{
|
||||
auto attrib = CreateAttributeDirective(tokenNode);
|
||||
if (attrib == NULL)
|
||||
return NULL;
|
||||
|
||||
BfAstNode* stmt = CreateStatementAfter(attrib);
|
||||
if (stmt != NULL)
|
||||
{
|
||||
bool isValid = true;
|
||||
|
||||
auto checkNode = stmt;
|
||||
if (auto exprStatement = BfNodeDynCast<BfExpressionStatement>(checkNode))
|
||||
checkNode = exprStatement->mExpression;
|
||||
|
||||
if ((checkNode->IsA<BfObjectCreateExpression>()) ||
|
||||
(checkNode->IsA<BfInvocationExpression>()) ||
|
||||
(checkNode->IsA<BfVariableDeclaration>()) ||
|
||||
(checkNode->IsA<BfBlock>()))
|
||||
{
|
||||
BfAttributedStatement* attribStmt = mAlloc->Alloc<BfAttributedStatement>();
|
||||
ReplaceNode(attrib, attribStmt);
|
||||
attribStmt->mAttributes = attrib;
|
||||
MEMBER_SET(attribStmt, mStatement, stmt);
|
||||
return attribStmt;
|
||||
}
|
||||
}
|
||||
|
||||
Fail("Prefixed attributes can only be used on allocations, invocations, blocks, or variable declarations", attrib);
|
||||
|
||||
BfAttributedStatement* attribStmt = mAlloc->Alloc<BfAttributedStatement>();
|
||||
ReplaceNode(attrib, attribStmt);
|
||||
attribStmt->mAttributes = attrib;
|
||||
if (stmt != NULL)
|
||||
MEMBER_SET(attribStmt, mStatement, stmt);
|
||||
return attribStmt;
|
||||
}
|
||||
|
||||
BfExpression* BfReducer::CreateAttributedExpression(BfTokenNode* tokenNode, bool onlyAllowIdentifier)
|
||||
{
|
||||
auto attrib = CreateAttributeDirective(tokenNode);
|
||||
|
@ -5347,8 +5392,8 @@ BfExpression* BfReducer::CreateAttributedExpression(BfTokenNode* tokenNode, bool
|
|||
return NULL;
|
||||
|
||||
if (!onlyAllowIdentifier)
|
||||
{
|
||||
auto expr = CreateExpressionAfter(attrib);
|
||||
{
|
||||
BfExpression* expr = CreateExpressionAfter(attrib);
|
||||
if (expr != NULL)
|
||||
{
|
||||
if (auto identifier = BfNodeDynCast<BfIdentifierNode>(expr))
|
||||
|
@ -5362,7 +5407,8 @@ BfExpression* BfReducer::CreateAttributedExpression(BfTokenNode* tokenNode, bool
|
|||
|
||||
if ((expr->IsA<BfObjectCreateExpression>()) ||
|
||||
(expr->IsA<BfInvocationExpression>()) ||
|
||||
(expr->IsA<BfVariableDeclaration>()))
|
||||
(expr->IsA<BfVariableDeclaration>()) ||
|
||||
(expr->IsA<BfBlock>()))
|
||||
{
|
||||
BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
|
||||
ReplaceNode(attrib, attribExpr);
|
||||
|
@ -5370,9 +5416,9 @@ BfExpression* BfReducer::CreateAttributedExpression(BfTokenNode* tokenNode, bool
|
|||
MEMBER_SET(attribExpr, mExpression, expr);
|
||||
return attribExpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fail("Prefixed attributes can only be used on constructor calls, invocations, or variable declarations", attrib);
|
||||
Fail("Prefixed attributes can only be used on allocations, invocations, blocks, or variable declarations", attrib);
|
||||
|
||||
BfAttributedExpression* attribExpr = mAlloc->Alloc<BfAttributedExpression>();
|
||||
ReplaceNode(attrib, attribExpr);
|
||||
|
|
|
@ -192,6 +192,7 @@ public:
|
|||
BfFieldDtorDeclaration* CreateFieldDtorDeclaration(BfAstNode* srcNode);
|
||||
BfFieldDeclaration* CreateFieldDeclaration(BfTokenNode* tokenNode, BfTypeReference* typeRef, BfIdentifierNode* nameIdentifier, BfFieldDeclaration* prevFieldDeclaration);
|
||||
BfAttributeDirective* CreateAttributeDirective(BfTokenNode* startToken);
|
||||
BfStatement* CreateAttributedStatement(BfTokenNode* tokenNode);
|
||||
BfExpression* CreateAttributedExpression(BfTokenNode* tokenNode, bool onlyAllowIdentifier);
|
||||
BfDelegateBindExpression* CreateDelegateBindExpression(BfAstNode* allocNode);
|
||||
BfLambdaBindExpression* CreateLambdaBindExpression(BfAstNode* allocNode, BfTokenNode* parenToken = NULL);
|
||||
|
|
|
@ -1492,7 +1492,8 @@ enum BfAttributeTargets : int32
|
|||
BfAttributeTargets_Alloc = 0x40000,
|
||||
BfAttributeTargets_Delete = 0x80000,
|
||||
BfAttributeTargets_Alias = 0x100000,
|
||||
BfAttributeTargets_All = 0x1FFFFF
|
||||
BfAttributeTargets_Block = 0x200000,
|
||||
BfAttributeTargets_All = 0x3FFFFF
|
||||
};
|
||||
|
||||
class BfAttributeData
|
||||
|
|
|
@ -3394,9 +3394,19 @@ void BfModule::VisitCodeBlock(BfBlock* block)
|
|||
{
|
||||
if (mCurMethodState->mCurScope->mExprEvaluator != NULL)
|
||||
{
|
||||
// Evaluate last child as an expression
|
||||
mCurMethodState->mCurScope->mExprEvaluator->VisitChild(expr);
|
||||
mCurMethodState->mCurScope->mExprEvaluator->FinishExpressionResult();
|
||||
if ((mAttributeState != NULL) &&
|
||||
((mAttributeState->mFlags & (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)) == (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)))
|
||||
{
|
||||
// Resolve as just 'false'
|
||||
mCurMethodState->mCurScope->mExprEvaluator->mResult = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Boolean));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Evaluate last child as an expression
|
||||
mCurMethodState->mCurScope->mExprEvaluator->VisitChild(expr);
|
||||
mCurMethodState->mCurScope->mExprEvaluator->FinishExpressionResult();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (mCurMethodState->InMainMixinScope())
|
||||
|
@ -3416,10 +3426,17 @@ void BfModule::VisitCodeBlock(BfBlock* block)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateSrcPos(child);
|
||||
BfAutoParentNodeEntry autoParentNode(this, child);
|
||||
child->Accept(this);
|
||||
|
||||
if ((mAttributeState != NULL) &&
|
||||
((mAttributeState->mFlags & (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)) == (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)))
|
||||
{
|
||||
// Ignore child
|
||||
}
|
||||
else
|
||||
child->Accept(this);
|
||||
|
||||
mSystem->CheckLockYield();
|
||||
|
||||
|
@ -3740,6 +3757,41 @@ void BfModule::Visit(BfLocalMethodDeclaration* methodDecl)
|
|||
Fail("Local method declarations must be wrapped in a block statement", methodDecl->mMethodDeclaration->mNameNode);
|
||||
}
|
||||
|
||||
void BfModule::Visit(BfAttributedStatement* attribStmt)
|
||||
{
|
||||
BfAttributeState attributeState;
|
||||
|
||||
attributeState.mTarget = (BfAttributeTargets)(BfAttributeTargets_Invocation | BfAttributeTargets_MemberAccess);
|
||||
if (auto block = BfNodeDynCast<BfBlock>(attribStmt->mStatement))
|
||||
attributeState.mTarget = BfAttributeTargets_Block;
|
||||
|
||||
attributeState.mCustomAttributes = GetCustomAttributes(attribStmt->mAttributes, attributeState.mTarget);
|
||||
|
||||
SetAndRestoreValue<BfAttributeState*> prevAttributeState(mAttributeState, &attributeState);
|
||||
|
||||
if (auto ignoreErrorsAttrib = attributeState.mCustomAttributes->Get(mCompiler->mIgnoreErrorsAttributeTypeDef))
|
||||
{
|
||||
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
|
||||
if (!ignoreErrorsAttrib->mCtorArgs.IsEmpty())
|
||||
{
|
||||
auto constant = mCurTypeInstance->mConstHolder->GetConstant(ignoreErrorsAttrib->mCtorArgs[0]);
|
||||
if (constant->mBool)
|
||||
attributeState.mFlags = BfAttributeState::Flag_StopOnError;
|
||||
}
|
||||
VisitChild(attribStmt->mStatement);
|
||||
attributeState.mUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VisitChild(attribStmt->mStatement);
|
||||
}
|
||||
|
||||
if (!attributeState.mUsed)
|
||||
{
|
||||
Fail("Unused attributes", attribStmt->mAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
void BfModule::Visit(BfExpression* expression)
|
||||
{
|
||||
UpdateSrcPos(expression);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue