<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />

ExpressionBinder

using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Syntax; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal class ExpressionBinder { protected class BinOpArgInfo { public EXPR arg1; public EXPR arg2; public PredefinedType pt1; public PredefinedType pt2; public PredefinedType ptRaw1; public PredefinedType ptRaw2; public CType type1; public CType type2; public CType typeRaw1; public CType typeRaw2; public BinOpKind binopKind; public BinOpMask mask; public BinOpArgInfo(EXPR op1, EXPR op2) { arg1 = op1; arg2 = op2; type1 = arg1.type; type2 = arg2.type; typeRaw1 = type1.StripNubs(); typeRaw2 = type2.StripNubs(); pt1 = (type1.isPredefined() ? type1.getPredefType() : PredefinedType.PT_COUNT); pt2 = (type2.isPredefined() ? type2.getPredefType() : PredefinedType.PT_COUNT); ptRaw1 = (typeRaw1.isPredefined() ? typeRaw1.getPredefType() : PredefinedType.PT_COUNT); ptRaw2 = (typeRaw2.isPredefined() ? typeRaw2.getPredefType() : PredefinedType.PT_COUNT); } public bool ValidForDelegate() { return (mask & BinOpMask.Delegate) != BinOpMask.None; } public bool ValidForEnumAndUnderlyingType() { return (mask & BinOpMask.EnumUnder) != BinOpMask.None; } public bool ValidForUnderlyingTypeAndEnum() { return (mask & BinOpMask.Add) != BinOpMask.None; } public bool ValidForEnum() { return (mask & BinOpMask.Enum) != BinOpMask.None; } public bool ValidForPointer() { return (mask & BinOpMask.Sub) != BinOpMask.None; } public bool ValidForVoidPointer() { return (mask & BinOpMask.VoidPtr) != BinOpMask.None; } public bool ValidForPointerAndNumber() { return (mask & BinOpMask.EnumUnder) != BinOpMask.None; } public bool ValidForNumberAndPointer() { return (mask & BinOpMask.Add) != BinOpMask.None; } } protected class BinOpSig { public PredefinedType pt1; public PredefinedType pt2; public BinOpMask mask; public int cbosSkip; public PfnBindBinOp pfn; public OpSigFlags grfos; public BinOpFuncKind fnkind; public BinOpSig() { } public BinOpSig(PredefinedType pt1, PredefinedType pt2, BinOpMask mask, int cbosSkip, PfnBindBinOp pfn, OpSigFlags grfos, BinOpFuncKind fnkind) { this.pt1 = pt1; this.pt2 = pt2; this.mask = mask; this.cbosSkip = cbosSkip; this.pfn = pfn; this.grfos = grfos; this.fnkind = fnkind; } public bool ConvertOperandsBeforeBinding() { return (grfos & OpSigFlags.Convert) != OpSigFlags.None; } public bool CanLift() { return (grfos & OpSigFlags.CanLift) != OpSigFlags.None; } public bool AutoLift() { return (grfos & OpSigFlags.AutoLift) != OpSigFlags.None; } } protected class BinOpFullSig : BinOpSig { private LiftFlags _grflt; private CType _type1; private CType _type2; public BinOpFullSig(CType type1, CType type2, PfnBindBinOp pfn, OpSigFlags grfos, LiftFlags grflt, BinOpFuncKind fnkind) { pt1 = PredefinedType.PT_UNDEFINEDINDEX; pt2 = PredefinedType.PT_UNDEFINEDINDEX; mask = BinOpMask.None; cbosSkip = 0; base.pfn = pfn; base.grfos = grfos; _type1 = type1; _type2 = type2; _grflt = grflt; base.fnkind = fnkind; } public BinOpFullSig(ExpressionBinder fnc, BinOpSig bos) { pt1 = bos.pt1; pt2 = bos.pt2; mask = bos.mask; cbosSkip = bos.cbosSkip; pfn = bos.pfn; grfos = bos.grfos; fnkind = bos.fnkind; _type1 = ((pt1 != PredefinedType.PT_UNDEFINEDINDEX) ? fnc.GetOptPDT(pt1) : null); _type2 = ((pt2 != PredefinedType.PT_UNDEFINEDINDEX) ? fnc.GetOptPDT(pt2) : null); _grflt = LiftFlags.None; } public bool FPreDef() { return pt1 != PredefinedType.PT_UNDEFINEDINDEX; } public bool isLifted() { if (_grflt == LiftFlags.None) return false; return true; } public bool ConvertFirst() { return (_grflt & LiftFlags.Convert1) != LiftFlags.None; } public bool ConvertSecond() { return (_grflt & LiftFlags.Convert2) != LiftFlags.None; } public CType Type1() { return _type1; } public CType Type2() { return _type2; } } private delegate bool ConversionFunc (EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, out EXPR ppDestinationExpr, CONVERTTYPE flags); private class ExplicitConversion { private ExpressionBinder _binder; private EXPR _exprSrc; private CType _typeSrc; private CType _typeDest; private EXPRTYPEORNAMESPACE _exprTypeDest; private CType _pDestinationTypeForLambdaErrorReporting; private EXPR _exprDest; private bool _needsExprDest; private CONVERTTYPE _flags; public EXPR ExprDest => _exprDest; public ExplicitConversion(ExpressionBinder binder, EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, CONVERTTYPE flags) { _binder = binder; _exprSrc = exprSrc; _typeSrc = typeSrc; _typeDest = typeDest.TypeOrNamespace.AsType(); _pDestinationTypeForLambdaErrorReporting = pDestinationTypeForLambdaErrorReporting; _exprTypeDest = typeDest; _needsExprDest = needsExprDest; _flags = flags; _exprDest = null; } public bool Bind() { if (_binder.BindImplicitConversion(_exprSrc, _typeSrc, _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.ISEXPLICIT)) return true; if (_typeSrc == null || _typeDest == null || _typeSrc.IsErrorType() || _typeDest.IsErrorType() || _typeDest.IsNeverSameType()) return false; if (_typeDest.IsNullableType()) return false; if (_typeSrc.IsNullableType()) return bindExplicitConversionFromNub(); if (bindExplicitConversionFromArrayToIList()) return true; switch (_typeDest.GetTypeKind()) { default: VSFAIL("Bad type kind"); return false; case TypeKind.TK_VoidType: return false; case TypeKind.TK_NullType: return false; case TypeKind.TK_TypeParameterType: if (bindExplicitConversionToTypeVar()) return true; break; case TypeKind.TK_ArrayType: if (bindExplicitConversionToArray(_typeDest.AsArrayType())) return true; break; case TypeKind.TK_PointerType: if (bindExplicitConversionToPointer()) return true; break; case TypeKind.TK_AggregateType: switch (bindExplicitConversionToAggregate(_typeDest.AsAggregateType())) { case AggCastResult.Success: return true; case AggCastResult.Abort: return false; } break; } if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0) return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false); return false; } private bool bindExplicitConversionFromNub() { if (_typeDest.IsValType() && _binder.BindExplicitConversion(null, _typeSrc.StripNubs(), _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _flags | CONVERTTYPE.NOUDC)) { if (_needsExprDest) { EXPR eXPR = _exprSrc; while (eXPR.type.IsNullableType()) { eXPR = _binder.BindNubValue(eXPR); } if (!_binder.BindExplicitConversion(eXPR, eXPR.type, _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.NOUDC)) { VSFAIL("BindExplicitConversion failed unexpectedly"); return false; } if (_exprDest.kind == ExpressionKind.EK_USERDEFINEDCONVERSION) _exprDest.asUSERDEFINEDCONVERSION().Argument = _exprSrc; } return true; } if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0) return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false); return false; } private bool bindExplicitConversionFromArrayToIList() { if (!_typeSrc.IsArrayType() || _typeSrc.AsArrayType().rank != 1 || !_typeDest.isInterfaceType() || _typeDest.AsAggregateType().GetTypeArgsAll().Size != 1) return false; AggregateSymbol optPredefAgg = GetSymbolLoader().GetOptPredefAgg(PredefinedType.PT_G_ILIST); AggregateSymbol optPredefAgg2 = GetSymbolLoader().GetOptPredefAgg(PredefinedType.PT_G_IREADONLYLIST); if ((optPredefAgg == null || !GetSymbolLoader().IsBaseAggregate(optPredefAgg, _typeDest.AsAggregateType().getAggregate())) && (optPredefAgg2 == null || !GetSymbolLoader().IsBaseAggregate(optPredefAgg2, _typeDest.AsAggregateType().getAggregate()))) return false; CType elementType = _typeSrc.AsArrayType().GetElementType(); CType typeDst = _typeDest.AsAggregateType().GetTypeArgsAll().Item(0); if (!CConversions.FExpRefConv(GetSymbolLoader(), elementType, typeDst)) return false; if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR); return true; } private bool bindExplicitConversionToTypeVar() { if (_typeSrc.isInterfaceType() || _binder.canConvert(_typeDest, _typeSrc, CONVERTTYPE.NOUDC)) { if (!_needsExprDest) return true; if (_typeSrc.IsTypeParameterType()) { EXPRCLASS exprTypeDest = GetExprFactory().MakeClass(_binder.GetReqPDT(PredefinedType.PT_OBJECT)); _binder.bindSimpleCast(_exprSrc, exprTypeDest, out EXPR pexprDest, EXPRFLAG.EXF_UNREALIZEDGOTO); _exprSrc = pexprDest; } if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_ASFINALLYLEAVE); return true; } return false; } private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest) { if (arrayDest.rank != 1 || !_typeSrc.isInterfaceType() || _typeSrc.AsAggregateType().GetTypeArgsAll().Size != 1) return false; AggregateSymbol optPredefAgg = GetSymbolLoader().GetOptPredefAgg(PredefinedType.PT_G_ILIST); AggregateSymbol optPredefAgg2 = GetSymbolLoader().GetOptPredefAgg(PredefinedType.PT_G_IREADONLYLIST); if ((optPredefAgg == null || !GetSymbolLoader().IsBaseAggregate(optPredefAgg, _typeSrc.AsAggregateType().getAggregate())) && (optPredefAgg2 == null || !GetSymbolLoader().IsBaseAggregate(optPredefAgg2, _typeSrc.AsAggregateType().getAggregate()))) return false; CType elementType = arrayDest.GetElementType(); CType cType = _typeSrc.AsAggregateType().GetTypeArgsAll().Item(0); if (elementType != cType && !CConversions.FExpRefConv(GetSymbolLoader(), elementType, cType)) return false; if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR); return true; } private bool bindExplicitConversionFromArrayToArray(ArrayType arraySrc, ArrayType arrayDest) { if (arraySrc.rank != arrayDest.rank) return false; if (CConversions.FExpRefConv(GetSymbolLoader(), arraySrc.GetElementType(), arrayDest.GetElementType())) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR); return true; } return false; } private bool bindExplicitConversionToArray(ArrayType arrayDest) { if (_typeSrc.IsArrayType()) return bindExplicitConversionFromArrayToArray(_typeSrc.AsArrayType(), arrayDest); if (bindExplicitConversionFromIListToArray(arrayDest)) return true; if (_binder.canConvert(_binder.GetReqPDT(PredefinedType.PT_ARRAY), _typeSrc, CONVERTTYPE.NOUDC)) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR); return true; } return false; } private bool bindExplicitConversionToPointer() { if (_typeSrc.IsPointerType() || (_typeSrc.fundType() <= FUNDTYPE.FT_U8 && _typeSrc.isNumericType())) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); return true; } return false; } private AggCastResult bindExplicitConversionFromEnumToAggregate(AggregateType aggTypeDest) { if (!_typeSrc.isEnumType()) return AggCastResult.Failure; AggregateSymbol aggregate = aggTypeDest.getAggregate(); if (aggregate.isPredefAgg(PredefinedType.PT_DECIMAL)) return bindExplicitConversionFromEnumToDecimal(aggTypeDest); if (!aggregate.getThisType().isNumericType() && !aggregate.IsEnum() && (!aggregate.IsPredefined() || aggregate.GetPredefType() != PredefinedType.PT_CHAR)) return AggCastResult.Failure; if (_exprSrc.GetConst() != null) { switch (_binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true)) { case ConstCastResult.Success: return AggCastResult.Success; case ConstCastResult.CheckFailure: return AggCastResult.Abort; } } if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); return AggCastResult.Success; } private AggCastResult bindExplicitConversionFromDecimalToEnum(AggregateType aggTypeDest) { if (_exprSrc.GetConst() != null) { switch (_binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true)) { case ConstCastResult.Success: return AggCastResult.Success; case ConstCastResult.CheckFailure: if ((_flags & CONVERTTYPE.CHECKOVERFLOW) == (CONVERTTYPE)0) return AggCastResult.Abort; break; } } bool flag = true; if (_needsExprDest) { CType typeDst = aggTypeDest.underlyingType(); flag = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, typeDst, _needsExprDest, out _exprDest, false); if (flag) _binder.bindSimpleCast(_exprDest, _exprTypeDest, out _exprDest); } if (!flag) return AggCastResult.Failure; return AggCastResult.Success; } private AggCastResult bindExplicitConversionFromEnumToDecimal(AggregateType aggTypeDest) { AggregateType aggregateType = _typeSrc.underlyingType().AsAggregateType(); EXPR pexprDest; if (_exprSrc == null) pexprDest = null; else { EXPRCLASS typeDest = GetExprFactory().MakeClass(aggregateType); _binder.bindSimpleCast(_exprSrc, typeDest, out pexprDest); } if (pexprDest.GetConst() != null) { switch (_binder.bindConstantCast(pexprDest, _exprTypeDest, _needsExprDest, out _exprDest, true)) { case ConstCastResult.Success: return AggCastResult.Success; case ConstCastResult.CheckFailure: if ((_flags & CONVERTTYPE.CHECKOVERFLOW) == (CONVERTTYPE)0) return AggCastResult.Abort; break; } } if (_needsExprDest) { bool flag = _binder.bindUserDefinedConversion(pexprDest, aggregateType, aggTypeDest, _needsExprDest, out _exprDest, false); } return AggCastResult.Success; } private AggCastResult bindExplicitConversionToEnum(AggregateType aggTypeDest) { AggregateSymbol aggregate = aggTypeDest.getAggregate(); if (!aggregate.IsEnum()) return AggCastResult.Failure; if (_typeSrc.isPredefType(PredefinedType.PT_DECIMAL)) return bindExplicitConversionFromDecimalToEnum(aggTypeDest); if (_typeSrc.isNumericType() || (_typeSrc.isPredefined() && _typeSrc.getPredefType() == PredefinedType.PT_CHAR)) { if (_exprSrc.GetConst() != null) { switch (_binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true)) { case ConstCastResult.Success: return AggCastResult.Success; case ConstCastResult.CheckFailure: return AggCastResult.Abort; } } if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); return AggCastResult.Success; } if (_typeSrc.isPredefined() && (_typeSrc.isPredefType(PredefinedType.PT_OBJECT) || _typeSrc.isPredefType(PredefinedType.PT_VALUE) || _typeSrc.isPredefType(PredefinedType.PT_ENUM))) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_INDEXER); return AggCastResult.Success; } return AggCastResult.Failure; } private AggCastResult bindExplicitConversionBetweenSimpleTypes(AggregateType aggTypeDest) { if (!_typeSrc.isSimpleType() || !aggTypeDest.isSimpleType()) return AggCastResult.Failure; AggregateSymbol aggregate = aggTypeDest.getAggregate(); PredefinedType predefType = _typeSrc.getPredefType(); PredefinedType predefType2 = aggregate.GetPredefType(); ConvKind convKind = GetConvKind(predefType, predefType2); if (convKind != ConvKind.Explicit) return AggCastResult.Failure; if (_exprSrc.GetConst() != null) { switch (_binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true)) { case ConstCastResult.Success: return AggCastResult.Success; case ConstCastResult.CheckFailure: if ((_flags & CONVERTTYPE.CHECKOVERFLOW) == (CONVERTTYPE)0) return AggCastResult.Abort; break; } } bool flag = true; if (_needsExprDest) { if (isUserDefinedConversion(predefType, predefType2)) flag = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, aggTypeDest, _needsExprDest, out _exprDest, false); else _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, ((_flags & CONVERTTYPE.CHECKOVERFLOW) != 0) ? EXPRFLAG.EXF_CHECKOVERFLOW : ((EXPRFLAG)0)); } if (!flag) return AggCastResult.Failure; return AggCastResult.Success; } private AggCastResult bindExplicitConversionBetweenAggregates(AggregateType aggTypeDest) { if (!_typeSrc.IsAggregateType()) return AggCastResult.Failure; AggregateSymbol aggregate = _typeSrc.AsAggregateType().getAggregate(); AggregateSymbol aggregate2 = aggTypeDest.getAggregate(); if (GetSymbolLoader().HasBaseConversion(aggTypeDest, _typeSrc.AsAggregateType())) { if (_needsExprDest) { if (aggregate2.IsValueType() && aggregate.getThisType().fundType() == FUNDTYPE.FT_REF) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_INDEXER); else _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR | ((_exprSrc != null) ? (_exprSrc.flags & EXPRFLAG.EXF_CANTBENULL) : ((EXPRFLAG)0))); } return AggCastResult.Success; } if ((aggregate.IsClass() && !aggregate.IsSealed() && aggregate2.IsInterface()) || (aggregate.IsInterface() && aggregate2.IsClass() && !aggregate2.IsSealed()) || (aggregate.IsInterface() && aggregate2.IsInterface()) || CConversions.HasGenericDelegateExplicitReferenceConversion(GetSymbolLoader(), _typeSrc, aggTypeDest)) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR | ((_exprSrc != null) ? (_exprSrc.flags & EXPRFLAG.EXF_CANTBENULL) : ((EXPRFLAG)0))); return AggCastResult.Success; } return AggCastResult.Failure; } private AggCastResult bindExplicitConversionFromPointerToInt(AggregateType aggTypeDest) { if (!_typeSrc.IsPointerType() || aggTypeDest.fundType() > FUNDTYPE.FT_U8 || !aggTypeDest.isNumericType()) return AggCastResult.Failure; if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); return AggCastResult.Success; } private AggCastResult bindExplicitConversionFromTypeVarToAggregate(AggregateType aggTypeDest) { if (!_typeSrc.IsTypeParameterType()) return AggCastResult.Failure; if (aggTypeDest.getAggregate().IsInterface()) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, (EXPRFLAG)40); return AggCastResult.Success; } return AggCastResult.Failure; } private AggCastResult bindExplicitConversionToAggregate(AggregateType aggTypeDest) { if (_typeSrc.isSpecialByRefType()) return AggCastResult.Abort; AggCastResult aggCastResult = bindExplicitConversionFromEnumToAggregate(aggTypeDest); if (aggCastResult != AggCastResult.Failure) return aggCastResult; aggCastResult = bindExplicitConversionToEnum(aggTypeDest); if (aggCastResult != AggCastResult.Failure) return aggCastResult; aggCastResult = bindExplicitConversionBetweenSimpleTypes(aggTypeDest); if (aggCastResult != AggCastResult.Failure) return aggCastResult; aggCastResult = bindExplicitConversionBetweenAggregates(aggTypeDest); if (aggCastResult != AggCastResult.Failure) return aggCastResult; aggCastResult = bindExplicitConversionFromPointerToInt(aggTypeDest); if (aggCastResult != AggCastResult.Failure) return aggCastResult; if (_typeSrc.IsVoidType()) return AggCastResult.Abort; aggCastResult = bindExplicitConversionFromTypeVarToAggregate(aggTypeDest); if (aggCastResult != AggCastResult.Failure) return aggCastResult; return AggCastResult.Failure; } private SymbolLoader GetSymbolLoader() { return _binder.GetSymbolLoader(); } private ExprFactory GetExprFactory() { return _binder.GetExprFactory(); } } protected delegate EXPR PfnBindBinOp (ExpressionKind ek, EXPRFLAG flags, EXPR op1, EXPR op2); protected delegate EXPR PfnBindUnaOp (ExpressionKind ek, EXPRFLAG flags, EXPR op); internal class GroupToArgsBinder { private enum Result { Success, Failure_SearchForExpanded, Failure_NoSearchForExpanded } private ExpressionBinder _pExprBinder; private bool _fCandidatesUnsupported; private BindingFlag _fBindFlags; private EXPRMEMGRP _pGroup; private ArgInfos _pArguments; private ArgInfos _pOriginalArguments; private bool _bHasNamedArguments; private AggregateType _pDelegate; private AggregateType _pCurrentType; private MethodOrPropertySymbol _pCurrentSym; private TypeArray _pCurrentTypeArgs; private TypeArray _pCurrentParameters; private TypeArray _pBestParameters; private int _nArgBest; private SymWithType[] _swtWrongCount = new SymWithType[20]; private int _nWrongCount; private bool _bIterateToEndOfNsList; private bool _bBindingCollectionAddArgs; private GroupToArgsBinderResult _results; private List<CandidateFunctionMember> _methList; private MethPropWithInst _mpwiParamTypeConstraints; private MethPropWithInst _mpwiBogus; private MethPropWithInst _mpwiCantInferInstArg; private MethWithType _mwtBadArity; private Name _pInvalidSpecifiedName; private Name _pNameUsedInPositionalArgument; private Name _pDuplicateSpecifiedName; private List<CType> _HiddenTypes; private bool _bArgumentsChangedForNamedOrOptionalArguments; public GroupToArgsBinder(ExpressionBinder exprBinder, BindingFlag bindFlags, EXPRMEMGRP grp, ArgInfos args, ArgInfos originalArgs, bool bHasNamedArguments, AggregateType atsDelegate) { _pExprBinder = exprBinder; _fCandidatesUnsupported = false; _fBindFlags = bindFlags; _pGroup = grp; _pArguments = args; _pOriginalArguments = originalArgs; _bHasNamedArguments = bHasNamedArguments; _pDelegate = atsDelegate; _pCurrentType = null; _pCurrentSym = null; _pCurrentTypeArgs = null; _pCurrentParameters = null; _pBestParameters = null; _nArgBest = -1; _nWrongCount = 0; _bIterateToEndOfNsList = false; _bBindingCollectionAddArgs = false; _results = new GroupToArgsBinderResult(); _methList = new List<CandidateFunctionMember>(); _mpwiParamTypeConstraints = new MethPropWithInst(); _mpwiBogus = new MethPropWithInst(); _mpwiCantInferInstArg = new MethPropWithInst(); _mwtBadArity = new MethWithType(); _HiddenTypes = new List<CType>(); } public bool Bind(bool bReportErrors) { LookForCandidates(); if (!GetResultOfBind(bReportErrors)) { if (bReportErrors) ReportErrorsOnFailure(); return false; } return true; } public GroupToArgsBinderResult GetResultsOfBind() { return _results; } public bool BindCollectionAddArgs() { _bBindingCollectionAddArgs = true; return Bind(true); } private SymbolLoader GetSymbolLoader() { return _pExprBinder.GetSymbolLoader(); } private CSemanticChecker GetSemanticChecker() { return _pExprBinder.GetSemanticChecker(); } private ErrorHandling GetErrorContext() { return _pExprBinder.GetErrorContext(); } public static CType GetTypeQualifier(EXPRMEMGRP pGroup) { CType cType = null; if ((pGroup.flags & EXPRFLAG.EXF_ASFINALLYLEAVE) == (EXPRFLAG)0) { if ((pGroup.flags & EXPRFLAG.EXF_CTOR) == (EXPRFLAG)0) { if (pGroup.GetOptionalObject() == null) return null; return pGroup.GetOptionalObject().type; } return pGroup.GetParentType(); } return null; } private void LookForCandidates() { bool flag = false; bool flag2 = true; int num = _swtWrongCount.Length; bool flag3 = true; bool flag4 = false; symbmask_t mask = (symbmask_t)(1 << (int)_pGroup.sk); CType pObject = (_pGroup.GetOptionalObject() != null) ? _pGroup.GetOptionalObject().type : null; CMemberLookupResults.CMethodIterator methodIterator = _pGroup.GetMemberLookupResults().GetMethodIterator(GetSemanticChecker(), GetSymbolLoader(), pObject, GetTypeQualifier(_pGroup), _pExprBinder.ContextForMemberLookup(), true, false, _pGroup.typeArgs.size, _pGroup.flags, mask); while (true) { bool flag5 = false; if (flag2 && !flag) flag5 = (flag = ConstructExpandedParameters()); if (!flag5) { flag = false; if (!GetNextSym(methodIterator)) break; _pCurrentParameters = _pCurrentSym.Params; flag2 = true; } if (_bArgumentsChangedForNamedOrOptionalArguments) { _bArgumentsChangedForNamedOrOptionalArguments = false; CopyArgInfos(_pOriginalArguments, _pArguments); } if (_pArguments.fHasExprs) { if (_bHasNamedArguments) { if (!ReOrderArgsForNamedArguments()) continue; } else if (HasOptionalParameters() && !AddArgumentsForOptionalParameters()) { continue; } } if (!flag5) { flag4 = true; flag3 &= _pCurrentSym.getBogus(); if (_pCurrentParameters.size != _pArguments.carg) { if (_nWrongCount < num && (!_pCurrentSym.isParamArray || _pArguments.carg < _pCurrentParameters.size - 1)) _swtWrongCount[_nWrongCount++] = new SymWithType(_pCurrentSym, _pCurrentType); flag2 = true; continue; } } if (methodIterator.CanUseCurrentSymbol()) { Result result = DetermineCurrentTypeArgs(); if (result != 0) flag2 = (result == Result.Failure_SearchForExpanded); else { bool flag6 = !methodIterator.IsCurrentSymbolInaccessible(); if (!flag6 && (!_methList.IsEmpty() || (bool)_results.GetInaccessibleResult())) flag2 = false; else { bool flag7 = flag6 && methodIterator.IsCurrentSymbolBogus(); if (flag7 && (!_methList.IsEmpty() || (bool)_results.GetInaccessibleResult() || (bool)_mpwiBogus)) flag2 = false; else if (!ArgumentsAreConvertible()) { flag2 = true; } else { if (!flag6) _results.GetInaccessibleResult().Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs); else if (flag7) { _mpwiBogus.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs); } else { _methList.Add(new CandidateFunctionMember(new MethPropWithInst(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs), _pCurrentParameters, 0, flag)); if (_pCurrentType.isInterfaceType()) { TypeArray ifacesAll = _pCurrentType.GetIfacesAll(); for (int i = 0; i < ifacesAll.size; i++) { AggregateType item = ifacesAll.Item(i).AsAggregateType(); _HiddenTypes.Add(item); } AggregateType reqPredefType = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT, true); _HiddenTypes.Add(reqPredefType); } } flag2 = false; } } } } } _fCandidatesUnsupported = (flag3 & flag4); if (_bArgumentsChangedForNamedOrOptionalArguments) CopyArgInfos(_pOriginalArguments, _pArguments); } private void CopyArgInfos(ArgInfos src, ArgInfos dst) { dst.carg = src.carg; dst.types = src.types; dst.fHasExprs = src.fHasExprs; dst.prgexpr.Clear(); for (int i = 0; i < src.prgexpr.Count; i++) { dst.prgexpr.Add(src.prgexpr[i]); } } private bool GetResultOfBind(bool bReportErrors) { if (!_methList.IsEmpty()) { CandidateFunctionMember candidateFunctionMember; if (_methList.Count == 1) candidateFunctionMember = _methList.Head(); else { CandidateFunctionMember methAmbig = null; CandidateFunctionMember methAmbig2 = null; CType pTypeThrough = (_pGroup.GetOptionalObject() != null) ? _pGroup.GetOptionalObject().type : null; candidateFunctionMember = _pExprBinder.FindBestMethod(_methList, pTypeThrough, _pArguments, out methAmbig, out methAmbig2); if (candidateFunctionMember == null) { candidateFunctionMember = methAmbig; _results.AmbiguousResult = methAmbig2.mpwi; if (bReportErrors) { if (methAmbig.params != methAmbig2.params || methAmbig.mpwi.MethProp().Params.size != methAmbig2.mpwi.MethProp().Params.size || methAmbig.mpwi.TypeArgs != methAmbig2.mpwi.TypeArgs || methAmbig.mpwi.GetType() != methAmbig2.mpwi.GetType() || methAmbig.mpwi.MethProp().Params == methAmbig2.mpwi.MethProp().Params) GetErrorContext().Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi, methAmbig2.mpwi); else GetErrorContext().Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi.MethProp(), methAmbig2.mpwi.MethProp()); } } } _results.BestResult = candidateFunctionMember.mpwi; if (bReportErrors) ReportErrorsOnSuccess(); return true; } return false; } private bool ReOrderArgsForNamedArguments() { MethodOrPropertySymbol methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.GetOptionalObject()); if (methodOrPropertySymbol == null) return false; int size = _pCurrentParameters.size; if (size == 0 || size < _pArguments.carg) return false; if (!NamedArgumentNamesAppearInParameterList(methodOrPropertySymbol)) return false; _bArgumentsChangedForNamedOrOptionalArguments = ReOrderArgsForNamedArguments(methodOrPropertySymbol, _pCurrentParameters, _pCurrentType, _pGroup, _pArguments, _pExprBinder.GetTypes(), _pExprBinder.GetExprFactory(), GetSymbolLoader()); return _bArgumentsChangedForNamedOrOptionalArguments; } internal static bool ReOrderArgsForNamedArguments(MethodOrPropertySymbol methprop, TypeArray pCurrentParameters, AggregateType pCurrentType, EXPRMEMGRP pGroup, ArgInfos pArguments, TypeManager typeManager, ExprFactory exprFactory, SymbolLoader symbolLoader) { int size = pCurrentParameters.size; EXPR[] array = new EXPR[size]; int num = 0; EXPR eXPR = null; TypeArray typeArray = typeManager.SubstTypeArray(pCurrentParameters, pCurrentType, pGroup.typeArgs); foreach (Name parameterName in methprop.ParameterNames) { if (num >= pCurrentParameters.size) break; if (methprop.isParamArray && num < pArguments.carg && pArguments.prgexpr[num].isARRINIT() && pArguments.prgexpr[num].asARRINIT().GeneratedForParamArray) eXPR = pArguments.prgexpr[num]; if (num < pArguments.carg && !pArguments.prgexpr[num].isNamedArgumentSpecification() && (!pArguments.prgexpr[num].isARRINIT() || !pArguments.prgexpr[num].asARRINIT().GeneratedForParamArray)) array[num] = pArguments.prgexpr[num++]; else { EXPR eXPR2 = FindArgumentWithName(pArguments, parameterName); if (eXPR2 == null) { if (methprop.IsParameterOptional(num)) eXPR2 = GenerateOptionalArgument(symbolLoader, exprFactory, methprop, typeArray.Item(num), num); else { if (eXPR == null || num != methprop.Params.Count - 1) return false; eXPR2 = eXPR; } } array[num++] = eXPR2; } } CType[] array2 = new CType[pCurrentParameters.size]; for (int i = 0; i < size; i++) { if (i < pArguments.prgexpr.Count) pArguments.prgexpr[i] = array[i]; else pArguments.prgexpr.Add(array[i]); array2[i] = pArguments.prgexpr[i].type; } pArguments.carg = pCurrentParameters.size; pArguments.types = symbolLoader.getBSymmgr().AllocParams(pCurrentParameters.size, array2); return true; } private static EXPR GenerateOptionalArgument(SymbolLoader symbolLoader, ExprFactory exprFactory, MethodOrPropertySymbol methprop, CType type, int index) { CType cType = type.IsNullableType() ? type.AsNullableType().GetUnderlyingType() : type; EXPR eXPR = null; if (methprop.HasDefaultParameterValue(index)) { CType defaultParameterValueConstValType = methprop.GetDefaultParameterValueConstValType(index); CONSTVAL defaultParameterValue = methprop.GetDefaultParameterValue(index); if (!defaultParameterValueConstValType.isPredefType(PredefinedType.PT_DATETIME) || (!cType.isPredefType(PredefinedType.PT_DATETIME) && !cType.isPredefType(PredefinedType.PT_OBJECT) && !cType.isPredefType(PredefinedType.PT_VALUE))) eXPR = (defaultParameterValueConstValType.isSimpleOrEnumOrString() ? ((!cType.isEnumType() || defaultParameterValueConstValType != cType.underlyingType()) ? exprFactory.CreateConstant(defaultParameterValueConstValType, defaultParameterValue) : exprFactory.CreateConstant(cType, defaultParameterValue)) : (((!type.IsRefType() && !type.IsNullableType()) || !defaultParameterValue.IsNullRef()) ? exprFactory.CreateZeroInit(type) : exprFactory.CreateNull())); else { AggregateType reqPredefType = symbolLoader.GetReqPredefType(PredefinedType.PT_DATETIME); eXPR = exprFactory.CreateConstant(reqPredefType, new CONSTVAL(DateTime.FromBinary(defaultParameterValue.longVal))); } } else if (type.isPredefType(PredefinedType.PT_OBJECT)) { if (methprop.MarshalAsObject(index)) eXPR = exprFactory.CreateNull(); else { AggregateSymbol optPredefAgg = symbolLoader.GetOptPredefAgg(PredefinedType.PT_MISSING); Name predefinedName = symbolLoader.GetNameManager().GetPredefinedName(PredefinedName.PN_CAP_VALUE); FieldSymbol field = symbolLoader.LookupAggMember(predefinedName, optPredefAgg, symbmask_t.MASK_FieldSymbol).AsFieldSymbol(); FieldWithType fWT = new FieldWithType(field, optPredefAgg.getThisType()); EXPRFIELD eXPRFIELD = exprFactory.CreateField((EXPRFLAG)0, optPredefAgg.getThisType(), null, 0, fWT, null); eXPR = ((optPredefAgg.getThisType() == type) ? ((EXPR)eXPRFIELD) : ((EXPR)exprFactory.CreateCast((EXPRFLAG)0, type, eXPRFIELD))); } } else { eXPR = exprFactory.CreateZeroInit(type); } eXPR.IsOptionalArgument = true; return eXPR; } private MethodOrPropertySymbol FindMostDerivedMethod(MethodOrPropertySymbol pMethProp, EXPR pObject) { return FindMostDerivedMethod(GetSymbolLoader(), pMethProp, pObject?.type); } public static MethodOrPropertySymbol FindMostDerivedMethod(SymbolLoader symbolLoader, MethodOrPropertySymbol pMethProp, CType pType) { bool flag = false; MethodSymbol methodSymbol; if (pMethProp.IsMethodSymbol()) methodSymbol = pMethProp.AsMethodSymbol(); else { PropertySymbol propertySymbol = pMethProp.AsPropertySymbol(); methodSymbol = ((propertySymbol.methGet != null) ? propertySymbol.methGet : propertySymbol.methSet); if (methodSymbol == null) return null; flag = propertySymbol.isIndexer(); } if (!methodSymbol.isVirtual) return methodSymbol; if (pType == null) return methodSymbol; if (methodSymbol.swtSlot != (SymWithType)null && methodSymbol.swtSlot.Meth() != null) methodSymbol = methodSymbol.swtSlot.Meth(); if (!pType.IsAggregateType()) return methodSymbol; AggregateSymbol aggregateSymbol = pType.AsAggregateType().GetOwningAggregate(); while (aggregateSymbol != null && aggregateSymbol.GetBaseAgg() != null) { for (MethodOrPropertySymbol methodOrPropertySymbol = symbolLoader.LookupAggMember(methodSymbol.name, aggregateSymbol, symbmask_t.MASK_MethodSymbol | symbmask_t.MASK_PropertySymbol).AsMethodOrPropertySymbol(); methodOrPropertySymbol != null; methodOrPropertySymbol = symbolLoader.LookupNextSym(methodOrPropertySymbol, aggregateSymbol, symbmask_t.MASK_MethodSymbol | symbmask_t.MASK_PropertySymbol).AsMethodOrPropertySymbol()) { if (methodOrPropertySymbol.isOverride && methodOrPropertySymbol.swtSlot.Sym != null && methodOrPropertySymbol.swtSlot.Sym == methodSymbol) { if (flag) return methodOrPropertySymbol.AsMethodSymbol().getProperty(); return methodOrPropertySymbol; } } aggregateSymbol = aggregateSymbol.GetBaseAgg(); } return methodSymbol; } private bool HasOptionalParameters() { return FindMostDerivedMethod(_pCurrentSym, _pGroup.GetOptionalObject())?.HasOptionalParameters() ?? false; } private bool AddArgumentsForOptionalParameters() { if (_pCurrentParameters.size <= _pArguments.carg) return true; MethodOrPropertySymbol methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.GetOptionalObject()); if (methodOrPropertySymbol == null) return false; int num = _pArguments.carg; int num2 = 0; TypeArray typeArray = _pExprBinder.GetTypes().SubstTypeArray(_pCurrentParameters, _pCurrentType, _pGroup.typeArgs); EXPR[] array = new EXPR[_pCurrentParameters.size - num]; while (num < typeArray.size) { if (!methodOrPropertySymbol.IsParameterOptional(num)) return false; array[num2] = GenerateOptionalArgument(GetSymbolLoader(), _pExprBinder.GetExprFactory(), methodOrPropertySymbol, typeArray.Item(num), num); num++; num2++; } for (int i = 0; i < num2; i++) { _pArguments.prgexpr.Add(array[i]); } CType[] array2 = new CType[typeArray.size]; for (int j = 0; j < typeArray.size; j++) { array2[j] = _pArguments.prgexpr[j].type; } _pArguments.types = GetSymbolLoader().getBSymmgr().AllocParams(typeArray.size, array2); _pArguments.carg = typeArray.size; _bArgumentsChangedForNamedOrOptionalArguments = true; return true; } private static EXPR FindArgumentWithName(ArgInfos pArguments, Name pName) { for (int i = 0; i < pArguments.carg; i++) { if (pArguments.prgexpr[i].isNamedArgumentSpecification() && pArguments.prgexpr[i].asNamedArgumentSpecification().Name == pName) return pArguments.prgexpr[i]; } return null; } private bool NamedArgumentNamesAppearInParameterList(MethodOrPropertySymbol methprop) { List<Name> list = methprop.ParameterNames; HashSet<Name> hashSet = new HashSet<Name>(); for (int i = 0; i < _pArguments.carg; i++) { if (!_pArguments.prgexpr[i].isNamedArgumentSpecification()) { if (!list.IsEmpty()) list = list.Tail(); } else { Name name = _pArguments.prgexpr[i].asNamedArgumentSpecification().Name; if (!methprop.ParameterNames.Contains(name)) { if (_pInvalidSpecifiedName == null) _pInvalidSpecifiedName = name; return false; } if (!list.Contains(name)) { if (_pNameUsedInPositionalArgument == null) _pNameUsedInPositionalArgument = name; return false; } if (hashSet.Contains(name)) { if (_pDuplicateSpecifiedName == null) _pDuplicateSpecifiedName = name; return false; } hashSet.Add(name); } } return true; } private bool GetNextSym(CMemberLookupResults.CMethodIterator iterator) { if (!iterator.MoveNext(_methList.IsEmpty(), _bIterateToEndOfNsList)) return false; _pCurrentSym = iterator.GetCurrentSymbol(); AggregateType currentType = iterator.GetCurrentType(); if (_pCurrentType != currentType && _pCurrentType != null && !_methList.IsEmpty() && !_methList.Head().mpwi.GetType().isInterfaceType() && (!_methList.Head().mpwi.Sym.IsMethodSymbol() || !_methList.Head().mpwi.Meth().IsExtension())) return false; if (_pCurrentType != currentType && _pCurrentType != null && !_methList.IsEmpty() && !_methList.Head().mpwi.GetType().isInterfaceType() && _methList.Head().mpwi.Sym.IsMethodSymbol() && _methList.Head().mpwi.Meth().IsExtension() && _pGroup.GetOptionalObject() != null) _bIterateToEndOfNsList = true; _pCurrentType = currentType; while (_HiddenTypes.Contains(_pCurrentType)) { while (iterator.GetCurrentType() == _pCurrentType) { iterator.MoveNext(_methList.IsEmpty(), _bIterateToEndOfNsList); } _pCurrentSym = iterator.GetCurrentSymbol(); _pCurrentType = iterator.GetCurrentType(); if (iterator.AtEnd()) return false; } return true; } private bool ConstructExpandedParameters() { if (_pCurrentSym == null || _pArguments == null || _pCurrentParameters == null) return false; if ((_fBindFlags & BindingFlag.BIND_NOPARAMS) != 0) return false; if (!_pCurrentSym.isParamArray) return false; int num = 0; for (int i = _pArguments.carg; i < _pCurrentSym.Params.size; i++) { if (_pCurrentSym.IsParameterOptional(i)) num++; } if (_pArguments.carg + num < _pCurrentParameters.size - 1) return false; return _pExprBinder.TryGetExpandedParams(_pCurrentSym.Params, _pArguments.carg, out _pCurrentParameters); } private Result DetermineCurrentTypeArgs() { TypeArray typeArgs = _pGroup.typeArgs; if (_pCurrentSym.IsMethodSymbol() && _pCurrentSym.AsMethodSymbol().typeVars.size != typeArgs.size) { MethodSymbol methodSymbol = _pCurrentSym.AsMethodSymbol(); if (typeArgs.size > 0) { if (!(bool)_mwtBadArity) _mwtBadArity.Set(methodSymbol, _pCurrentType); return Result.Failure_NoSearchForExpanded; } if (!MethodTypeInferrer.Infer(_pExprBinder, GetSymbolLoader(), methodSymbol, _pCurrentType.GetTypeArgsAll(), _pCurrentParameters, _pArguments, out _pCurrentTypeArgs)) { if (_results.IsBetterUninferableResult(_pCurrentTypeArgs)) { TypeArray typeVars = methodSymbol.typeVars; if (typeVars != null && _pCurrentTypeArgs != null && typeVars.size == _pCurrentTypeArgs.size) _mpwiCantInferInstArg.Set(_pCurrentSym.AsMethodSymbol(), _pCurrentType, _pCurrentTypeArgs); else _mpwiCantInferInstArg.Set(_pCurrentSym.AsMethodSymbol(), _pCurrentType, typeVars); } return Result.Failure_SearchForExpanded; } } else _pCurrentTypeArgs = typeArgs; return Result.Success; } private bool ArgumentsAreConvertible() { bool flag = false; bool flag2 = false; if (_pArguments.carg != 0) { UpdateArguments(); for (int i = 0; i < _pArguments.carg; i++) { CType cType = _pCurrentParameters.Item(i); if (!TypeBind.CheckConstraints(GetSemanticChecker(), GetErrorContext(), cType, CheckConstraintsFlags.NoErrors) && !DoesTypeArgumentsContainErrorSym(cType)) { _mpwiParamTypeConstraints.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs); return false; } } for (int j = 0; j < _pArguments.carg; j++) { CType cType2 = _pCurrentParameters.Item(j); flag |= DoesTypeArgumentsContainErrorSym(cType2); bool flag3; if (_pArguments.fHasExprs) { EXPR expr = _pArguments.prgexpr[j]; if (expr.isNamedArgumentSpecification()) expr = expr.asNamedArgumentSpecification().Value; flag3 = _pExprBinder.canConvert(expr, cType2); } else flag3 = _pExprBinder.canConvert(_pArguments.types.Item(j), cType2); if (!flag3 && !flag) { if (j > _nArgBest) { _nArgBest = j; if (!(bool)_results.GetBestResult()) { _results.GetBestResult().Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs); _pBestParameters = _pCurrentParameters; } } else if (j == _nArgBest && _pArguments.types.Item(j) != cType2) { CType cType3 = _pArguments.types.Item(j).IsParameterModifierType() ? _pArguments.types.Item(j).AsParameterModifierType().GetParameterType() : _pArguments.types.Item(j); CType cType4 = cType2.IsParameterModifierType() ? cType2.AsParameterModifierType().GetParameterType() : cType2; if (cType3 == cType4 && !(bool)_results.GetBestResult()) { _results.GetBestResult().Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs); _pBestParameters = _pCurrentParameters; } } if (_pCurrentSym.IsMethodSymbol() && (!_pCurrentSym.AsMethodSymbol().IsExtension() | flag2)) _results.AddInconvertibleResult(_pCurrentSym.AsMethodSymbol(), _pCurrentType, _pCurrentTypeArgs); return false; } } } if (flag) { if (_results.IsBetterUninferableResult(_pCurrentTypeArgs) && _pCurrentSym.IsMethodSymbol() && (!_pCurrentSym.AsMethodSymbol().IsExtension() || _pCurrentSym.AsMethodSymbol().typeVars.size == 0 || MethodTypeInferrer.CanObjectOfExtensionBeInferred(_pExprBinder, GetSymbolLoader(), _pCurrentSym.AsMethodSymbol(), _pCurrentType.GetTypeArgsAll(), _pCurrentSym.AsMethodSymbol().Params, _pArguments))) _results.GetUninferableResult().Set(_pCurrentSym.AsMethodSymbol(), _pCurrentType, _pCurrentTypeArgs); } else if (_pCurrentSym.IsMethodSymbol() && (!_pCurrentSym.AsMethodSymbol().IsExtension() | flag2)) { _results.AddInconvertibleResult(_pCurrentSym.AsMethodSymbol(), _pCurrentType, _pCurrentTypeArgs); } return !flag; } private void UpdateArguments() { _pCurrentParameters = _pExprBinder.GetTypes().SubstTypeArray(_pCurrentParameters, _pCurrentType, _pCurrentTypeArgs); if (_pArguments.prgexpr != null && _pArguments.prgexpr.Count != 0) { MethodOrPropertySymbol methodOrPropertySymbol = null; for (int i = 0; i < _pCurrentParameters.size; i++) { EXPR eXPR = _pArguments.prgexpr[i]; if (eXPR.IsOptionalArgument) { CType cType = _pCurrentParameters.Item(i); if (cType != eXPR.type) { if (methodOrPropertySymbol == null) methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.GetOptionalObject()); EXPR value = GenerateOptionalArgument(GetSymbolLoader(), _pExprBinder.GetExprFactory(), methodOrPropertySymbol, _pCurrentParameters[i], i); _pArguments.prgexpr[i] = value; } } } } } private bool DoesTypeArgumentsContainErrorSym(CType var) { if (!var.IsAggregateType()) return false; TypeArray typeArgsAll = var.AsAggregateType().GetTypeArgsAll(); for (int i = 0; i < typeArgsAll.size; i++) { CType cType = typeArgsAll.Item(i); if (cType.IsErrorType()) return true; if (cType.IsAggregateType() && DoesTypeArgumentsContainErrorSym(cType)) return true; } return false; } private void ReportErrorsOnSuccess() { if (_results.GetBestResult().MethProp().name == GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_DTOR) && _results.GetBestResult().MethProp().getClass() .isPredefAgg(PredefinedType.PT_OBJECT)) { if ((_pGroup.flags & EXPRFLAG.EXF_ASFINALLYLEAVE) != 0) GetErrorContext().Error(ErrorCode.ERR_CallingBaseFinalizeDeprecated, Array.Empty<ErrArg>()); else GetErrorContext().Error(ErrorCode.ERR_CallingFinalizeDepracated, Array.Empty<ErrArg>()); } if (_pGroup.sk == SYMKIND.SK_MethodSymbol && _results.GetBestResult().TypeArgs.size > 0) TypeBind.CheckMethConstraints(GetSemanticChecker(), GetErrorContext(), new MethWithInst(_results.GetBestResult())); } private void ReportErrorsOnFailure() { if (_pDuplicateSpecifiedName != null) GetErrorContext().Error(ErrorCode.ERR_DuplicateNamedArgument, _pDuplicateSpecifiedName); else if ((bool)_results.GetInaccessibleResult()) { GetSemanticChecker().ReportAccessError(_results.GetInaccessibleResult(), _pExprBinder.ContextForMemberLookup(), GetTypeQualifier(_pGroup)); } else if ((bool)_mpwiBogus) { GetErrorContext().ErrorRef(ErrorCode.ERR_BindToBogus, _mpwiBogus); } else { bool flag = false; Name name = _pGroup.name; if (_pGroup.GetOptionalObject() != null && _pGroup.GetOptionalObject().type != null && _pGroup.GetOptionalObject().type.isDelegateType() && _pGroup.name == GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_INVOKE)) { flag = true; name = _pGroup.GetOptionalObject().type.getAggregate().name; } if ((bool)_results.GetBestResult()) ReportErrorsForBestMatching(flag, name); else if ((bool)_results.GetUninferableResult() || (bool)_mpwiCantInferInstArg) { if (!(bool)_results.GetUninferableResult()) _results.GetUninferableResult().Set(_mpwiCantInferInstArg.Sym.AsMethodSymbol(), _mpwiCantInferInstArg.GetType(), _mpwiCantInferInstArg.TypeArgs); MethodSymbol methodSymbol = _results.GetUninferableResult().Meth(); TypeArray params = methodSymbol.Params; CType cType = null; if (_pGroup.GetOptionalObject() != null) cType = _pGroup.GetOptionalObject().type; else if (_pGroup.GetOptionalLHS() != null) { cType = _pGroup.GetOptionalLHS().type; } MethWithType methWithType = new MethWithType(); methWithType.Set(_results.GetUninferableResult().Meth(), _results.GetUninferableResult().GetType()); GetErrorContext().Error(ErrorCode.ERR_CantInferMethTypeArgs, methWithType); } else if ((bool)_mwtBadArity) { int size = _mwtBadArity.Meth().typeVars.size; GetErrorContext().ErrorRef((size > 0) ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _mwtBadArity, new ErrArgSymKind(_mwtBadArity.Meth()), _pArguments.carg); } else if ((bool)_mpwiParamTypeConstraints) { TypeBind.CheckMethConstraints(GetSemanticChecker(), GetErrorContext(), new MethWithInst(_mpwiParamTypeConstraints)); } else if (_pInvalidSpecifiedName != null) { if (_pGroup.GetOptionalObject() != null && _pGroup.GetOptionalObject().type.IsAggregateType() && _pGroup.GetOptionalObject().type.AsAggregateType().GetOwningAggregate().IsDelegate()) GetErrorContext().Error(ErrorCode.ERR_BadNamedArgumentForDelegateInvoke, _pGroup.GetOptionalObject().type.AsAggregateType().GetOwningAggregate().name, _pInvalidSpecifiedName); else GetErrorContext().Error(ErrorCode.ERR_BadNamedArgument, _pGroup.name, _pInvalidSpecifiedName); } else if (_pNameUsedInPositionalArgument != null) { GetErrorContext().Error(ErrorCode.ERR_NamedArgumentUsedInPositional, _pNameUsedInPositionalArgument); } else { CParameterizedError error = default(CParameterizedError); if (_pDelegate != null) { GetErrorContext().MakeError(out error, ErrorCode.ERR_MethDelegateMismatch, name, _pDelegate); GetErrorContext().AddRelatedTypeLoc(error, _pDelegate); } else if (_fCandidatesUnsupported) { GetErrorContext().MakeError(out error, ErrorCode.ERR_BindToBogus, name); } else if (flag) { GetErrorContext().MakeError(out error, ErrorCode.ERR_BadDelArgCount, name, _pArguments.carg); } else if ((_pGroup.flags & EXPRFLAG.EXF_CTOR) != 0) { GetErrorContext().MakeError(out error, ErrorCode.ERR_BadCtorArgCount, _pGroup.GetParentType(), _pArguments.carg); } else { GetErrorContext().MakeError(out error, ErrorCode.ERR_BadArgCount, name, _pArguments.carg); } for (int i = 0; i < _nWrongCount; i++) { if (GetSemanticChecker().CheckAccess(_swtWrongCount[i].Sym, _swtWrongCount[i].GetType(), _pExprBinder.ContextForMemberLookup(), GetTypeQualifier(_pGroup))) GetErrorContext().AddRelatedSymLoc(error, _swtWrongCount[i].Sym); } GetErrorContext().SubmitError(error); } } } private void ReportErrorsForBestMatching(bool bUseDelegateErrors, Name nameErr) { if (_pDelegate != null) GetErrorContext().ErrorRef(ErrorCode.ERR_MethDelegateMismatch, nameErr, _pDelegate, _results.GetBestResult()); else if (!_bBindingCollectionAddArgs || !ReportErrorsForCollectionAdd()) { if (bUseDelegateErrors) GetErrorContext().Error(ErrorCode.ERR_BadDelArgTypes, _results.GetBestResult().GetType()); else if (_results.GetBestResult().Sym.IsMethodSymbol() && _results.GetBestResult().Sym.AsMethodSymbol().IsExtension() && _pGroup.GetOptionalObject() != null) { GetErrorContext().Error(ErrorCode.ERR_BadExtensionArgTypes, _pGroup.GetOptionalObject().type, _pGroup.name, _results.GetBestResult().Sym); } else if (_bBindingCollectionAddArgs) { GetErrorContext().Error(ErrorCode.ERR_BadArgTypesForCollectionAdd, _results.GetBestResult()); } else { GetErrorContext().Error(ErrorCode.ERR_BadArgTypes, _results.GetBestResult()); } for (int i = 0; i < _pArguments.carg; i++) { CType cType = _pBestParameters.Item(i); if (!_pExprBinder.canConvert(_pArguments.prgexpr[i], cType)) { CType cType2 = _pArguments.types.Item(i).IsParameterModifierType() ? _pArguments.types.Item(i).AsParameterModifierType().GetParameterType() : _pArguments.types.Item(i); CType cType3 = cType.IsParameterModifierType() ? cType.AsParameterModifierType().GetParameterType() : cType; if (cType2 == cType3) { if (cType3 != cType) GetErrorContext().Error(ErrorCode.ERR_BadArgRef, i + 1, (cType.IsParameterModifierType() && cType.AsParameterModifierType().isOut) ? "out" : "ref"); else { CType cType4 = _pArguments.types.Item(i); GetErrorContext().Error(ErrorCode.ERR_BadArgExtraRef, i + 1, (cType4.IsParameterModifierType() && cType4.AsParameterModifierType().isOut) ? "out" : "ref"); } } else { Symbol sym = _results.GetBestResult().Sym; if (i == 0 && sym.IsMethodSymbol() && sym.AsMethodSymbol().IsExtension() && _pGroup.GetOptionalObject() != null && !_pExprBinder.canConvertInstanceParamForExtension(_pGroup.GetOptionalObject(), sym.AsMethodSymbol().Params.Item(0))) { if (!_pGroup.GetOptionalObject().type.getBogus()) GetErrorContext().Error(ErrorCode.ERR_BadInstanceArgType, _pGroup.GetOptionalObject().type, cType); } else GetErrorContext().Error(ErrorCode.ERR_BadArgType, i + 1, new ErrArg(_pArguments.types.Item(i), ErrArgFlags.Unique), new ErrArg(cType, ErrArgFlags.Unique)); } } } } } private bool ReportErrorsForCollectionAdd() { for (int i = 0; i < _pArguments.carg; i++) { CType cType = _pBestParameters.Item(i); if (cType.IsParameterModifierType()) { GetErrorContext().ErrorRef(ErrorCode.ERR_InitializerAddHasParamModifiers, _results.GetBestResult()); return true; } } return false; } } internal class GroupToArgsBinderResult { public MethPropWithInst BestResult; public MethPropWithInst AmbiguousResult; public MethPropWithInst InaccessibleResult; public MethPropWithInst UninferableResult; public MethPropWithInst InconvertibleResult; private List<MethPropWithInst> _inconvertibleResults; public MethPropWithInst GetBestResult() { return BestResult; } public MethPropWithInst GetAmbiguousResult() { return AmbiguousResult; } public MethPropWithInst GetInaccessibleResult() { return InaccessibleResult; } public MethPropWithInst GetUninferableResult() { return UninferableResult; } public GroupToArgsBinderResult() { BestResult = new MethPropWithInst(); AmbiguousResult = new MethPropWithInst(); InaccessibleResult = new MethPropWithInst(); UninferableResult = new MethPropWithInst(); InconvertibleResult = new MethPropWithInst(); _inconvertibleResults = new List<MethPropWithInst>(); } public void AddInconvertibleResult(MethodSymbol method, AggregateType currentType, TypeArray currentTypeArgs) { if (InconvertibleResult.Sym == null) InconvertibleResult.Set(method, currentType, currentTypeArgs); _inconvertibleResults.Add(new MethPropWithInst(method, currentType, currentTypeArgs)); } private static int NumberOfErrorTypes(TypeArray pTypeArgs) { int num = 0; for (int i = 0; i < pTypeArgs.Size; i++) { if (pTypeArgs.Item(i).IsErrorType()) num++; } return num; } private static bool IsBetterThanCurrent(TypeArray pTypeArgs1, TypeArray pTypeArgs2) { int num = NumberOfErrorTypes(pTypeArgs1); int num2 = NumberOfErrorTypes(pTypeArgs2); if (num == num2) { int num3 = (pTypeArgs1.Size > pTypeArgs2.Size) ? pTypeArgs2.Size : pTypeArgs1.Size; for (int i = 0; i < num3; i++) { if (pTypeArgs1.Item(i).IsAggregateType()) num += NumberOfErrorTypes(pTypeArgs1.Item(i).AsAggregateType().GetTypeArgsAll()); if (pTypeArgs2.Item(i).IsAggregateType()) num2 += NumberOfErrorTypes(pTypeArgs2.Item(i).AsAggregateType().GetTypeArgsAll()); } } return num2 < num; } public bool IsBetterUninferableResult(TypeArray pTypeArguments) { if (UninferableResult.Sym == null) return true; if (pTypeArguments == null) return false; return IsBetterThanCurrent(UninferableResult.TypeArgs, pTypeArguments); } } private class ImplicitConversion { private EXPR _exprDest; private ExpressionBinder _binder; private EXPR _exprSrc; private CType _typeSrc; private CType _typeDest; private EXPRTYPEORNAMESPACE _exprTypeDest; private bool _needsExprDest; private CONVERTTYPE _flags; public EXPR ExprDest => _exprDest; public ImplicitConversion(ExpressionBinder binder, EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, bool needsExprDest, CONVERTTYPE flags) { _binder = binder; _exprSrc = exprSrc; _typeSrc = typeSrc; _typeDest = typeDest.TypeOrNamespace.AsType(); _exprTypeDest = typeDest; _needsExprDest = needsExprDest; _flags = flags; _exprDest = null; } public bool Bind() { if (_typeSrc != null && _typeDest != null && !_typeDest.IsNeverSameType()) { switch (_typeDest.GetTypeKind()) { case TypeKind.TK_ErrorType: if (_typeSrc != _typeDest) return false; if (_needsExprDest) _exprDest = _exprSrc; return true; case TypeKind.TK_NullType: if (!_typeSrc.IsNullType()) return false; if (_needsExprDest) _exprDest = _exprSrc; return true; case TypeKind.TK_MethodGroupType: VSFAIL("Something is wrong with Type.IsNeverSameType()"); return false; case TypeKind.TK_NaturalIntegerType: case TypeKind.TK_ArgumentListType: return _typeSrc == _typeDest; case TypeKind.TK_VoidType: return false; default: { if (_typeSrc.IsErrorType()) return false; if (_typeSrc == _typeDest && ((_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0 || (!_typeSrc.isPredefType(PredefinedType.PT_FLOAT) && !_typeSrc.isPredefType(PredefinedType.PT_DOUBLE)))) { if (_needsExprDest) _exprDest = _exprSrc; return true; } if (_typeDest.IsNullableType()) return BindNubConversion(_typeDest.AsNullableType()); if (_typeSrc.IsNullableType()) return bindImplicitConversionFromNullable(_typeSrc.AsNullableType()); if ((_flags & CONVERTTYPE.ISEXPLICIT) != 0) _flags |= CONVERTTYPE.NOUDC; FUNDTYPE fUNDTYPE = _typeDest.fundType(); switch (_typeSrc.GetTypeKind()) { default: VSFAIL("Bad type symbol kind"); break; case TypeKind.TK_MethodGroupType: if (_exprSrc.isMEMGRP()) { EXPRCALL pexprDst; bool result = _binder.BindGrpConversion(_exprSrc.asMEMGRP(), _typeDest, _needsExprDest, out pexprDst, false); _exprDest = pexprDst; return result; } return false; case TypeKind.TK_VoidType: case TypeKind.TK_ErrorType: case TypeKind.TK_ArgumentListType: case TypeKind.TK_ParameterModifierType: return false; case TypeKind.TK_NullType: if (bindImplicitConversionFromNull()) return true; break; case TypeKind.TK_ArrayType: if (bindImplicitConversionFromArray()) return true; break; case TypeKind.TK_PointerType: if (bindImplicitConversionFromPointer()) return true; break; case TypeKind.TK_TypeParameterType: if (bindImplicitConversionFromTypeVar(_typeSrc.AsTypeParameterType())) return true; break; case TypeKind.TK_AggregateType: if (_typeSrc.isSpecialByRefType()) return false; if (bindImplicitConversionFromAgg(_typeSrc.AsAggregateType())) return true; break; } if (_exprSrc != null && _exprSrc.RuntimeObject != null && TypeExtensions.IsInstanceOfType(_typeDest.AssociatedSystemType, _exprSrc.RuntimeObject) && _binder.GetSemanticChecker().CheckTypeAccess(_typeDest, _binder.Context.ContextForMemberLookup())) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, _exprSrc.flags & EXPRFLAG.EXF_CANTBENULL); return true; } if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0) return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, true); return false; } } } return false; } private bool BindNubConversion(NullableType nubDst) { AggregateType ats = nubDst.GetAts(GetErrorContext()); if (ats == null) return false; if (GetSymbolLoader().HasBaseConversion(nubDst.GetUnderlyingType(), _typeSrc) && !CConversions.FWrappingConv(_typeSrc, nubDst)) { if ((_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0) return false; if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_INDEXER); return true; } int pcnub; CType cType = nubDst.StripNubs(out pcnub); EXPRCLASS pDestinationTypeExpr = GetExprFactory().MakeClass(cType); int pcnub2; CType cType2 = _typeSrc.StripNubs(out pcnub2); ConversionFunc conversionFunc = ((_flags & CONVERTTYPE.ISEXPLICIT) != 0) ? new ConversionFunc(_binder.BindExplicitConversion) : new ConversionFunc(_binder.BindImplicitConversion); if (pcnub2 == 0) { if (_typeSrc.IsNullType()) { if (_needsExprDest) { if (_exprSrc.isCONSTANT_OK()) _exprDest = GetExprFactory().CreateZeroInit(nubDst); else _exprDest = GetExprFactory().CreateCast((EXPRFLAG)0, _typeDest, _exprSrc); } return true; } EXPR ppDestinationExpr = _exprSrc; if (_typeSrc == cType || conversionFunc(_exprSrc, _typeSrc, pDestinationTypeExpr, nubDst, _needsExprDest, out ppDestinationExpr, _flags | CONVERTTYPE.NOUDC)) { if (_needsExprDest) { EXPRUSERDEFINEDCONVERSION eXPRUSERDEFINEDCONVERSION = (ppDestinationExpr.kind == ExpressionKind.EK_USERDEFINEDCONVERSION) ? ppDestinationExpr.asUSERDEFINEDCONVERSION() : null; if (eXPRUSERDEFINEDCONVERSION != null) ppDestinationExpr = eXPRUSERDEFINEDCONVERSION.UserDefinedCall; for (int i = 0; i < pcnub; i++) { ppDestinationExpr = _binder.BindNubNew(ppDestinationExpr); ppDestinationExpr.asCALL().nubLiftKind = NullableCallLiftKind.NullableConversionConstructor; } if (eXPRUSERDEFINEDCONVERSION != null) { eXPRUSERDEFINEDCONVERSION.UserDefinedCall = ppDestinationExpr; eXPRUSERDEFINEDCONVERSION.setType(ppDestinationExpr.type); ppDestinationExpr = eXPRUSERDEFINEDCONVERSION; } _exprDest = ppDestinationExpr; } return true; } if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0) return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, (_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0); return false; } if (cType2 != cType && !conversionFunc(null, cType2, pDestinationTypeExpr, nubDst, false, out _exprDest, _flags | CONVERTTYPE.NOUDC)) { if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0) return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, (_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0); return false; } if (_needsExprDest) { MethWithInst mwi = new MethWithInst(null, null); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, mwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, nubDst, _exprSrc, pMemberGroup, null); EXPR ppDestinationExpr2 = _binder.mustCast(_exprSrc, cType2); EXPRCLASS pDestinationTypeExpr2 = GetExprFactory().MakeClass(cType); if (!(((_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0) ? _binder.BindImplicitConversion(ppDestinationExpr2, ppDestinationExpr2.type, pDestinationTypeExpr2, cType, out ppDestinationExpr2, _flags | CONVERTTYPE.NOUDC) : _binder.BindExplicitConversion(ppDestinationExpr2, ppDestinationExpr2.type, pDestinationTypeExpr2, cType, out ppDestinationExpr2, _flags | CONVERTTYPE.NOUDC))) { VSFAIL("bind(Im|Ex)plicitConversion failed unexpectedly"); return false; } eXPRCALL.castOfNonLiftedResultToLiftedType = _binder.mustCast(ppDestinationExpr2, nubDst, (CONVERTTYPE)0); eXPRCALL.nubLiftKind = NullableCallLiftKind.NullableConversion; eXPRCALL.pConversions = eXPRCALL.castOfNonLiftedResultToLiftedType; _exprDest = eXPRCALL; } return true; } private bool bindImplicitConversionFromNull() { switch (_typeDest.fundType()) { case FUNDTYPE.FT_VAR: if (_typeDest.AsTypeParameterType().IsReferenceType()) break; goto default; default: if (!_typeDest.isPredefType(PredefinedType.PT_G_OPTIONAL)) return false; break; case FUNDTYPE.FT_REF: case FUNDTYPE.FT_PTR: break; } if (_needsExprDest) { if (_exprSrc.isCONSTANT_OK()) _exprDest = GetExprFactory().CreateZeroInit(_typeDest); else _exprDest = GetExprFactory().CreateCast((EXPRFLAG)0, _typeDest, _exprSrc); } return true; } private bool bindImplicitConversionFromNullable(NullableType nubSrc) { AggregateType ats = nubSrc.GetAts(GetErrorContext()); if (ats == null) return false; if (ats == _typeDest) { if (_needsExprDest) _exprDest = _exprSrc; return true; } if (GetSymbolLoader().HasBaseConversion(nubSrc.GetUnderlyingType(), _typeDest) && !CConversions.FUnwrappingConv(nubSrc, _typeDest)) { if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_CTOR); if (!_typeDest.isPredefType(PredefinedType.PT_OBJECT)) _binder.bindSimpleCast(_exprDest, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_ASFINALLYLEAVE); } return true; } if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0) return _binder.bindUserDefinedConversion(_exprSrc, nubSrc, _typeDest, _needsExprDest, out _exprDest, true); return false; } private bool bindImplicitConversionFromArray() { if (!GetSymbolLoader().HasBaseConversion(_typeSrc, _typeDest)) return false; EXPRFLAG exprFlags = (EXPRFLAG)0; if ((_typeDest.IsArrayType() || (_typeDest.isInterfaceType() && _typeDest.AsAggregateType().GetTypeArgsAll().Size == 1 && (_typeDest.AsAggregateType().GetTypeArgsAll().Item(0) != _typeSrc.AsArrayType().GetElementType() || (_flags & CONVERTTYPE.FORCECAST) != 0))) && ((_flags & CONVERTTYPE.FORCECAST) != 0 || TypeManager.TypeContainsTyVars(_typeSrc, null) || TypeManager.TypeContainsTyVars(_typeDest, null))) exprFlags = EXPRFLAG.EXF_OPERATOR; if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, exprFlags); return true; } private bool bindImplicitConversionFromPointer() { if (_typeDest.IsPointerType() && _typeDest.AsPointerType().GetReferentType() == _binder.getVoidType()) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); return true; } return false; } private bool bindImplicitConversionFromAgg(AggregateType aggTypeSrc) { AggregateSymbol aggregate = aggTypeSrc.getAggregate(); if (aggregate.IsEnum()) return bindImplicitConversionFromEnum(aggTypeSrc); if (_typeDest.isEnumType()) { if (bindImplicitConversionToEnum(aggTypeSrc)) return true; } else if (aggregate.getThisType().isSimpleType() && _typeDest.isSimpleType() && bindImplicitConversionBetweenSimpleTypes(aggTypeSrc)) { return true; } return bindImplicitConversionToBase(aggTypeSrc); } private bool bindImplicitConversionToBase(AggregateType pSource) { if (!_typeDest.IsAggregateType() || !GetSymbolLoader().HasBaseConversion(pSource, _typeDest)) return false; EXPRFLAG exprFlags = (EXPRFLAG)0; if (pSource.getAggregate().IsStruct() && _typeDest.fundType() == FUNDTYPE.FT_REF) exprFlags = (EXPRFLAG)131074; else if (_exprSrc != null) { exprFlags = (_exprSrc.flags & EXPRFLAG.EXF_CANTBENULL); } if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, exprFlags); return true; } private bool bindImplicitConversionFromEnum(AggregateType aggTypeSrc) { if (_typeDest.IsAggregateType() && GetSymbolLoader().HasBaseConversion(aggTypeSrc, _typeDest.AsAggregateType())) { if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, (EXPRFLAG)131074); return true; } return false; } private bool bindImplicitConversionToEnum(AggregateType aggTypeSrc) { if (aggTypeSrc.getAggregate().GetPredefType() != PredefinedType.PT_BOOL && _exprSrc != null && _exprSrc.isZero() && _exprSrc.type.isNumericType() && (_flags & CONVERTTYPE.STANDARD) == (CONVERTTYPE)0) { if (_needsExprDest) _exprDest = GetExprFactory().CreateConstant(_typeDest, ConstValFactory.GetDefaultValue(_typeDest.constValKind())); return true; } return false; } private bool bindImplicitConversionBetweenSimpleTypes(AggregateType aggTypeSrc) { AggregateSymbol aggregate = aggTypeSrc.getAggregate(); PredefinedType predefType = aggregate.GetPredefType(); PredefinedType predefType2 = _typeDest.getPredefType(); bool flag = false; ConvKind convKind; if (_exprSrc == null || !_exprSrc.isCONSTANT_OK() || ((predefType != PredefinedType.PT_INT || predefType2 == PredefinedType.PT_BOOL || predefType2 == PredefinedType.PT_CHAR) && (predefType != PredefinedType.PT_LONG || predefType2 != PredefinedType.PT_ULONG)) || !isConstantInRange(_exprSrc.asCONSTANT(), _typeDest)) convKind = ((predefType != predefType2) ? GetConvKind(predefType, predefType2) : ConvKind.Implicit); else { convKind = ConvKind.Implicit; flag = (_needsExprDest && GetConvKind(predefType, predefType2) != ConvKind.Implicit); } if (convKind != ConvKind.Implicit) return false; if (_exprSrc.GetConst() != null && _binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, false) == ConstCastResult.Success) return true; if (isUserDefinedConversion(predefType, predefType2)) { if (!_needsExprDest) return true; return _binder.bindUserDefinedConversion(_exprSrc, aggTypeSrc, _typeDest, _needsExprDest, out _exprDest, true); } if (_needsExprDest) _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); return true; } private bool bindImplicitConversionFromTypeVar(TypeParameterType tyVarSrc) { CType cType = tyVarSrc.GetEffectiveBaseClass(); TypeArray bounds = tyVarSrc.GetBounds(); int num = -1; while (!_binder.canConvert(cType, _typeDest, _flags | CONVERTTYPE.NOUDC)) { do { if (++num >= bounds.Size) return false; cType = bounds.Item(num); } while (!cType.isInterfaceType() && !cType.IsTypeParameterType()); } if (!_needsExprDest) return true; if (_typeDest.IsTypeParameterType()) { EXPRCLASS exprTypeDest = GetExprFactory().MakeClass(_binder.GetReqPDT(PredefinedType.PT_OBJECT)); _binder.bindSimpleCast(_exprSrc, exprTypeDest, out EXPR pexprDest, EXPRFLAG.EXF_UNREALIZEDGOTO); _binder.bindSimpleCast(pexprDest, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_ASFINALLYLEAVE); } else _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_UNREALIZEDGOTO); return true; } private SymbolLoader GetSymbolLoader() { return _binder.GetSymbolLoader(); } private ExprFactory GetExprFactory() { return _binder.GetExprFactory(); } private ErrorHandling GetErrorContext() { return _binder.GetErrorContext(); } } protected class UnaOpSig { public PredefinedType pt; public UnaOpMask grfuom; public int cuosSkip; public PfnBindUnaOp pfn; public UnaOpFuncKind fnkind; public UnaOpSig() { } public UnaOpSig(PredefinedType pt, UnaOpMask grfuom, int cuosSkip, PfnBindUnaOp pfn, UnaOpFuncKind fnkind) { this.pt = pt; this.grfuom = grfuom; this.cuosSkip = cuosSkip; this.pfn = pfn; this.fnkind = fnkind; } } protected class UnaOpFullSig : UnaOpSig { private LiftFlags _grflt; private CType _type; public UnaOpFullSig(CType type, PfnBindUnaOp pfn, LiftFlags grflt, UnaOpFuncKind fnkind) { pt = PredefinedType.PT_UNDEFINEDINDEX; grfuom = UnaOpMask.None; cuosSkip = 0; base.pfn = pfn; _type = type; _grflt = grflt; base.fnkind = fnkind; } public UnaOpFullSig(ExpressionBinder fnc, UnaOpSig uos) { pt = uos.pt; grfuom = uos.grfuom; cuosSkip = uos.cuosSkip; pfn = uos.pfn; fnkind = uos.fnkind; _type = ((pt != PredefinedType.PT_UNDEFINEDINDEX) ? fnc.GetOptPDT(pt) : null); _grflt = LiftFlags.None; } public bool FPreDef() { return pt != PredefinedType.PT_UNDEFINEDINDEX; } public bool isLifted() { if (_grflt == LiftFlags.None) return false; return true; } public bool Convert() { return (_grflt & LiftFlags.Convert1) != LiftFlags.None; } public new CType GetType() { return _type; } } private static readonly byte[][] s_betterConversionTable = new byte[16][] { new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 }, new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, new byte[16], new byte[16], new byte[16], new byte[16], new byte[16], new byte[16] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, new byte[16] { 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, new byte[16] { 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, new byte[16] { 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, new byte[16], new byte[16], new byte[16] }; private static readonly ErrorCode[] s_ReadOnlyLocalErrors = new ErrorCode[2] { ErrorCode.ERR_RefReadonlyLocal, ErrorCode.ERR_AssgReadonlyLocal }; private static readonly ErrorCode[] s_ReadOnlyErrors = new ErrorCode[8] { ErrorCode.ERR_RefReadonly, ErrorCode.ERR_AssgReadonly, ErrorCode.ERR_RefReadonlyStatic, ErrorCode.ERR_AssgReadonlyStatic, ErrorCode.ERR_RefReadonly2, ErrorCode.ERR_AssgReadonly2, ErrorCode.ERR_RefReadonlyStatic2, ErrorCode.ERR_AssgReadonlyStatic2 }; private const byte ID = 1; private const byte IMP = 2; private const byte EXP = 3; private const byte NO = 5; private const byte CONV_KIND_MASK = 15; private const byte UDC = 64; private const byte XUD = 67; private const byte IUD = 66; private static readonly byte[][] s_simpleTypeConversions = new byte[13][] { new byte[13] { 1, 2, 2, 2, 2, 2, 66, 3, 5, 3, 2, 2, 2 }, new byte[13] { 3, 1, 2, 2, 2, 2, 66, 3, 5, 3, 3, 3, 3 }, new byte[13] { 3, 3, 1, 2, 2, 2, 66, 3, 5, 3, 3, 3, 3 }, new byte[13] { 3, 3, 3, 1, 2, 2, 66, 3, 5, 3, 3, 3, 3 }, new byte[13] { 3, 3, 3, 3, 1, 2, 67, 3, 5, 3, 3, 3, 3 }, new byte[13] { 3, 3, 3, 3, 3, 1, 67, 3, 5, 3, 3, 3, 3 }, new byte[13] { 67, 67, 67, 67, 67, 67, 1, 67, 5, 67, 67, 67, 67 }, new byte[13] { 3, 3, 2, 2, 2, 2, 66, 1, 5, 3, 2, 2, 2 }, new byte[13] { 5, 5, 5, 5, 5, 5, 5, 5, 1, 5, 5, 5, 5 }, new byte[13] { 3, 2, 2, 2, 2, 2, 66, 3, 5, 1, 3, 3, 3 }, new byte[13] { 3, 3, 2, 2, 2, 2, 66, 3, 5, 3, 1, 2, 2 }, new byte[13] { 3, 3, 3, 2, 2, 2, 66, 3, 5, 3, 3, 1, 2 }, new byte[13] { 3, 3, 3, 3, 2, 2, 66, 3, 5, 3, 3, 3, 1 } }; private const int NUM_SIMPLE_TYPES = 13; private const int NUM_EXT_TYPES = 16; private const byte same = 0; private const byte left = 1; private const byte right = 2; private const byte neither = 3; private static readonly byte[][] s_simpleTypeBetter = new byte[16][] { new byte[16] { 0, 1, 1, 1, 1, 1, 1, 3, 3, 2, 1, 1, 1, 3, 3, 1 }, new byte[16] { 2, 0, 1, 1, 1, 1, 1, 3, 3, 2, 1, 1, 1, 3, 3, 1 }, new byte[16] { 2, 2, 0, 1, 1, 1, 1, 2, 3, 2, 2, 1, 1, 3, 3, 1 }, new byte[16] { 2, 2, 2, 0, 1, 1, 1, 2, 3, 2, 2, 2, 1, 3, 3, 1 }, new byte[16] { 2, 2, 2, 2, 0, 1, 3, 2, 3, 2, 2, 2, 2, 3, 3, 1 }, new byte[16] { 2, 2, 2, 2, 2, 0, 3, 2, 3, 2, 2, 2, 2, 3, 3, 1 }, new byte[16] { 2, 2, 2, 2, 3, 3, 0, 2, 3, 2, 2, 2, 2, 3, 3, 1 }, new byte[16] { 3, 3, 1, 1, 1, 1, 1, 0, 3, 3, 1, 1, 1, 3, 3, 1 }, new byte[16] { 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 1 }, new byte[16] { 1, 1, 1, 1, 1, 1, 1, 3, 3, 0, 1, 1, 1, 3, 3, 1 }, new byte[16] { 2, 2, 1, 1, 1, 1, 1, 2, 3, 2, 0, 1, 1, 3, 3, 1 }, new byte[16] { 2, 2, 2, 1, 1, 1, 1, 2, 3, 2, 2, 0, 1, 3, 3, 1 }, new byte[16] { 2, 2, 2, 2, 1, 1, 1, 2, 3, 2, 2, 2, 0, 3, 3, 1 }, new byte[16] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 1 }, new byte[16] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1 }, new byte[16] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 } }; protected BindingContext Context; protected CNullable m_nullable; private static readonly PredefinedType[] s_rgptIntOp = new PredefinedType[4] { PredefinedType.PT_INT, PredefinedType.PT_UINT, PredefinedType.PT_LONG, PredefinedType.PT_ULONG }; private static readonly PredefinedName[] s_EK2NAME = new PredefinedName[26] { PredefinedName.PN_OPEQUALS, PredefinedName.PN_OPCOMPARE, PredefinedName.PN_OPTRUE, PredefinedName.PN_OPFALSE, PredefinedName.PN_OPINCREMENT, PredefinedName.PN_OPDECREMENT, PredefinedName.PN_OPNEGATION, PredefinedName.PN_OPEQUALITY, PredefinedName.PN_OPINEQUALITY, PredefinedName.PN_OPLESSTHAN, PredefinedName.PN_OPLESSTHANOREQUAL, PredefinedName.PN_OPGREATERTHAN, PredefinedName.PN_OPGREATERTHANOREQUAL, PredefinedName.PN_OPPLUS, PredefinedName.PN_OPMINUS, PredefinedName.PN_OPMULTIPLY, PredefinedName.PN_OPDIVISION, PredefinedName.PN_OPMODULUS, PredefinedName.PN_OPUNARYMINUS, PredefinedName.PN_OPUNARYPLUS, PredefinedName.PN_OPBITWISEAND, PredefinedName.PN_OPBITWISEOR, PredefinedName.PN_OPXOR, PredefinedName.PN_OPCOMPLEMENT, PredefinedName.PN_OPLEFTSHIFT, PredefinedName.PN_OPRIGHTSHIFT }; protected readonly BinOpSig[] g_binopSignatures; protected readonly UnaOpSig[] g_rguos; protected SymbolLoader SymbolLoader => Context.SymbolLoader; protected CSemanticChecker SemanticChecker => Context.SemanticChecker; private ErrorHandling ErrorContext => SymbolLoader.ErrorContext; protected TypeManager TypeManager => SymbolLoader.TypeManager; private ExprFactory ExprFactory => Context.GetExprFactory(); protected CType VoidType => GetSymbolLoader().GetTypeManager().GetVoid(); protected BetterType WhichMethodIsBetterTieBreaker(CandidateFunctionMember node1, CandidateFunctionMember node2, CType pTypeThrough, ArgInfos args) { MethPropWithInst mpwi = node1.mpwi; MethPropWithInst mpwi2 = node2.mpwi; if (node1.ctypeLift != node2.ctypeLift) { if (node1.ctypeLift >= node2.ctypeLift) return BetterType.Right; return BetterType.Left; } if (mpwi.TypeArgs.size != 0) { if (mpwi2.TypeArgs.size == 0) return BetterType.Right; } else if (mpwi2.TypeArgs.size != 0) { return BetterType.Left; } if (node1.fExpanded) { if (!node2.fExpanded) return BetterType.Right; } else if (node2.fExpanded) { return BetterType.Left; } BetterType betterType = GetGlobalSymbols().CompareTypes(RearrangeNamedArguments(mpwi.MethProp().Params, mpwi, pTypeThrough, args), RearrangeNamedArguments(mpwi2.MethProp().Params, mpwi2, pTypeThrough, args)); if (betterType == BetterType.Left || betterType == BetterType.Right) return betterType; if (mpwi.MethProp().modOptCount != mpwi2.MethProp().modOptCount) { if (mpwi.MethProp().modOptCount >= mpwi2.MethProp().modOptCount) return BetterType.Right; return BetterType.Left; } return BetterType.Neither; } private static int FindName(List<Name> names, Name name) { return names.IndexOf(name); } private TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst mpwi, CType pTypeThrough, ArgInfos args) { if (!args.fHasExprs) return pta; CType pType = (pTypeThrough != null) ? pTypeThrough : mpwi.GetType(); CType[] array = new CType[pta.size]; MethodOrPropertySymbol methodOrPropertySymbol = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi.MethProp(), pType); for (int i = 0; i < pta.size; i++) { array[i] = pta.Item(i); } for (int j = 0; j < args.carg; j++) { EXPR expr = args.prgexpr[j]; if (expr.isNamedArgumentSpecification()) { int num = FindName(methodOrPropertySymbol.ParameterNames, expr.asNamedArgumentSpecification().Name); CType cType = pta.Item(num); for (int k = j; k < num; k++) { array[k + 1] = array[k]; } array[j] = cType; } } return GetSymbolLoader().getBSymmgr().AllocParams(pta.size, array); } protected BetterType WhichMethodIsBetter(CandidateFunctionMember node1, CandidateFunctionMember node2, CType pTypeThrough, ArgInfos args) { MethPropWithInst mpwi = node1.mpwi; MethPropWithInst mpwi2 = node2.mpwi; TypeArray typeArray = RearrangeNamedArguments(node1.params, mpwi, pTypeThrough, args); TypeArray typeArray2 = RearrangeNamedArguments(node2.params, mpwi2, pTypeThrough, args); if (typeArray == typeArray2) return WhichMethodIsBetterTieBreaker(node1, node2, pTypeThrough, args); BetterType betterType = BetterType.Neither; CType pType = (pTypeThrough != null) ? pTypeThrough : mpwi.GetType(); CType pType2 = (pTypeThrough != null) ? pTypeThrough : mpwi2.GetType(); MethodOrPropertySymbol methodOrPropertySymbol = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi.MethProp(), pType); MethodOrPropertySymbol methodOrPropertySymbol2 = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi2.MethProp(), pType2); List<Name> parameterNames = methodOrPropertySymbol.ParameterNames; List<Name> parameterNames2 = methodOrPropertySymbol2.ParameterNames; for (int i = 0; i < args.carg; i++) { EXPR eXPR = args.fHasExprs ? args.prgexpr[i] : null; CType argType = args.types.Item(i); CType p = typeArray.Item(i); CType p2 = typeArray2.Item(i); if (eXPR.RuntimeObjectActualType != null) argType = eXPR.RuntimeObjectActualType; BetterType betterType2 = WhichConversionIsBetter(eXPR, argType, p, p2); if (betterType == BetterType.Right && betterType2 == BetterType.Left) { betterType = BetterType.Neither; break; } if (betterType == BetterType.Left && betterType2 == BetterType.Right) { betterType = BetterType.Neither; break; } if (betterType == BetterType.Neither && (betterType2 == BetterType.Right || betterType2 == BetterType.Left)) betterType = betterType2; } if (typeArray.size != typeArray2.size && betterType == BetterType.Neither) { if (node1.fExpanded && !node2.fExpanded) return BetterType.Right; if (node2.fExpanded && !node1.fExpanded) return BetterType.Left; if (typeArray.size == args.carg) return BetterType.Left; if (typeArray2.size == args.carg) return BetterType.Right; return BetterType.Neither; } return betterType; } protected BetterType WhichConversionIsBetter(EXPR arg, CType argType, CType p1, CType p2) { if (p1 == p2) return BetterType.Same; return WhichConversionIsBetter(argType, p1, p2); } public BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2) { if (p1 == p2) return BetterType.Same; if (argType == p1) return BetterType.Left; if (argType == p2) return BetterType.Right; bool flag = canConvert(p1, p2); bool flag2 = canConvert(p2, p1); if (flag && !flag2) return BetterType.Left; if (flag2 && !flag) return BetterType.Right; if (p1.isPredefined() && p2.isPredefined() && p1.getPredefType() <= PredefinedType.PT_OBJECT && p2.getPredefType() <= PredefinedType.PT_OBJECT) { switch (s_betterConversionTable[(uint)p1.getPredefType()][(uint)p2.getPredefType()]) { case 1: return BetterType.Left; case 2: return BetterType.Right; } } return BetterType.Neither; } protected CandidateFunctionMember FindBestMethod(List<CandidateFunctionMember> list, CType pTypeThrough, ArgInfos args, out CandidateFunctionMember methAmbig1, out CandidateFunctionMember methAmbig2) { CandidateFunctionMember candidateFunctionMember = null; CandidateFunctionMember candidateFunctionMember2 = null; bool flag = false; CandidateFunctionMember candidateFunctionMember3 = list[0]; for (int i = 1; i < list.Count; i++) { CandidateFunctionMember candidateFunctionMember4 = list[i]; switch (WhichMethodIsBetter(candidateFunctionMember3, candidateFunctionMember4, pTypeThrough, args)) { case BetterType.Left: flag = false; break; case BetterType.Right: flag = false; candidateFunctionMember3 = candidateFunctionMember4; break; default: candidateFunctionMember = candidateFunctionMember3; candidateFunctionMember2 = candidateFunctionMember4; i++; if (i < list.Count) { candidateFunctionMember4 = list[i]; candidateFunctionMember3 = candidateFunctionMember4; } else flag = true; break; } } if (!flag) { foreach (CandidateFunctionMember item in list) { if (item != candidateFunctionMember3) { switch (WhichMethodIsBetter(item, candidateFunctionMember3, pTypeThrough, args)) { case BetterType.Same: case BetterType.Neither: candidateFunctionMember = candidateFunctionMember3; candidateFunctionMember2 = item; break; case BetterType.Right: continue; } break; } methAmbig1 = null; methAmbig2 = null; return candidateFunctionMember3; } } if (candidateFunctionMember != null && candidateFunctionMember2 != null) { methAmbig1 = candidateFunctionMember; methAmbig2 = candidateFunctionMember2; } else { methAmbig1 = list.First(); methAmbig2 = list.Skip(1).First(); } return null; } protected void ReportLocalError(LocalVariableSymbol local, CheckLvalueKind kind, bool isNested) { int num = (kind != CheckLvalueKind.OutParameter) ? 1 : 0; ErrorCode id = s_ReadOnlyLocalErrors[num]; ErrorContext.Error(id, local.name); } protected void ReportReadOnlyError(EXPRFIELD field, CheckLvalueKind kind, bool isNested) { bool isStatic = field.fwt.Field().isStatic; int num = (isNested ? 4 : 0) + (isStatic ? 2 : 0) + ((kind != CheckLvalueKind.OutParameter) ? 1 : 0); ErrorCode id = s_ReadOnlyErrors[num]; if (isNested) ErrorContext.Error(id, field.fwt); else ErrorContext.Error(id, Array.Empty<ErrArg>()); } protected bool TryReportLvalueFailure(EXPR expr, CheckLvalueKind kind) { bool flag = false; EXPR expr2 = expr; while (true) { if (expr2.isANYLOCAL_OK()) { ReportLocalError(expr2.asANYLOCAL().local, kind, flag); return true; } EXPR eXPR = null; if (expr2.isPROP()) eXPR = expr2.asPROP().GetMemberGroup().GetOptionalObject(); else if (expr2.isFIELD()) { EXPRFIELD eXPRFIELD = expr2.asFIELD(); if (eXPRFIELD.fwt.Field().isReadOnly) { ReportReadOnlyError(eXPRFIELD, kind, flag); return true; } if (!eXPRFIELD.fwt.Field().isStatic) eXPR = eXPRFIELD.GetOptionalObject(); } if (eXPR != null && eXPR.type.isStructOrEnum()) { if (eXPR.isCALL() || eXPR.isPROP()) { ErrorContext.Error(ErrorCode.ERR_ReturnNotLValue, eXPR.GetSymWithType()); return true; } if (eXPR.isCAST()) { eXPR.flags |= EXPRFLAG.EXF_USERCALLABLE; return false; } } if (eXPR == null || eXPR.isLvalue() || (!expr2.isFIELD() && (flag || !expr2.isPROP()))) break; expr2 = eXPR; flag = true; } ErrorContext.Error(GetStandardLvalueError(kind), Array.Empty<ErrArg>()); return true; } public static void ReportTypeArgsNotAllowedError(SymbolLoader symbolLoader, int arity, ErrArgRef argName, ErrArgRef argKind) { symbolLoader.ErrorContext.ErrorRef(ErrorCode.ERR_TypeArgsNotAllowed, argName, argKind); } private static void RoundToFloat(double d, out float f) { f = (float)d; } private static long I64(long x) { return x; } private static long I64(ulong x) { return (long)x; } private static void RETAILVERIFY(bool b) { if (!b) throw Error.InternalCompilerError(); } private static ConvKind GetConvKind(PredefinedType ptSrc, PredefinedType ptDst) { if ((int)ptSrc < 13 && (int)ptDst < 13) return (ConvKind)(s_simpleTypeConversions[(uint)ptSrc][(uint)ptDst] & 15); if (ptSrc == ptDst || (ptDst == PredefinedType.PT_OBJECT && ptSrc < PredefinedType.PT_COUNT)) return ConvKind.Implicit; if (ptSrc == PredefinedType.PT_OBJECT && ptDst < PredefinedType.PT_COUNT) return ConvKind.Explicit; return ConvKind.Unknown; } private static bool isUserDefinedConversion(PredefinedType ptSrc, PredefinedType ptDst) { if ((int)ptSrc < 13 && (int)ptDst < 13) return (s_simpleTypeConversions[(uint)ptSrc][(uint)ptDst] & 64) != 0; return false; } private BetterType WhichSimpleConversionIsBetter(PredefinedType pt1, PredefinedType pt2) { RETAILVERIFY((int)pt1 < 16); RETAILVERIFY((int)pt2 < 16); return (BetterType)s_simpleTypeBetter[(uint)pt1][(uint)pt2]; } private BetterType WhichTypeIsBetter(PredefinedType pt1, PredefinedType pt2, CType typeGiven) { if (pt1 == pt2) return BetterType.Same; if (typeGiven.isPredefType(pt1)) return BetterType.Left; if (typeGiven.isPredefType(pt2)) return BetterType.Right; if ((int)pt1 <= 16 && (int)pt2 <= 16) return WhichSimpleConversionIsBetter(pt1, pt2); if (pt2 == PredefinedType.PT_OBJECT && pt1 < PredefinedType.PT_COUNT) return BetterType.Left; if (pt1 == PredefinedType.PT_OBJECT && pt2 < PredefinedType.PT_COUNT) return BetterType.Right; return WhichTypeIsBetter(GetOptPDT(pt1), GetOptPDT(pt2), typeGiven); } private BetterType WhichTypeIsBetter(CType type1, CType type2, CType typeGiven) { if (type1 == type2) return BetterType.Same; if (typeGiven == type1) return BetterType.Left; if (typeGiven == type2) return BetterType.Right; bool flag = canConvert(type1, type2); bool flag2 = canConvert(type2, type1); if (flag != flag2) { if (!flag) return BetterType.Right; return BetterType.Left; } if (!type1.IsNullableType() || !type2.IsNullableType() || !type1.AsNullableType().UnderlyingType.isPredefined() || !type2.AsNullableType().UnderlyingType.isPredefined()) return BetterType.Neither; PredefinedType predefType = (type1 as NullableType).UnderlyingType.getPredefType(); PredefinedType predefType2 = (type2 as NullableType).UnderlyingType.getPredefType(); if ((int)predefType <= 16 && (int)predefType2 <= 16) return WhichSimpleConversionIsBetter(predefType, predefType2); return BetterType.Neither; } public bool canConvert(CType src, CType dest, CONVERTTYPE flags) { EXPRCLASS pDestinationTypeExpr = ExprFactory.MakeClass(dest); return BindImplicitConversion(null, src, pDestinationTypeExpr, dest, flags); } public bool canConvert(CType src, CType dest) { return canConvert(src, dest, (CONVERTTYPE)0); } public bool canConvert(EXPR expr, CType dest) { return canConvert(expr, dest, (CONVERTTYPE)0); } public bool canConvert(EXPR expr, CType dest, CONVERTTYPE flags) { EXPRCLASS pDestinationTypeExpr = ExprFactory.MakeClass(dest); return BindImplicitConversion(expr, expr.type, pDestinationTypeExpr, dest, flags); } public EXPR mustConvertCore(EXPR expr, EXPRTYPEORNAMESPACE destExpr) { return mustConvertCore(expr, destExpr, (CONVERTTYPE)0); } public EXPR mustConvertCore(EXPR expr, EXPRTYPEORNAMESPACE destExpr, CONVERTTYPE flags) { CType cType = destExpr.TypeOrNamespace as CType; if (BindImplicitConversion(expr, expr.type, destExpr, cType, out EXPR ppDestinationExpr, flags)) { checkUnsafe(expr.type); checkUnsafe(cType); return ppDestinationExpr; } if (expr.isOK() && !cType.IsErrorType()) { FUNDTYPE fUNDTYPE = expr.type.fundType(); FUNDTYPE fUNDTYPE2 = cType.fundType(); if (expr.isCONSTANT_OK() && expr.type.isSimpleType() && cType.isSimpleType()) { if ((fUNDTYPE == FUNDTYPE.FT_I4 && (fUNDTYPE2 <= FUNDTYPE.FT_U4 || fUNDTYPE2 == FUNDTYPE.FT_U8)) || (fUNDTYPE == FUNDTYPE.FT_I8 && fUNDTYPE2 == FUNDTYPE.FT_U8)) { string psz = expr.asCONSTANT().I64Value.ToString(CultureInfo.InvariantCulture); ErrorContext.Error(ErrorCode.ERR_ConstOutOfRange, psz, cType); ppDestinationExpr = ExprFactory.CreateCast((EXPRFLAG)0, destExpr, expr); ppDestinationExpr.SetError(); return ppDestinationExpr; } if (fUNDTYPE == FUNDTYPE.FT_R8 && (expr.flags & EXPRFLAG.EXF_LITERALCONST) != 0 && (cType.isPredefType(PredefinedType.PT_FLOAT) || cType.isPredefType(PredefinedType.PT_DECIMAL))) { ErrorContext.Error(ErrorCode.ERR_LiteralDoubleCast, cType.isPredefType(PredefinedType.PT_DECIMAL) ? "M" : "F", cType); ppDestinationExpr = ExprFactory.CreateCast((EXPRFLAG)0, destExpr, expr); ppDestinationExpr.SetError(); return ppDestinationExpr; } } if (expr.type is NullType && cType.fundType() != FUNDTYPE.FT_REF) ErrorContext.Error((cType is TypeParameterType) ? ErrorCode.ERR_TypeVarCantBeNull : ErrorCode.ERR_ValueCantBeNull, cType); else if (expr.isMEMGRP()) { BindGrpConversion(expr.asMEMGRP(), cType, true); } else if (!TypeManager.TypeContainsAnonymousTypes(cType) && canCast(expr.type, cType, flags)) { ErrorContext.Error(ErrorCode.ERR_NoImplicitConvCast, new ErrArg(expr.type, ErrArgFlags.Unique), new ErrArg(cType, ErrArgFlags.Unique)); } else { ErrorContext.Error(ErrorCode.ERR_NoImplicitConv, new ErrArg(expr.type, ErrArgFlags.Unique), new ErrArg(cType, ErrArgFlags.Unique)); } } ppDestinationExpr = ExprFactory.CreateCast((EXPRFLAG)0, destExpr, expr); ppDestinationExpr.SetError(); return ppDestinationExpr; } public EXPR tryConvert(EXPR expr, CType dest) { return tryConvert(expr, dest, (CONVERTTYPE)0); } public EXPR tryConvert(EXPR expr, CType dest, CONVERTTYPE flags) { EXPRCLASS pDestinationTypeExpr = ExprFactory.MakeClass(dest); if (BindImplicitConversion(expr, expr.type, pDestinationTypeExpr, dest, out EXPR ppDestinationExpr, flags)) { checkUnsafe(expr.type); checkUnsafe(dest); return ppDestinationExpr; } return null; } public EXPR mustConvert(EXPR expr, CType dest) { return mustConvert(expr, dest, (CONVERTTYPE)0); } public EXPR mustConvert(EXPR expr, CType dest, CONVERTTYPE flags) { EXPRCLASS dest2 = ExprFactory.MakeClass(dest); return mustConvert(expr, dest2, flags); } public EXPR mustConvert(EXPR expr, EXPRTYPEORNAMESPACE dest, CONVERTTYPE flags) { return mustConvertCore(expr, dest, flags); } private EXPR mustCastCore(EXPR expr, EXPRTYPEORNAMESPACE destExpr, CONVERTTYPE flags) { CType cType = destExpr.TypeOrNamespace as CType; SemanticChecker.CheckForStaticClass(null, cType, ErrorCode.ERR_ConvertToStaticClass); EXPR ppDestinationExpr; if (expr.isOK()) { if (BindExplicitConversion(expr, expr.type, destExpr, cType, out ppDestinationExpr, flags)) { checkUnsafe(expr.type); checkUnsafe(cType); return ppDestinationExpr; } if (cType != null && !(cType is ErrorType)) { string psz = ""; EXPR const = expr.GetConst(); FUNDTYPE fUNDTYPE = expr.type.fundType(); bool flag = const != null && expr.type.isSimpleOrEnum() && cType.isSimpleOrEnum(); if (flag && fUNDTYPE == FUNDTYPE.FT_STRUCT) ErrorContext.Error(ErrorCode.ERR_ConstOutOfRange, const.asCONSTANT().Val.decVal.ToString(CultureInfo.InvariantCulture), cType); else if (flag && Context.CheckedConstant) { if (!canExplicitConversionBeBoundInUncheckedContext(expr, expr.type, destExpr, flags | CONVERTTYPE.NOUDC)) CantConvert(expr, cType); else { if (fUNDTYPE <= FUNDTYPE.FT_U8) psz = ((!expr.type.isUnsigned()) ? const.asCONSTANT().I64Value.ToString(CultureInfo.InvariantCulture) : ((ulong)const.asCONSTANT().I64Value).ToString((IFormatProvider)CultureInfo.InvariantCulture)); else if (fUNDTYPE <= FUNDTYPE.FT_R8) { psz = const.asCONSTANT().Val.doubleVal.ToString(CultureInfo.InvariantCulture); } ErrorContext.Error(ErrorCode.ERR_ConstOutOfRangeChecked, psz, cType); } } else if (expr.type is NullType && cType.fundType() != FUNDTYPE.FT_REF) { ErrorContext.Error(ErrorCode.ERR_ValueCantBeNull, cType); } else if (expr.isMEMGRP()) { BindGrpConversion(expr.asMEMGRP(), cType, true); } else { CantConvert(expr, cType); } } } ppDestinationExpr = ExprFactory.CreateCast((EXPRFLAG)0, destExpr, expr); ppDestinationExpr.SetError(); return ppDestinationExpr; } private void CantConvert(EXPR expr, CType dest) { if (expr.type != null && !(expr.type is ErrorType)) ErrorContext.Error(ErrorCode.ERR_NoExplicitConv, new ErrArg(expr.type, ErrArgFlags.Unique), new ErrArg(dest, ErrArgFlags.Unique)); } public EXPR mustCast(EXPR expr, CType dest) { return mustCast(expr, dest, (CONVERTTYPE)0); } public EXPR mustCast(EXPR expr, CType dest, CONVERTTYPE flags) { EXPRCLASS destExpr = ExprFactory.MakeClass(dest); return mustCastCore(expr, destExpr, flags); } private EXPR mustCastInUncheckedContext(EXPR expr, CType dest, CONVERTTYPE flags) { CheckedContext context = CheckedContext.CreateInstance(Context, false, false); return new ExpressionBinder(context).mustCast(expr, dest, flags); } private bool canCast(CType src, CType dest, CONVERTTYPE flags) { EXPRCLASS pDestinationTypeExpr = ExprFactory.MakeClass(dest); return BindExplicitConversion(null, src, pDestinationTypeExpr, dest, flags); } public bool BindGrpConversion(EXPRMEMGRP grp, CType typeDst, bool fReportErrors) { EXPRCALL pexprDst; return BindGrpConversion(grp, typeDst, false, out pexprDst, fReportErrors); } public bool BindGrpConversion(EXPRMEMGRP grp, CType typeDst, bool needDest, out EXPRCALL pexprDst, bool fReportErrors) { pexprDst = null; if (!typeDst.isDelegateType()) { if (fReportErrors) ErrorContext.Error(ErrorCode.ERR_MethGrpToNonDel, grp.name, typeDst); return false; } AggregateType aggregateType = typeDst.AsAggregateType(); MethodSymbol methodSymbol = SymbolLoader.PredefinedMembers.FindDelegateConstructor(aggregateType.getAggregate(), fReportErrors); if (methodSymbol == null) return false; MethodSymbol methodSymbol2 = SymbolLoader.LookupInvokeMeth(aggregateType.getAggregate()); TypeArray args = GetTypes().SubstTypeArray(methodSymbol2.Params, aggregateType); CType cType = GetTypes().SubstType(methodSymbol2.RetType, aggregateType); if (!BindGrpConversionCore(out MethPropWithInst pmpwi, BindingFlag.BIND_NOPARAMS, grp, ref args, aggregateType, fReportErrors, out MethPropWithInst pmpwiAmbig)) return false; MethWithInst pMWI = new MethWithInst(pmpwi); MethWithInst methWithInst = new MethWithInst(pmpwiAmbig); bool flag = false; if (methodSymbol2.Params.Size < args.Size && pMWI.Meth().IsExtension()) { flag = true; TypeArray typeArray = GetTypes().SubstTypeArray(pMWI.Meth().Params, pMWI.GetType()); if (typeArray.Item(0).IsTypeParameterType() ? (!args.Item(0).IsRefType()) : (!typeArray.Item(0).IsRefType())) ErrorContext.Error(ErrorCode.ERR_ValueTypeExtDelegate, pMWI, typeArray.Item(0).IsTypeParameterType() ? args.Item(0) : typeArray.Item(0)); } if (!fReportErrors && !needDest) return true; bool flag2 = methWithInst; if ((bool)methWithInst && !fReportErrors) ErrorContext.Error(ErrorCode.ERR_AmbigCall, pMWI, methWithInst); CType cType2 = GetTypes().SubstType(pMWI.Meth().RetType, pMWI.Ats, pMWI.TypeArgs); if (cType != cType2 && !CConversions.FImpRefConv(GetSymbolLoader(), cType2, cType)) { ErrorContext.ErrorRef(ErrorCode.ERR_BadRetType, pMWI, cType2); flag2 = true; } TypeArray typeArray2 = GetTypes().SubstTypeArray(pMWI.Meth().Params, pMWI.Ats, pMWI.TypeArgs); if (typeArray2 != args) { for (int i = 0; i < typeArray2.Size; i++) { CType cType3 = args.Item(i); CType cType4 = typeArray2.Item(i); if (cType3 != cType4 && !CConversions.FImpRefConv(GetSymbolLoader(), cType3, cType4)) { ErrorContext.ErrorRef(ErrorCode.ERR_MethDelegateMismatch, pMWI, typeDst); flag2 = true; break; } } } EXPR pObject = (!flag) ? grp.GetOptionalObject() : null; PostBindMethod((grp.flags & EXPRFLAG.EXF_ASFINALLYLEAVE) != (EXPRFLAG)0, ref pMWI, pObject); pObject = AdjustMemberObject(pMWI, pObject, out bool _, out bool pIsMatchingStatic); if (!pIsMatchingStatic) grp.SetMismatchedStaticBit(); pObject = (flag ? grp.GetOptionalObject() : pObject); if (pMWI.TypeArgs.Size > 0) TypeBind.CheckMethConstraints(GetSemanticChecker(), GetErrorContext(), pMWI); if (pMWI.Meth().MethKind() == MethodKindEnum.Latent) ErrorContext.ErrorRef(ErrorCode.ERR_PartialMethodToDelegate, pMWI); if (!needDest) return true; EXPRFUNCPTR eXPRFUNCPTR = ExprFactory.CreateFunctionPointer(grp.flags & EXPRFLAG.EXF_ASFINALLYLEAVE, getVoidType(), null, pMWI); if (!pMWI.Meth().isStatic | flag) { if (pMWI.Meth().getClass().isPredefAgg(PredefinedType.PT_G_OPTIONAL)) ErrorContext.Error(ErrorCode.ERR_DelegateOnNullable, pMWI); eXPRFUNCPTR.SetOptionalObject(pObject); if (pObject != null && pObject.type.fundType() != FUNDTYPE.FT_REF) pObject = mustConvert(pObject, GetReqPDT(PredefinedType.PT_OBJECT)); } else { eXPRFUNCPTR.SetOptionalObject(null); pObject = ExprFactory.CreateNull(); } MethWithInst mWI = new MethWithInst(methodSymbol, aggregateType); grp.SetOptionalObject(null); EXPRCALL eXPRCALL = pexprDst = ExprFactory.CreateCall((EXPRFLAG)131088, aggregateType, ExprFactory.CreateList(pObject, eXPRFUNCPTR), grp, mWI); return true; } private bool BindGrpConversionCore(out MethPropWithInst pmpwi, BindingFlag bindFlags, EXPRMEMGRP grp, ref TypeArray args, AggregateType atsDelegate, bool fReportErrors, out MethPropWithInst pmpwiAmbig) { bool flag = false; int size = args.Size; ArgInfos argInfos = new ArgInfos(); argInfos.carg = args.Size; argInfos.types = args; argInfos.fHasExprs = false; GroupToArgsBinder groupToArgsBinder = new GroupToArgsBinder(this, bindFlags, grp, argInfos, null, false, atsDelegate); flag = groupToArgsBinder.Bind(fReportErrors); GroupToArgsBinderResult resultsOfBind = groupToArgsBinder.GetResultsOfBind(); pmpwi = resultsOfBind.GetBestResult(); pmpwiAmbig = resultsOfBind.GetAmbiguousResult(); return flag; } private bool canConvertInstanceParamForExtension(EXPR exprSrc, CType typeDest) { if (exprSrc == null || exprSrc.type == null) return false; return canConvertInstanceParamForExtension(exprSrc.type, typeDest); } private bool canConvertInstanceParamForExtension(CType typeSrc, CType typeDest) { if (!CConversions.FIsSameType(typeSrc, typeDest) && !CConversions.FImpRefConv(GetSymbolLoader(), typeSrc, typeDest)) return CConversions.FBoxingConv(GetSymbolLoader(), typeSrc, typeDest); return true; } private bool BindImplicitConversion(EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, CONVERTTYPE flags) { ImplicitConversion implicitConversion = new ImplicitConversion(this, pSourceExpr, pSourceType, pDestinationTypeExpr, false, flags); return implicitConversion.Bind(); } private bool BindImplicitConversion(EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, out EXPR ppDestinationExpr, CONVERTTYPE flags) { ImplicitConversion implicitConversion = new ImplicitConversion(this, pSourceExpr, pSourceType, pDestinationTypeExpr, true, flags); bool result = implicitConversion.Bind(); ppDestinationExpr = implicitConversion.ExprDest; return result; } private bool BindImplicitConversion(EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, out EXPR ppDestinationExpr, CONVERTTYPE flags) { ImplicitConversion implicitConversion = new ImplicitConversion(this, pSourceExpr, pSourceType, pDestinationTypeExpr, needsExprDest, flags); bool result = implicitConversion.Bind(); ppDestinationExpr = (needsExprDest ? implicitConversion.ExprDest : null); return result; } private bool BindExplicitConversion(EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, out EXPR ppDestinationExpr, CONVERTTYPE flags) { ExplicitConversion explicitConversion = new ExplicitConversion(this, pSourceExpr, pSourceType, pDestinationTypeExpr, pDestinationTypeForLambdaErrorReporting, needsExprDest, flags); bool result = explicitConversion.Bind(); ppDestinationExpr = (needsExprDest ? explicitConversion.ExprDest : null); return result; } private bool BindExplicitConversion(EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, out EXPR ppDestinationExpr, CONVERTTYPE flags) { ExplicitConversion explicitConversion = new ExplicitConversion(this, pSourceExpr, pSourceType, pDestinationTypeExpr, pDestinationTypeForLambdaErrorReporting, true, flags); bool result = explicitConversion.Bind(); ppDestinationExpr = explicitConversion.ExprDest; return result; } private bool BindExplicitConversion(EXPR pSourceExpr, CType pSourceType, EXPRTYPEORNAMESPACE pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, CONVERTTYPE flags) { ExplicitConversion explicitConversion = new ExplicitConversion(this, pSourceExpr, pSourceType, pDestinationTypeExpr, pDestinationTypeForLambdaErrorReporting, false, flags); return explicitConversion.Bind(); } private bool bindUserDefinedConversion(EXPR exprSrc, CType typeSrc, CType typeDst, bool needExprDest, out EXPR pexprDst, bool fImplicitOnly) { pexprDst = null; if (typeSrc == null || typeDst == null || typeSrc.isInterfaceType() || typeDst.isInterfaceType()) return false; CType cType = typeSrc.StripNubs(); CType cType2 = typeDst.StripNubs(); bool flag = cType != typeSrc; bool flag2 = cType2 != typeDst; bool flag3 = flag2 || typeDst.IsRefType() || typeDst.IsPointerType(); AggregateType[] array = new AggregateType[2]; int num = 0; bool flag4 = fImplicitOnly; bool flag5 = false; if (cType.IsTypeParameterType()) { AggregateType effectiveBaseClass = cType.AsTypeParameterType().GetEffectiveBaseClass(); if (effectiveBaseClass != null && effectiveBaseClass.getAggregate().HasConversion(GetSymbolLoader())) array[num++] = effectiveBaseClass; flag4 = true; } else if (cType.IsAggregateType() && cType.getAggregate().HasConversion(GetSymbolLoader())) { array[num++] = cType.AsAggregateType(); flag5 = (cType.isPredefType(PredefinedType.PT_INTPTR) || cType.isPredefType(PredefinedType.PT_UINTPTR)); } if (cType2.IsTypeParameterType()) { AggregateType effectiveBaseClass2; if (!fImplicitOnly && (effectiveBaseClass2 = cType2.AsTypeParameterType().GetEffectiveBaseClass()).getAggregate().HasConversion(GetSymbolLoader())) array[num++] = effectiveBaseClass2; } else if (cType2.IsAggregateType()) { if (cType2.getAggregate().HasConversion(GetSymbolLoader())) array[num++] = cType2.AsAggregateType(); if (flag5 && !cType2.isPredefType(PredefinedType.PT_LONG) && !cType2.isPredefType(PredefinedType.PT_ULONG)) flag5 = false; } else { flag5 = false; } if (num == 0) return false; List<UdConvInfo> list = new List<UdConvInfo>(); CType cType3 = null; CType cType4 = null; bool flag6 = false; bool flag7 = false; int num6 = -1; int num7 = -1; CType cType5; CType cType6; for (int i = 0; i < num; i++) { AggregateType aggregateType = array[i]; while (aggregateType != null && aggregateType.getAggregate().HasConversion(GetSymbolLoader())) { AggregateSymbol aggregate = aggregateType.getAggregate(); PredefinedType predefType = aggregate.GetPredefType(); bool flag8 = aggregate.IsPredefined() && (predefType == PredefinedType.PT_INTPTR || predefType == PredefinedType.PT_UINTPTR || predefType == PredefinedType.PT_DECIMAL); for (MethodSymbol methodSymbol = aggregate.GetFirstUDConversion(); methodSymbol != null; methodSymbol = methodSymbol.ConvNext()) { if (methodSymbol.Params.Size == 1 && (!fImplicitOnly || methodSymbol.isImplicit()) && !GetSemanticChecker().CheckBogus(methodSymbol)) { cType5 = GetTypes().SubstType(methodSymbol.Params.Item(0), aggregateType); cType6 = GetTypes().SubstType(methodSymbol.RetType, aggregateType); bool flag9 = fImplicitOnly; if (flag4 && !flag9 && cType5.StripNubs() != cType) { if (!methodSymbol.isImplicit()) continue; flag9 = true; } FUNDTYPE fUNDTYPE2; FUNDTYPE fUNDTYPE; if (((fUNDTYPE = cType6.fundType()) > FUNDTYPE.FT_R8 || fUNDTYPE <= FUNDTYPE.FT_NONE || (fUNDTYPE2 = cType5.fundType()) > FUNDTYPE.FT_R8 || fUNDTYPE2 <= FUNDTYPE.FT_NONE) && (!flag5 || (!cType6.isPredefType(PredefinedType.PT_INT) && !cType6.isPredefType(PredefinedType.PT_UINT)))) { if (flag && (flag3 || !flag9) && cType5.IsNonNubValType()) cType5 = GetTypes().GetNullable(cType5); if (flag2 && cType6.IsNonNubValType()) cType6 = GetTypes().GetNullable(cType6); bool flag10 = (exprSrc != null) ? canConvert(exprSrc, cType5, CONVERTTYPE.STANDARDANDNOUDC) : canConvert(typeSrc, cType5, CONVERTTYPE.STANDARDANDNOUDC); if (flag10 || (!flag9 && (canConvert(cType5, typeSrc, CONVERTTYPE.STANDARDANDNOUDC) || (flag8 && !typeSrc.IsPointerType() && !cType5.IsPointerType() && canCast(typeSrc, cType5, CONVERTTYPE.NOUDC))))) { bool flag11 = canConvert(cType6, typeDst, CONVERTTYPE.STANDARDANDNOUDC); if ((flag11 || (!flag9 && (canConvert(typeDst, cType6, CONVERTTYPE.STANDARDANDNOUDC) || (flag8 && !typeDst.IsPointerType() && !cType6.IsPointerType() && canCast(cType6, typeDst, CONVERTTYPE.NOUDC))))) && !isConvInTable(list, methodSymbol, aggregateType, flag10, flag11)) { list.Add(new UdConvInfo()); list[list.Count - 1].mwt = new MethWithType(); list[list.Count - 1].mwt.Set(methodSymbol, aggregateType); list[list.Count - 1].fSrcImplicit = flag10; list[list.Count - 1].fDstImplicit = flag11; if (!flag6) { if (cType5 == typeSrc) { cType3 = cType5; num6 = list.Count - 1; flag6 = true; } else if (cType3 == null) { cType3 = cType5; num6 = list.Count - 1; } else if (cType3 != cType5) { int num8 = CompareSrcTypesBased(cType3, list[num6].fSrcImplicit, cType5, flag10); if (num8 > 0) { cType3 = cType5; num6 = list.Count - 1; } } } if (!flag7) { if (cType6 == typeDst) { cType4 = cType6; num7 = list.Count - 1; flag7 = true; } else if (cType4 == null) { cType4 = cType6; num7 = list.Count - 1; } else if (cType4 != cType6) { int num9 = CompareDstTypesBased(cType4, list[num7].fDstImplicit, cType6, flag11); if (num9 > 0) { cType4 = cType6; num7 = list.Count - 1; } } } } } } } } aggregateType = aggregateType.GetBaseClass(); } } if (cType3 == null) return false; int num10 = 3; int num11 = -1; int num12 = -1; for (int j = 0; j < list.Count; j++) { UdConvInfo udConvInfo = list[j]; cType5 = GetTypes().SubstType(udConvInfo.mwt.Meth().Params.Item(0), udConvInfo.mwt.GetType()); cType6 = GetTypes().SubstType(udConvInfo.mwt.Meth().RetType, udConvInfo.mwt.GetType()); int num13 = 0; if (flag && cType5.IsNonNubValType()) { cType5 = GetTypes().GetNullable(cType5); num13++; } if (flag2 && cType6.IsNonNubValType()) { cType6 = GetTypes().GetNullable(cType6); num13++; } if (cType5 == cType3 && cType6 == cType4) { if (num10 > num13) { num11 = j; num12 = -1; num10 = num13; } else if (num10 >= num13 && num12 < 0) { num12 = j; if (num13 == 0) break; } } else { if (!flag6 && cType5 != cType3) { int num14 = CompareSrcTypesBased(cType3, list[num6].fSrcImplicit, cType5, udConvInfo.fSrcImplicit); if (num14 >= 0) { if (!needExprDest) return true; num7 = j; pexprDst = HandleAmbiguity(exprSrc, typeSrc, typeDst, list, num6, num7); return true; } } if (!flag7 && cType6 != cType4) { int num15 = CompareDstTypesBased(cType4, list[num7].fDstImplicit, cType6, udConvInfo.fDstImplicit); if (num15 >= 0) { if (!needExprDest) return true; num7 = j; pexprDst = HandleAmbiguity(exprSrc, typeSrc, typeDst, list, num6, num7); return true; } } } } if (!needExprDest) return true; if (num11 < 0) { pexprDst = HandleAmbiguity(exprSrc, typeSrc, typeDst, list, num6, num7); return true; } if (num12 >= 0) { num6 = num11; num7 = num12; pexprDst = HandleAmbiguity(exprSrc, typeSrc, typeDst, list, num6, num7); return true; } MethWithInst methWithInst = new MethWithInst(list[num11].mwt.Meth(), list[num11].mwt.GetType(), null); cType5 = GetTypes().SubstType(methWithInst.Meth().Params.Item(0), methWithInst.GetType()); cType6 = GetTypes().SubstType(methWithInst.Meth().RetType, methWithInst.GetType()); EXPR ppTransformedArgument = exprSrc; EXPR eXPR; if ((num10 > 0 && !cType5.IsNullableType()) & flag3) { EXPRMEMGRP pMemberGroup = ExprFactory.CreateMemGroup(null, methWithInst); eXPR = ExprFactory.CreateCall((EXPRFLAG)0, typeDst, exprSrc, pMemberGroup, methWithInst); EXPR eXPR2 = mustCast(exprSrc, cType5); MarkAsIntermediateConversion(eXPR2); EXPR expr = BindUDConversionCore(eXPR2, cType5, cType6, typeDst, methWithInst); EXPRCALL eXPRCALL = eXPR.asCALL(); eXPRCALL.castOfNonLiftedResultToLiftedType = mustCast(expr, typeDst); eXPRCALL.nubLiftKind = NullableCallLiftKind.UserDefinedConversion; if (flag) { EXPR eXPR3 = null; if (cType5 == cType) eXPR3 = ((!cType6.IsNullableType()) ? exprSrc : mustCast(exprSrc, cType5)); else { NullableType nullable = SymbolLoader.GetTypeManager().GetNullable(cType5); eXPR3 = mustCast(exprSrc, nullable); MarkAsIntermediateConversion(eXPR3); } EXPR eXPR4 = ExprFactory.CreateCall((EXPRFLAG)0, typeDst, eXPR3, pMemberGroup, methWithInst); eXPR4.asCALL().nubLiftKind = NullableCallLiftKind.NotLiftedIntermediateConversion; eXPRCALL.pConversions = eXPR4; } else { EXPR eXPR5 = BindUDConversionCore(eXPR2, cType5, cType6, typeDst, methWithInst); MarkAsIntermediateConversion(eXPR5); eXPRCALL.pConversions = eXPR5; } } else eXPR = BindUDConversionCore(exprSrc, cType5, cType6, typeDst, methWithInst, out ppTransformedArgument); pexprDst = ExprFactory.CreateUserDefinedConversion(ppTransformedArgument, eXPR, methWithInst); return true; } private EXPR HandleAmbiguity(EXPR exprSrc, CType typeSrc, CType typeDst, List<UdConvInfo> prguci, int iuciBestSrc, int iuciBestDst) { ErrorContext.Error(ErrorCode.ERR_AmbigUDConv, prguci[iuciBestSrc].mwt, prguci[iuciBestDst].mwt, typeSrc, typeDst); EXPRCLASS pType = ExprFactory.MakeClass(typeDst); EXPR eXPR = ExprFactory.CreateCast((EXPRFLAG)0, pType, exprSrc); eXPR.SetError(); return eXPR; } private void MarkAsIntermediateConversion(EXPR pExpr) { if (pExpr.isCALL()) { switch (pExpr.asCALL().nubLiftKind) { case NullableCallLiftKind.NotLifted: pExpr.asCALL().nubLiftKind = NullableCallLiftKind.NotLiftedIntermediateConversion; break; case NullableCallLiftKind.NullableConversion: pExpr.asCALL().nubLiftKind = NullableCallLiftKind.NullableIntermediateConversion; break; case NullableCallLiftKind.NullableConversionConstructor: MarkAsIntermediateConversion(pExpr.asCALL().GetOptionalArguments()); break; } } else if (pExpr.isUSERDEFINEDCONVERSION()) { MarkAsIntermediateConversion(pExpr.asUSERDEFINEDCONVERSION().UserDefinedCall); } } private EXPR BindUDConversionCore(EXPR pFrom, CType pTypeFrom, CType pTypeTo, CType pTypeDestination, MethWithInst mwiBest) { EXPR ppTransformedArgument; return BindUDConversionCore(pFrom, pTypeFrom, pTypeTo, pTypeDestination, mwiBest, out ppTransformedArgument); } private EXPR BindUDConversionCore(EXPR pFrom, CType pTypeFrom, CType pTypeTo, CType pTypeDestination, MethWithInst mwiBest, out EXPR ppTransformedArgument) { EXPRCLASS destExpr = ExprFactory.MakeClass(pTypeFrom); EXPR eXPR = mustCastCore(pFrom, destExpr, CONVERTTYPE.NOUDC); EXPRMEMGRP pMemberGroup = ExprFactory.CreateMemGroup(null, mwiBest); EXPRCALL expr = ExprFactory.CreateCall((EXPRFLAG)0, pTypeTo, eXPR, pMemberGroup, mwiBest); EXPRCLASS destExpr2 = ExprFactory.MakeClass(pTypeDestination); EXPR result = mustCastCore(expr, destExpr2, CONVERTTYPE.NOUDC); ppTransformedArgument = eXPR; return result; } private ConstCastResult bindConstantCast(EXPR exprSrc, EXPRTYPEORNAMESPACE exprTypeDest, bool needExprDest, out EXPR pexprDest, bool explicitConversion) { pexprDest = null; long num = 0; double num2 = 0; CType cType = exprTypeDest.TypeOrNamespace.AsType(); FUNDTYPE fUNDTYPE = exprSrc.type.fundType(); FUNDTYPE fUNDTYPE2 = cType.fundType(); bool flag = fUNDTYPE <= FUNDTYPE.FT_U8; bool flag2 = fUNDTYPE <= FUNDTYPE.FT_R8; EXPRCONSTANT eXPRCONSTANT = exprSrc.GetConst().asCONSTANT(); if (fUNDTYPE == FUNDTYPE.FT_STRUCT || fUNDTYPE2 == FUNDTYPE.FT_STRUCT) { EXPR eXPR = bindDecimalConstCast(exprTypeDest, exprSrc.type, eXPRCONSTANT); if (eXPR == null) { if (explicitConversion) return ConstCastResult.CheckFailure; return ConstCastResult.Failure; } if (needExprDest) pexprDest = eXPR; return ConstCastResult.Success; } if (explicitConversion && Context.CheckedConstant && !isConstantInRange(eXPRCONSTANT, cType, true)) return ConstCastResult.CheckFailure; if (!needExprDest) return ConstCastResult.Success; if (flag) { if (eXPRCONSTANT.type.fundType() == FUNDTYPE.FT_U8) { if (fUNDTYPE2 == FUNDTYPE.FT_U8) { CONSTVAL constVal = GetExprConstants().Create(eXPRCONSTANT.getU64Value()); pexprDest = ExprFactory.CreateConstant(cType, constVal); return ConstCastResult.Success; } num = ((long)eXPRCONSTANT.getU64Value() & -1); } else num = eXPRCONSTANT.getI64Value(); } else { if (!flag2) return ConstCastResult.Failure; num2 = eXPRCONSTANT.getVal().doubleVal; } switch (fUNDTYPE2) { case FUNDTYPE.FT_I1: if (!flag) num = (long)num2; num = (sbyte)(num & 255); break; case FUNDTYPE.FT_I2: if (!flag) num = (long)num2; num = (short)(num & 65535); break; case FUNDTYPE.FT_I4: if (!flag) num = (long)num2; num = (int)(num & uint.MaxValue); break; case FUNDTYPE.FT_I8: if (!flag) num = (long)num2; break; case FUNDTYPE.FT_U1: if (!flag) num = (long)num2; num = (byte)(num & 255); break; case FUNDTYPE.FT_U2: if (!flag) num = (long)num2; num = (ushort)(num & 65535); break; case FUNDTYPE.FT_U4: if (!flag) num = (long)num2; num = (uint)(num & uint.MaxValue); break; case FUNDTYPE.FT_U8: if (!flag) { num = (long)(ulong)num2; num = ((!(num2 < 9.223372036854776E+18)) ? ((long)(num2 - 9.223372036854776E+18) + I64(9223372036854775808)) : ((long)num2)); } break; case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: if (flag) num2 = ((fUNDTYPE != FUNDTYPE.FT_U8) ? ((double)num) : ((double)(ulong)num)); if (fUNDTYPE2 == FUNDTYPE.FT_R4) { RoundToFloat(num2, out float f); num2 = (double)f; } break; } CONSTVAL cONSTVAL = new CONSTVAL(); if (fUNDTYPE2 == FUNDTYPE.FT_U4) cONSTVAL.uiVal = (uint)num; else if (fUNDTYPE2 > FUNDTYPE.FT_U4) { cONSTVAL = ((fUNDTYPE2 > FUNDTYPE.FT_U8) ? GetExprConstants().Create(num2) : GetExprConstants().Create(num)); } else { cONSTVAL.iVal = (int)num; } EXPRCONSTANT eXPRCONSTANT2 = (EXPRCONSTANT)(pexprDest = ExprFactory.CreateConstant(cType, cONSTVAL)); return ConstCastResult.Success; } private int CompareSrcTypesBased(CType type1, bool fImplicit1, CType type2, bool fImplicit2) { if (fImplicit1 != fImplicit2) { if (!fImplicit1) return 1; return -1; } bool flag = canConvert(type1, type2, CONVERTTYPE.NOUDC); bool flag2 = canConvert(type2, type1, CONVERTTYPE.NOUDC); if (flag == flag2) return 0; if (fImplicit1 != flag) return 1; return -1; } private int CompareDstTypesBased(CType type1, bool fImplicit1, CType type2, bool fImplicit2) { if (fImplicit1 != fImplicit2) { if (!fImplicit1) return 1; return -1; } bool flag = canConvert(type1, type2, CONVERTTYPE.NOUDC); bool flag2 = canConvert(type2, type1, CONVERTTYPE.NOUDC); if (flag == flag2) return 0; if (fImplicit1 != flag) return -1; return 1; } private EXPR bindDecimalConstCast(EXPRTYPEORNAMESPACE exprDestType, CType srcType, EXPRCONSTANT src) { CType cType = exprDestType.TypeOrNamespace.AsType(); CType optPredefType = SymbolLoader.GetOptPredefType(PredefinedType.PT_DECIMAL); CONSTVAL cONSTVAL = new CONSTVAL(); if (optPredefType == null) return null; if (cType == optPredefType) { decimal value; switch (srcType.fundType()) { case FUNDTYPE.FT_I1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_I4: value = Convert.ToDecimal(src.getVal().iVal); break; case FUNDTYPE.FT_U1: case FUNDTYPE.FT_U2: case FUNDTYPE.FT_U4: value = Convert.ToDecimal(src.getVal().uiVal); break; case FUNDTYPE.FT_R4: value = Convert.ToDecimal((float)src.getVal().doubleVal); break; case FUNDTYPE.FT_R8: value = Convert.ToDecimal(src.getVal().doubleVal); break; case FUNDTYPE.FT_U8: value = Convert.ToDecimal((ulong)src.getVal().longVal); break; case FUNDTYPE.FT_I8: value = Convert.ToDecimal(src.getVal().longVal); break; default: return null; } cONSTVAL = GetExprConstants().Create(value); return ExprFactory.CreateConstant(optPredefType, cONSTVAL); } if (srcType == optPredefType) { decimal value2 = default(decimal); FUNDTYPE fUNDTYPE = cType.fundType(); try { if (fUNDTYPE != FUNDTYPE.FT_R4 && fUNDTYPE != FUNDTYPE.FT_R8) value2 = decimal.Truncate(src.getVal().decVal); switch (fUNDTYPE) { case FUNDTYPE.FT_I1: cONSTVAL.iVal = Convert.ToSByte(value2); break; case FUNDTYPE.FT_U1: cONSTVAL.uiVal = Convert.ToByte(value2); break; case FUNDTYPE.FT_I2: cONSTVAL.iVal = Convert.ToInt16(value2); break; case FUNDTYPE.FT_U2: cONSTVAL.uiVal = Convert.ToUInt16(value2); break; case FUNDTYPE.FT_I4: cONSTVAL.iVal = Convert.ToInt32(value2); break; case FUNDTYPE.FT_U4: cONSTVAL.uiVal = Convert.ToUInt32(value2); break; case FUNDTYPE.FT_I8: cONSTVAL = GetExprConstants().Create(Convert.ToInt64(value2)); break; case FUNDTYPE.FT_U8: cONSTVAL = GetExprConstants().Create(Convert.ToUInt64(value2)); break; case FUNDTYPE.FT_R4: cONSTVAL = GetExprConstants().Create(Convert.ToSingle(src.getVal().decVal)); break; case FUNDTYPE.FT_R8: cONSTVAL = GetExprConstants().Create(Convert.ToDouble(src.getVal().decVal)); break; default: return null; } } catch (OverflowException) { return null; } return ExprFactory.CreateConstant(cType, cONSTVAL); } return null; } private bool canExplicitConversionBeBoundInUncheckedContext(EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, CONVERTTYPE flags) { CheckedContext context = CheckedContext.CreateInstance(Context, false, false); return new ExpressionBinder(context).BindExplicitConversion(exprSrc, typeSrc, typeDest, typeDest.TypeOrNamespace.AsType(), flags); } public BindingContext GetContext() { return Context; } private static void VSFAIL(string s) { } public ExpressionBinder(BindingContext context) { Context = context; m_nullable = new CNullable(GetSymbolLoader(), GetErrorContext(), GetExprFactory()); g_binopSignatures = new BinOpSig[20] { new BinOpSig(PredefinedType.PT_INT, PredefinedType.PT_INT, BinOpMask.Integer, 8, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp), new BinOpSig(PredefinedType.PT_UINT, PredefinedType.PT_UINT, BinOpMask.Integer, 7, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp), new BinOpSig(PredefinedType.PT_LONG, PredefinedType.PT_LONG, BinOpMask.Integer, 6, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp), new BinOpSig(PredefinedType.PT_ULONG, PredefinedType.PT_ULONG, BinOpMask.Integer, 5, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp), new BinOpSig(PredefinedType.PT_ULONG, PredefinedType.PT_LONG, BinOpMask.Integer, 4, null, OpSigFlags.Value, BinOpFuncKind.None), new BinOpSig(PredefinedType.PT_LONG, PredefinedType.PT_ULONG, BinOpMask.Integer, 3, null, OpSigFlags.Value, BinOpFuncKind.None), new BinOpSig(PredefinedType.PT_FLOAT, PredefinedType.PT_FLOAT, BinOpMask.Real, 1, BindRealBinOp, OpSigFlags.Value, BinOpFuncKind.RealBinOp), new BinOpSig(PredefinedType.PT_DOUBLE, PredefinedType.PT_DOUBLE, BinOpMask.Real, 0, BindRealBinOp, OpSigFlags.Value, BinOpFuncKind.RealBinOp), new BinOpSig(PredefinedType.PT_DECIMAL, PredefinedType.PT_DECIMAL, BinOpMask.Real, 0, BindDecBinOp, OpSigFlags.Value, BinOpFuncKind.DecBinOp), new BinOpSig(PredefinedType.PT_STRING, PredefinedType.PT_STRING, BinOpMask.Equal, 0, BindStrCmpOp, OpSigFlags.Convert, BinOpFuncKind.StrCmpOp), new BinOpSig(PredefinedType.PT_STRING, PredefinedType.PT_STRING, BinOpMask.Add, 2, BindStrBinOp, OpSigFlags.Convert, BinOpFuncKind.StrBinOp), new BinOpSig(PredefinedType.PT_STRING, PredefinedType.PT_OBJECT, BinOpMask.Add, 1, BindStrBinOp, OpSigFlags.Convert, BinOpFuncKind.StrBinOp), new BinOpSig(PredefinedType.PT_OBJECT, PredefinedType.PT_STRING, BinOpMask.Add, 0, BindStrBinOp, OpSigFlags.Convert, BinOpFuncKind.StrBinOp), new BinOpSig(PredefinedType.PT_INT, PredefinedType.PT_INT, BinOpMask.Shift, 3, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp), new BinOpSig(PredefinedType.PT_UINT, PredefinedType.PT_INT, BinOpMask.Shift, 2, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp), new BinOpSig(PredefinedType.PT_LONG, PredefinedType.PT_INT, BinOpMask.Shift, 1, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp), new BinOpSig(PredefinedType.PT_ULONG, PredefinedType.PT_INT, BinOpMask.Shift, 0, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp), new BinOpSig(PredefinedType.PT_BOOL, PredefinedType.PT_BOOL, BinOpMask.BoolNorm, 0, BindBoolBinOp, OpSigFlags.Value, BinOpFuncKind.BoolBinOp), new BinOpSig(PredefinedType.PT_BOOL, PredefinedType.PT_BOOL, BinOpMask.Logical, 0, BindBoolBinOp, OpSigFlags.BoolBit, BinOpFuncKind.BoolBinOp), new BinOpSig(PredefinedType.PT_BOOL, PredefinedType.PT_BOOL, BinOpMask.Bitwise, 0, BindLiftedBoolBitwiseOp, OpSigFlags.BoolBit, BinOpFuncKind.BoolBitwiseOp) }; g_rguos = new UnaOpSig[16] { new UnaOpSig(PredefinedType.PT_INT, UnaOpMask.Signed, 7, BindIntUnaOp, UnaOpFuncKind.IntUnaOp), new UnaOpSig(PredefinedType.PT_UINT, UnaOpMask.Unsigned, 6, BindIntUnaOp, UnaOpFuncKind.IntUnaOp), new UnaOpSig(PredefinedType.PT_LONG, UnaOpMask.Signed, 5, BindIntUnaOp, UnaOpFuncKind.IntUnaOp), new UnaOpSig(PredefinedType.PT_ULONG, UnaOpMask.Unsigned, 4, BindIntUnaOp, UnaOpFuncKind.IntUnaOp), new UnaOpSig(PredefinedType.PT_ULONG, UnaOpMask.Minus, 3, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_FLOAT, UnaOpMask.Real, 1, BindRealUnaOp, UnaOpFuncKind.RealUnaOp), new UnaOpSig(PredefinedType.PT_DOUBLE, UnaOpMask.Real, 0, BindRealUnaOp, UnaOpFuncKind.RealUnaOp), new UnaOpSig(PredefinedType.PT_DECIMAL, UnaOpMask.Real, 0, BindDecUnaOp, UnaOpFuncKind.DecUnaOp), new UnaOpSig(PredefinedType.PT_BOOL, UnaOpMask.Bang, 0, BindBoolUnaOp, UnaOpFuncKind.BoolUnaOp), new UnaOpSig(PredefinedType.PT_INT, UnaOpMask.IncDec, 6, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_UINT, UnaOpMask.IncDec, 5, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_LONG, UnaOpMask.IncDec, 4, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_ULONG, UnaOpMask.IncDec, 3, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_FLOAT, UnaOpMask.IncDec, 1, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_DOUBLE, UnaOpMask.IncDec, 0, null, UnaOpFuncKind.None), new UnaOpSig(PredefinedType.PT_DECIMAL, UnaOpMask.IncDec, 0, null, UnaOpFuncKind.None) }; } protected SymbolLoader GetSymbolLoader() { return SymbolLoader; } public CSemanticChecker GetSemanticChecker() { return SemanticChecker; } private ErrorHandling GetErrorContext() { return ErrorContext; } protected BSYMMGR GetGlobalSymbols() { return GetSymbolLoader().getBSymmgr(); } protected TypeManager GetTypes() { return TypeManager; } private ExprFactory GetExprFactory() { return ExprFactory; } private ConstValFactory GetExprConstants() { return GetExprFactory().GetExprConstants(); } protected AggregateType GetReqPDT(PredefinedType pt) { return GetReqPDT(pt, GetSymbolLoader()); } protected static AggregateType GetReqPDT(PredefinedType pt, SymbolLoader symbolLoader) { return symbolLoader.GetReqPredefType(pt, true); } protected AggregateType GetOptPDT(PredefinedType pt) { return GetOptPDT(pt, true); } protected AggregateType GetOptPDT(PredefinedType pt, bool WarnIfNotFound) { if (WarnIfNotFound) return GetSymbolLoader().GetOptPredefTypeErr(pt, true); return GetSymbolLoader().GetOptPredefType(pt, true); } protected CType getVoidType() { return VoidType; } public EXPR GenerateAssignmentConversion(EXPR op1, EXPR op2, bool allowExplicit) { if (allowExplicit) return mustCastCore(op2, GetExprFactory().MakeClass(op1.type), (CONVERTTYPE)0); return mustConvertCore(op2, GetExprFactory().MakeClass(op1.type)); } public EXPR bindAssignment(EXPR op1, EXPR op2, bool allowExplicit) { bool flag = false; bool flag2 = false; if (!op1.isANYLOCAL_OK()) { if (!checkLvalue(op1, CheckLvalueKind.Assignment)) { EXPR eXPR = GetExprFactory().CreateAssignment(op1, op2); eXPR.SetError(); return eXPR; } } else { if (op2.type.IsArrayType()) return BindPtrToArray(op1.asANYLOCAL(), op2); if (op2.type == GetReqPDT(PredefinedType.PT_STRING)) op2 = bindPtrToString(op2); else if (op2.kind == ExpressionKind.EK_ADDR) { op2.flags |= EXPRFLAG.EXF_ASFINALLYLEAVE; } else if (op2.isOK()) { flag = true; flag2 = op2.isCAST(); } } op2 = GenerateAssignmentConversion(op1, op2, allowExplicit); if (op2.isOK() & flag) { if (flag2) ErrorContext.Error(ErrorCode.ERR_BadCastInFixed, Array.Empty<ErrArg>()); else ErrorContext.Error(ErrorCode.ERR_FixedNotNeeded, Array.Empty<ErrArg>()); } return GenerateOptimizedAssignment(op1, op2); } internal EXPR BindArrayIndexCore(BindingFlag bindFlags, EXPR pOp1, EXPR pOp2) { bool flag = false; if (!pOp1.isOK() || !pOp2.isOK()) flag = true; CType pIntType = GetReqPDT(PredefinedType.PT_INT); EXPR eXPR; if (!pOp1.type.IsArrayType()) { eXPR = bindIndexer(pOp1, pOp2, bindFlags); if (flag) eXPR.SetError(); return eXPR; } ArrayType arrayType = pOp1.type.AsArrayType(); checkUnsafe(arrayType.GetElementType()); CType pDestType = chooseArrayIndexType(pOp2); if (pDestType == null) pDestType = pIntType; int rank = arrayType.rank; int cIndices = 0; EXPR pIndex = pOp2.Map(GetExprFactory(), delegate(EXPR x) { cIndices++; EXPR eXPR2 = mustConvert(x, pDestType); if (pDestType == pIntType) return eXPR2; EXPRFLAG nFlags = EXPRFLAG.EXF_LITERALCONST; EXPRCLASS pType = GetExprFactory().MakeClass(pDestType); return GetExprFactory().CreateCast(nFlags, pType, eXPR2); }); if (cIndices != rank) { ErrorContext.Error(ErrorCode.ERR_BadIndexCount, rank); eXPR = GetExprFactory().CreateArrayIndex(pOp1, pIndex); eXPR.SetError(); return eXPR; } eXPR = GetExprFactory().CreateArrayIndex(pOp1, pIndex); eXPR.flags |= (EXPRFLAG)6291456; if (flag) eXPR.SetError(); return eXPR; } protected EXPRUNARYOP bindPtrToString(EXPR string) { CType pointer = GetTypes().GetPointer(GetReqPDT(PredefinedType.PT_CHAR)); return GetExprFactory().CreateUnaryOp(ExpressionKind.EK_ADDR, pointer, string); } protected EXPRQUESTIONMARK BindPtrToArray(EXPRLOCAL exprLoc, EXPR array) { CType elementType = array.type.AsArrayType().GetElementType(); CType pointer = GetTypes().GetPointer(elementType); if (GetSymbolLoader().isManagedType(elementType)) ErrorContext.Error(ErrorCode.ERR_ManagedAddr, elementType); SetExternalRef(elementType); EXPR eXPR = null; EXPRWRAP eXPRWRAP = WrapShortLivedExpression(array).asWRAP(); EXPR p = GetExprFactory().CreateSave(eXPRWRAP); EXPR p2 = GetExprFactory().CreateBinop(ExpressionKind.EK_NE, GetReqPDT(PredefinedType.PT_BOOL), p, GetExprFactory().CreateConstant(eXPRWRAP.type, ConstValFactory.GetInt(0))); EXPR p4; if (array.type.AsArrayType().rank == 1) { EXPR p3 = GetExprFactory().CreateArrayLength(eXPRWRAP); p4 = GetExprFactory().CreateBinop(ExpressionKind.EK_NE, GetReqPDT(PredefinedType.PT_BOOL), p3, GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), ConstValFactory.GetInt(0))); } else { EXPRCALL p5 = BindPredefMethToArgs(PREDEFMETH.PM_ARRAY_GETLENGTH, eXPRWRAP, null, null, null); p4 = GetExprFactory().CreateBinop(ExpressionKind.EK_NE, GetReqPDT(PredefinedType.PT_BOOL), p5, GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), ConstValFactory.GetInt(0))); } eXPR = GetExprFactory().CreateBinop(ExpressionKind.EK_LOGAND, GetReqPDT(PredefinedType.PT_BOOL), p2, p4); EXPR eXPR2 = null; EXPR first = eXPR2; EXPR last = null; for (int i = 0; i < array.type.AsArrayType().rank; i++) { GetExprFactory().AppendItemToList(GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), ConstValFactory.GetInt(0)), ref first, ref last); } EXPR eXPR3 = GetExprFactory().CreateUnaryOp(ExpressionKind.EK_ADDR, pointer, GetExprFactory().CreateArrayIndex(eXPRWRAP, eXPR2)); eXPR3.flags |= EXPRFLAG.EXF_ASFINALLYLEAVE; eXPR3 = mustConvert(eXPR3, exprLoc.type, CONVERTTYPE.NOUDC); eXPR3 = GetExprFactory().CreateAssignment(exprLoc, eXPR3); eXPR3.flags |= EXPRFLAG.EXF_ASSGOP; eXPR3 = GetExprFactory().CreateBinop(ExpressionKind.EK_SEQREV, exprLoc.type, eXPR3, WrapShortLivedExpression(eXPRWRAP)); EXPR pRHS = GetExprFactory().CreateZeroInit(exprLoc.type); pRHS = GetExprFactory().CreateAssignment(exprLoc, pRHS); pRHS.flags |= EXPRFLAG.EXF_ASSGOP; EXPRBINOP pConsequence = GetExprFactory().CreateBinop(ExpressionKind.EK_BINOP, eXPR3.type, eXPR3, pRHS); return GetExprFactory().CreateQuestionMark(eXPR, pConsequence); } protected EXPR bindIndexer(EXPR pObject, EXPR args, BindingFlag bindFlags) { CType type = pObject.type; if (!type.IsAggregateType() && !type.IsTypeParameterType()) { ErrorContext.Error(ErrorCode.ERR_BadIndexLHS, type); MethWithInst mwi = new MethWithInst(null, null); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(pObject, mwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, type, args, pMemberGroup, null); eXPRCALL.SetError(); return eXPRCALL; } Name predefName = GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_INDEXERINTERNAL); MemberLookup memberLookup = new MemberLookup(); if (!memberLookup.Lookup(GetSemanticChecker(), type, pObject, ContextForMemberLookup(), predefName, 0, ((bindFlags & BindingFlag.BIND_BASECALL) != 0) ? ((MemLookFlags)68) : MemLookFlags.Indexer)) { memberLookup.ReportErrors(); type = GetTypes().GetErrorSym(); Symbol symbol = null; if (memberLookup.SwtInaccessible().Sym != null) { type = memberLookup.SwtInaccessible().MethProp().RetType; symbol = memberLookup.SwtInaccessible().Sym; } EXPRMEMGRP eXPRMEMGRP = null; if (symbol != null) { eXPRMEMGRP = GetExprFactory().CreateMemGroup((EXPRFLAG)memberLookup.GetFlags(), predefName, BSYMMGR.EmptyTypeArray(), symbol.getKind(), memberLookup.GetSourceType(), null, memberLookup.GetObject(), memberLookup.GetResults()); eXPRMEMGRP.SetInaccessibleBit(); } else { MethWithInst mwi2 = new MethWithInst(null, null); eXPRMEMGRP = GetExprFactory().CreateMemGroup(memberLookup.GetObject(), mwi2); } EXPRCALL eXPRCALL2 = GetExprFactory().CreateCall((EXPRFLAG)0, type, args, eXPRMEMGRP, null); eXPRCALL2.SetError(); return eXPRCALL2; } EXPRMEMGRP grp = GetExprFactory().CreateMemGroup((EXPRFLAG)memberLookup.GetFlags(), predefName, BSYMMGR.EmptyTypeArray(), memberLookup.SymFirst().getKind(), memberLookup.GetSourceType(), null, memberLookup.GetObject(), memberLookup.GetResults()); EXPR eXPR = BindMethodGroupToArguments(bindFlags, grp, args); if (eXPR.getObject() == null) { eXPR.SetObject(pObject); eXPR.SetError(); } return eXPR; } public void bindSimpleCast(EXPR exprSrc, EXPRTYPEORNAMESPACE typeDest, out EXPR pexprDest) { bindSimpleCast(exprSrc, typeDest, out pexprDest, (EXPRFLAG)0); } public void bindSimpleCast(EXPR exprSrc, EXPRTYPEORNAMESPACE exprTypeDest, out EXPR pexprDest, EXPRFLAG exprFlags) { CType cType = exprTypeDest.TypeOrNamespace.AsType(); pexprDest = null; EXPR const = exprSrc.GetConst(); EXPRCAST eXPRCAST = GetExprFactory().CreateCast(exprFlags, exprTypeDest, exprSrc); if (Context.CheckedNormal) eXPRCAST.flags |= EXPRFLAG.EXF_CHECKOVERFLOW; if (const != null && exprFlags == (EXPRFLAG)0 && exprSrc.type.fundType() == cType.fundType() && (!exprSrc.type.isPredefType(PredefinedType.PT_STRING) || const.asCONSTANT().getVal().IsNullRef())) { EXPRCONSTANT eXPRCONSTANT = (EXPRCONSTANT)(pexprDest = GetExprFactory().CreateConstant(cType, const.asCONSTANT().getVal())); } else pexprDest = eXPRCAST; } internal EXPRCALL BindToMethod(MethWithInst mwi, EXPR pArguments, EXPRMEMGRP pMemGroup, MemLookFlags flags) { EXPR optionalObject = pMemGroup.GetOptionalObject(); CType callingObjectType = optionalObject?.type; PostBindMethod((flags & MemLookFlags.BaseCall) != MemLookFlags.None, ref mwi, optionalObject); optionalObject = AdjustMemberObject(mwi, optionalObject, out bool pfConstrained, out bool pIsMatchingStatic); pMemGroup.SetOptionalObject(optionalObject); CType cType = null; cType = (((flags & (MemLookFlags)18) != (MemLookFlags)18) ? GetTypes().SubstType(mwi.Meth().RetType, mwi.GetType(), mwi.TypeArgs) : mwi.Ats); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, cType, pArguments, pMemGroup, mwi); if (!pIsMatchingStatic) eXPRCALL.SetMismatchedStaticBit(); if (!eXPRCALL.isOK()) return eXPRCALL; if ((flags & MemLookFlags.Ctor) != 0 && (flags & MemLookFlags.NewObj) != 0) eXPRCALL.flags |= (EXPRFLAG)131088; if ((flags & MemLookFlags.BaseCall) != 0) eXPRCALL.flags |= EXPRFLAG.EXF_ASFINALLYLEAVE; else if (pfConstrained && optionalObject != null) { eXPRCALL.flags |= EXPRFLAG.EXF_UNREALIZEDGOTO; } verifyMethodArgs(eXPRCALL, callingObjectType); return eXPRCALL; } internal EXPR BindToField(EXPR pObject, FieldWithType fwt, BindingFlag bindFlags) { return BindToField(pObject, fwt, bindFlags, null); } internal EXPR BindToField(EXPR pOptionalObject, FieldWithType fwt, BindingFlag bindFlags, EXPR pOptionalLHS) { CType cType = GetTypes().SubstType(fwt.Field().GetType(), fwt.GetType()); if (pOptionalObject != null && !pOptionalObject.isOK()) { EXPRFIELD eXPRFIELD = GetExprFactory().CreateField((EXPRFLAG)0, cType, pOptionalObject, 0, fwt, pOptionalLHS); eXPRFIELD.SetError(); return eXPRFIELD; } EXPR eXPR = pOptionalObject; pOptionalObject = AdjustMemberObject(fwt, pOptionalObject, out bool _, out bool pIsMatchingStatic); checkUnsafe(cType); bool flag = false; if ((pOptionalObject != null && pOptionalObject.type.IsPointerType()) || objectIsLvalue(pOptionalObject)) flag = true; if (RespectReadonly() && fwt.Field().isReadOnly && (ContainingAgg() == null || !InMethod() || !InConstructor() || fwt.Field().getClass() != ContainingAgg() || InStaticMethod() != fwt.Field().isStatic || (pOptionalObject != null && !isThisPointer(pOptionalObject)) || InAnonymousMethod())) flag = false; EXPRFIELD eXPRFIELD2 = GetExprFactory().CreateField(flag ? EXPRFLAG.EXF_LVALUE : ((EXPRFLAG)0), cType, pOptionalObject, 0, fwt, pOptionalLHS); if (!pIsMatchingStatic) eXPRFIELD2.SetMismatchedStaticBit(); if (cType.IsErrorType()) eXPRFIELD2.SetError(); eXPRFIELD2.flags |= (EXPRFLAG)(bindFlags & BindingFlag.BIND_MEMBERSET); if (eXPRFIELD2.isFIELD() && fwt.Field().isEvent && fwt.Field().getEvent(GetSymbolLoader()) != null && fwt.Field().getEvent(GetSymbolLoader()).IsWindowsRuntimeEvent) { CType type = fwt.Field().GetType(); if (type.IsAggregateType()) { eXPRFIELD2.setType(GetTypes().GetParameterModifier(eXPRFIELD2.type, false)); Name predefName = GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_GETORCREATEEVENTREGISTRATIONTOKENTABLE); GetSymbolLoader().RuntimeBinderSymbolTable.PopulateSymbolTableWithName(predefName.Text, null, type.AssociatedSystemType); MethodSymbol mps = GetSymbolLoader().LookupAggMember(predefName, type.getAggregate(), symbmask_t.MASK_MethodSymbol).AsMethodSymbol(); MethPropWithInst methPropWithInst = new MethPropWithInst(mps, type.AsAggregateType()); EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, methPropWithInst); EXPR pObject = BindToMethod(new MethWithInst(methPropWithInst), eXPRFIELD2, pMemGroup, MemLookFlags.None); AggregateSymbol owningAggregate = type.AsAggregateType().GetOwningAggregate(); Name predefName2 = GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_INVOCATIONLIST); GetSymbolLoader().RuntimeBinderSymbolTable.PopulateSymbolTableWithName(predefName2.Text, null, type.AssociatedSystemType); PropertySymbol propertySymbol = GetSymbolLoader().LookupAggMember(predefName2, owningAggregate, symbmask_t.MASK_PropertySymbol).AsPropertySymbol(); MethPropWithInst mwi = new MethPropWithInst(propertySymbol, type.AsAggregateType()); EXPRMEMGRP pMemGroup2 = GetExprFactory().CreateMemGroup(pObject, mwi); PropWithType pwt = new PropWithType(propertySymbol, type.AsAggregateType()); return BindToProperty(pObject, pwt, bindFlags, null, null, pMemGroup2); } } return eXPRFIELD2; } internal EXPR BindToProperty(EXPR pObject, PropWithType pwt, BindingFlag bindFlags, EXPR args, AggregateType pOtherType, EXPRMEMGRP pMemGroup) { EXPR eXPR = null; if ((bindFlags & BindingFlag.BIND_BASECALL) == (BindingFlag)0) eXPR = pObject; PostBindProperty((bindFlags & BindingFlag.BIND_BASECALL) != (BindingFlag)0, pwt, pObject, out MethWithType pmwtGet, out MethWithType pmwtSet); pObject = (((bool)pmwtGet && (!(bool)pmwtSet || pmwtSet.GetType() == pmwtGet.GetType() || GetSymbolLoader().HasBaseConversion(pmwtGet.GetType(), pmwtSet.GetType()))) ? AdjustMemberObject(pmwtGet, pObject, out bool pfConstrained, out bool pIsMatchingStatic) : ((!(bool)pmwtSet) ? AdjustMemberObject(pwt, pObject, out pfConstrained, out pIsMatchingStatic) : AdjustMemberObject(pmwtSet, pObject, out pfConstrained, out pIsMatchingStatic))); pMemGroup.SetOptionalObject(pObject); CType pType = GetTypes().SubstType(pwt.Prop().RetType, pwt.GetType()); if (pObject != null && !pObject.isOK()) { EXPRPROP eXPRPROP = GetExprFactory().CreateProperty(pType, eXPR, args, pMemGroup, pwt, null, null); if (!pIsMatchingStatic) eXPRPROP.SetMismatchedStaticBit(); eXPRPROP.SetError(); return eXPRPROP; } if ((bindFlags & BindingFlag.BIND_RVALUEREQUIRED) != 0) { if (!(bool)pmwtGet) { if (pOtherType != null) return GetExprFactory().MakeClass(pOtherType); ErrorContext.ErrorRef(ErrorCode.ERR_PropertyLacksGet, pwt); } else if ((bindFlags & BindingFlag.BIND_BASECALL) != 0 && pmwtGet.Meth().isAbstract) { if (pOtherType != null) return GetExprFactory().MakeClass(pOtherType); ErrorContext.Error(ErrorCode.ERR_AbstractBaseCall, pwt); } else { CType cType = null; if (eXPR != null) cType = eXPR.type; ACCESSERROR aCCESSERROR = SemanticChecker.CheckAccess2(pmwtGet.Meth(), pmwtGet.GetType(), ContextForMemberLookup(), cType); if (aCCESSERROR != ACCESSERROR.ACCESSERROR_NOERROR) { if (pOtherType != null) return GetExprFactory().MakeClass(pOtherType); if (aCCESSERROR == ACCESSERROR.ACCESSERROR_NOACCESSTHRU) ErrorContext.Error(ErrorCode.ERR_BadProtectedAccess, pwt, cType, ContextForMemberLookup()); else ErrorContext.ErrorRef(ErrorCode.ERR_InaccessibleGetter, pwt); } } } EXPRPROP eXPRPROP2 = GetExprFactory().CreateProperty(pType, eXPR, args, pMemGroup, pwt, pmwtGet, pmwtSet); if (!pIsMatchingStatic) eXPRPROP2.SetMismatchedStaticBit(); if ((BindingFlag.BIND_BASECALL & bindFlags) != 0) eXPRPROP2.flags |= EXPRFLAG.EXF_ASFINALLYLEAVE; else if (pfConstrained && pObject != null) { eXPRPROP2.flags |= EXPRFLAG.EXF_UNREALIZEDGOTO; } if (eXPRPROP2.GetOptionalArguments() != null) verifyMethodArgs(eXPRPROP2, eXPR?.type); if ((bool)pmwtSet && objectIsLvalue(eXPRPROP2.GetMemberGroup().GetOptionalObject())) eXPRPROP2.flags |= EXPRFLAG.EXF_LVALUE; if (pOtherType != null) eXPRPROP2.flags |= EXPRFLAG.EXF_SAMENAMETYPE; return eXPRPROP2; } internal EXPR bindUDUnop(ExpressionKind ek, EXPR arg) { Name name = ekName(ek); CType cType = arg.type; while (true) { switch (cType.GetTypeKind()) { case TypeKind.TK_NullableType: cType = cType.StripNubs(); break; case TypeKind.TK_TypeParameterType: cType = cType.AsTypeParameterType().GetEffectiveBaseClass(); break; case TypeKind.TK_AggregateType: { if ((!cType.isClassType() && !cType.isStructType()) || cType.AsAggregateType().getAggregate().IsSkipUDOps()) return null; ArgInfos argInfos = new ArgInfos(); argInfos.carg = 1; FillInArgInfoFromArgList(argInfos, arg); List<CandidateFunctionMember> list = new List<CandidateFunctionMember>(); MethodSymbol methodSymbol = null; AggregateType aggregateType = cType.AsAggregateType(); while (true) { methodSymbol = ((methodSymbol == null) ? GetSymbolLoader().LookupAggMember(name, aggregateType.getAggregate(), symbmask_t.MASK_MethodSymbol).AsMethodSymbol() : GetSymbolLoader().LookupNextSym(methodSymbol, aggregateType.getAggregate(), symbmask_t.MASK_MethodSymbol).AsMethodSymbol()); if (methodSymbol == null) { if (!list.IsEmpty()) break; aggregateType = aggregateType.GetBaseClass(); if (aggregateType == null) break; } else if (methodSymbol.isOperator && methodSymbol.Params.size == 1) { TypeArray typeArray = GetTypes().SubstTypeArray(methodSymbol.Params, aggregateType); CType cType2 = typeArray.Item(0); NullableType nullable; if (canConvert(arg, cType2)) list.Add(new CandidateFunctionMember(new MethPropWithInst(methodSymbol, aggregateType, BSYMMGR.EmptyTypeArray()), typeArray, 0, false)); else if (GetSymbolLoader().FCanLift() && cType2.IsNonNubValType() && GetTypes().SubstType(methodSymbol.RetType, aggregateType).IsNonNubValType() && canConvert(arg, nullable = GetTypes().GetNullable(cType2))) { list.Add(new CandidateFunctionMember(new MethPropWithInst(methodSymbol, aggregateType, BSYMMGR.EmptyTypeArray()), GetGlobalSymbols().AllocParams(1, new CType[1] { nullable }), 1, false)); } } } if (list.IsEmpty()) return null; CandidateFunctionMember methAmbig; CandidateFunctionMember methAmbig2; CandidateFunctionMember candidateFunctionMember = FindBestMethod(list, null, argInfos, out methAmbig, out methAmbig2); if (candidateFunctionMember == null) { ErrorContext.Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi, methAmbig2.mpwi); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methAmbig.mpwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, null, arg, pMemberGroup, null); eXPRCALL.SetError(); return eXPRCALL; } if (SemanticChecker.CheckBogus(candidateFunctionMember.mpwi.Meth())) { ErrorContext.ErrorRef(ErrorCode.ERR_BindToBogus, candidateFunctionMember.mpwi); EXPRMEMGRP pMemberGroup2 = GetExprFactory().CreateMemGroup(null, candidateFunctionMember.mpwi); EXPRCALL eXPRCALL2 = GetExprFactory().CreateCall((EXPRFLAG)0, null, arg, pMemberGroup2, null); eXPRCALL2.SetError(); return eXPRCALL2; } EXPRCALL eXPRCALL3 = (candidateFunctionMember.ctypeLift == 0) ? BindUDUnopCall(arg, candidateFunctionMember.params.Item(0), candidateFunctionMember.mpwi) : BindLiftedUDUnop(arg, candidateFunctionMember.params.Item(0), candidateFunctionMember.mpwi); return GetExprFactory().CreateUserDefinedUnaryOperator(ek, eXPRCALL3.type, arg, eXPRCALL3, candidateFunctionMember.mpwi); } default: return null; } } } private EXPRCALL BindLiftedUDUnop(EXPR arg, CType typeArg, MethPropWithInst mpwi) { CType cType = typeArg.StripNubs(); if (!arg.type.IsNullableType() || !canConvert(arg.type.StripNubs(), cType, CONVERTTYPE.NOUDC)) arg = mustConvert(arg, typeArg); CType cType2 = GetTypes().SubstType(mpwi.Meth().RetType, mpwi.GetType()); if (!cType2.IsNullableType()) cType2 = GetTypes().GetNullable(cType2); EXPR arg2 = mustCast(arg, cType); EXPRCALL expr = BindUDUnopCall(arg2, cType, mpwi); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, cType2, arg, pMemberGroup, null); eXPRCALL.mwi = new MethWithInst(mpwi); eXPRCALL.castOfNonLiftedResultToLiftedType = mustCast(expr, cType2, (CONVERTTYPE)0); eXPRCALL.nubLiftKind = NullableCallLiftKind.Operator; return eXPRCALL; } private EXPRCALL BindUDUnopCall(EXPR arg, CType typeArg, MethPropWithInst mpwi) { CType cType = GetTypes().SubstType(mpwi.Meth().RetType, mpwi.GetType()); checkUnsafe(cType); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, cType, mustConvert(arg, typeArg), pMemberGroup, null); eXPRCALL.mwi = new MethWithInst(mpwi); verifyMethodArgs(eXPRCALL, mpwi.GetType()); return eXPRCALL; } private bool BindMethodGroupToArgumentsCore(out GroupToArgsBinderResult pResults, BindingFlag bindFlags, EXPRMEMGRP grp, ref EXPR args, int carg, bool bindingCollectionAdd, bool bHasNamedArgumentSpecifiers) { bool flag = false; ArgInfos argInfos = new ArgInfos(); argInfos.carg = carg; FillInArgInfoFromArgList(argInfos, args); ArgInfos argInfos2 = new ArgInfos(); argInfos2.carg = carg; FillInArgInfoFromArgList(argInfos2, args); GroupToArgsBinder groupToArgsBinder = new GroupToArgsBinder(this, bindFlags, grp, argInfos, argInfos2, bHasNamedArgumentSpecifiers, null); flag = ((!bindingCollectionAdd) ? groupToArgsBinder.Bind(true) : groupToArgsBinder.BindCollectionAddArgs()); pResults = groupToArgsBinder.GetResultsOfBind(); return flag; } internal EXPR BindMethodGroupToArguments(BindingFlag bindFlags, EXPRMEMGRP grp, EXPR args) { bool typeErrors; int carg = CountArguments(args, out typeErrors); EXPR optionalObject = grp.GetOptionalObject(); if (grp.name == null) { EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, GetTypes().GetErrorSym(), args, grp, null); eXPRCALL.SetError(); return eXPRCALL; } bool seenNamed = false; if (!VerifyNamedArgumentsAfterFixed(args, out seenNamed)) { EXPRCALL eXPRCALL2 = GetExprFactory().CreateCall((EXPRFLAG)0, GetTypes().GetErrorSym(), args, grp, null); eXPRCALL2.SetError(); return eXPRCALL2; } if (!BindMethodGroupToArgumentsCore(out GroupToArgsBinderResult pResults, bindFlags, grp, ref args, carg, false, seenNamed)) return null; MethPropWithInst bestResult = pResults.GetBestResult(); if (grp.sk != SYMKIND.SK_PropertySymbol) return BindToMethod(new MethWithInst(bestResult), args, grp, (MemLookFlags)grp.flags); return BindToProperty(grp.GetOptionalObject(), new PropWithType(bestResult), (BindingFlag)((int)bindFlags | (int)(grp.flags & EXPRFLAG.EXF_ASFINALLYLEAVE)), args, null, grp); } private bool VerifyNamedArgumentsAfterFixed(EXPR args, out bool seenNamed) { EXPR eXPR = args; seenNamed = false; while (eXPR != null) { EXPR expr; if (eXPR.isLIST()) { expr = eXPR.asLIST().GetOptionalElement(); eXPR = eXPR.asLIST().GetOptionalNextListNode(); } else { expr = eXPR; eXPR = null; } if (expr.isNamedArgumentSpecification()) seenNamed = true; else if (seenNamed) { GetErrorContext().Error(ErrorCode.ERR_NamedArgumentSpecificationBeforeFixedArgument, Array.Empty<ErrArg>()); return false; } } return true; } internal EXPRCALL BindPredefMethToArgs(PREDEFMETH predefMethod, EXPR obj, EXPR args, TypeArray clsTypeArgs, TypeArray methTypeArgs) { MethodSymbol method = GetSymbolLoader().getPredefinedMembers().GetMethod(predefMethod); if (method == null) { MethWithInst mwi = new MethWithInst(null, null); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(obj, mwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, null, args, pMemberGroup, null); eXPRCALL.SetError(); return eXPRCALL; } AggregateSymbol class = method.getClass(); if (clsTypeArgs == null) clsTypeArgs = BSYMMGR.EmptyTypeArray(); AggregateType aggregate = GetTypes().GetAggregate(class, clsTypeArgs); MethPropWithInst methPropWithInst = new MethPropWithInst(method, aggregate, methTypeArgs); EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(obj, methPropWithInst); return BindToMethod(new MethWithInst(methPropWithInst), args, pMemGroup, MemLookFlags.None); } protected EXPR BadOperatorTypesError(ExpressionKind ek, EXPR pOperand1, EXPR pOperand2) { return BadOperatorTypesError(ek, pOperand1, pOperand2, null); } protected EXPR BadOperatorTypesError(ExpressionKind ek, EXPR pOperand1, EXPR pOperand2, CType pTypeErr) { string errorString = pOperand1.errorString; pOperand1 = UnwrapExpression(pOperand1); if (pOperand1 != null) { if (pOperand2 != null) { pOperand2 = UnwrapExpression(pOperand2); if (pOperand1.type != null && !pOperand1.type.IsErrorType() && pOperand2.type != null && !pOperand2.type.IsErrorType()) ErrorContext.Error(ErrorCode.ERR_BadBinaryOps, errorString, pOperand1.type, pOperand2.type); } else if (pOperand1.type != null && !pOperand1.type.IsErrorType()) { ErrorContext.Error(ErrorCode.ERR_BadUnaryOp, errorString, pOperand1.type); } } if (pTypeErr == null) pTypeErr = GetReqPDT(PredefinedType.PT_OBJECT); EXPR eXPR = GetExprFactory().CreateOperator(ek, pTypeErr, pOperand1, pOperand2); eXPR.SetError(); return eXPR; } protected EXPR UnwrapExpression(EXPR pExpression) { EXPR eXPR = pExpression; while (eXPR != null && eXPR.isWRAP() && eXPR.asWRAP().GetOptionalExpression() != null) { eXPR = eXPR.asWRAP().GetOptionalExpression(); } return eXPR; } private static ErrorCode GetStandardLvalueError(CheckLvalueKind kind) { switch (kind) { default: VSFAIL("bad kind"); return ErrorCode.ERR_AssgLvalueExpected; case CheckLvalueKind.Assignment: return ErrorCode.ERR_AssgLvalueExpected; case CheckLvalueKind.OutParameter: return ErrorCode.ERR_RefLvalueExpected; case CheckLvalueKind.Increment: return ErrorCode.ERR_IncrementLvalueExpected; } } protected void CheckLvalueProp(EXPRPROP prop) { if (prop.isBaseCall() && prop.mwtSet.Meth().isAbstract) ErrorContext.Error(ErrorCode.ERR_AbstractBaseCall, prop.mwtSet); else { CType type = null; if (prop.GetOptionalObjectThrough() != null) type = prop.GetOptionalObjectThrough().type; CheckPropertyAccess(prop.mwtSet, prop.pwtSlot, type); } } protected bool CheckPropertyAccess(MethWithType mwt, PropWithType pwtSlot, CType type) { switch (SemanticChecker.CheckAccess2(mwt.Meth(), mwt.GetType(), ContextForMemberLookup(), type)) { case ACCESSERROR.ACCESSERROR_NOACCESSTHRU: ErrorContext.Error(ErrorCode.ERR_BadProtectedAccess, pwtSlot, type, ContextForMemberLookup()); return false; case ACCESSERROR.ACCESSERROR_NOACCESS: ErrorContext.Error(mwt.Meth().isSetAccessor() ? ErrorCode.ERR_InaccessibleSetter : ErrorCode.ERR_InaccessibleGetter, pwtSlot); return false; default: return true; } } internal bool checkLvalue(EXPR expr, CheckLvalueKind kind) { if (!expr.isOK()) return false; if (expr.isLvalue()) { if (expr.isPROP()) CheckLvalueProp(expr.asPROP()); markFieldAssigned(expr); return true; } switch (expr.kind) { case ExpressionKind.EK_PROP: if (kind == CheckLvalueKind.OutParameter) { ErrorContext.Error(ErrorCode.ERR_RefProperty, Array.Empty<ErrArg>()); return true; } if (!(bool)expr.asPROP().mwtSet) { ErrorContext.Error(ErrorCode.ERR_AssgReadonlyProp, expr.asPROP().pwtSlot); return true; } break; case ExpressionKind.EK_ARRAYLENGTH: if (kind == CheckLvalueKind.OutParameter) ErrorContext.Error(ErrorCode.ERR_RefProperty, Array.Empty<ErrArg>()); else ErrorContext.Error(ErrorCode.ERR_AssgReadonlyProp, GetSymbolLoader().getPredefinedMembers().GetProperty(PREDEFPROP.PP_ARRAY_LENGTH)); return true; case ExpressionKind.EK_CONSTANT: case ExpressionKind.EK_BOUNDLAMBDA: case ExpressionKind.EK_UNBOUNDLAMBDA: ErrorContext.Error(GetStandardLvalueError(kind), Array.Empty<ErrArg>()); return false; case ExpressionKind.EK_MEMGRP: { ErrorCode id = (kind == CheckLvalueKind.OutParameter) ? ErrorCode.ERR_RefReadonlyLocalCause : ErrorCode.ERR_AssgReadonlyLocalCause; ErrorContext.Error(id, expr.asMEMGRP().name, new ErrArgIds(MessageID.MethodGroup)); return false; } } return !TryReportLvalueFailure(expr, kind); } internal void PostBindMethod(bool fBaseCall, ref MethWithInst pMWI, EXPR pObject) { MethWithInst methWithInst = pMWI; if (pObject != null && (fBaseCall || pObject.type.isSimpleType() || pObject.type.isSpecialByRefType())) RemapToOverride(GetSymbolLoader(), pMWI, pObject.type); if (fBaseCall && pMWI.Meth().isAbstract) ErrorContext.Error(ErrorCode.ERR_AbstractBaseCall, pMWI); if (pMWI.Meth().RetType != null) { checkUnsafe(pMWI.Meth().RetType); bool flag = false; if (pMWI.Meth().isExternal) { flag = true; SetExternalRef(pMWI.Meth().RetType); } TypeArray params = pMWI.Meth().Params; for (int i = 0; i < params.size; i++) { CType cType = params.Item(i); if (cType.isUnsafe()) checkUnsafe(cType); if (flag && cType.IsParameterModifierType()) SetExternalRef(cType); } } } protected void PostBindProperty(bool fBaseCall, PropWithType pwt, EXPR pObject, out MethWithType pmwtGet, out MethWithType pmwtSet) { pmwtGet = new MethWithType(); pmwtSet = new MethWithType(); if (pwt.Prop().methGet != null) pmwtGet.Set(pwt.Prop().methGet, pwt.GetType()); else pmwtGet.Clear(); if (pwt.Prop().methSet != null) pmwtSet.Set(pwt.Prop().methSet, pwt.GetType()); else pmwtSet.Clear(); if (fBaseCall && pObject != null) { if ((bool)pmwtGet) RemapToOverride(GetSymbolLoader(), pmwtGet, pObject.type); if ((bool)pmwtSet) RemapToOverride(GetSymbolLoader(), pmwtSet, pObject.type); } if (pwt.Prop().RetType != null) checkUnsafe(pwt.Prop().RetType); } private EXPR AdjustMemberObject(SymWithType swt, EXPR pObject, out bool pfConstrained, out bool pIsMatchingStatic) { bool flag = pIsMatchingStatic = IsMatchingStatic(swt, pObject); pfConstrained = false; bool isStatic = swt.Sym.isStatic; if (!flag) { if (isStatic) { if ((pObject.flags & EXPRFLAG.EXF_UNREALIZEDGOTO) != 0) { pIsMatchingStatic = true; return null; } ErrorContext.ErrorRef(ErrorCode.ERR_ObjectProhibited, swt); return null; } ErrorContext.ErrorRef(ErrorCode.ERR_ObjectRequired, swt); return pObject; } if (isStatic) return null; if (swt.Sym.IsMethodSymbol() && swt.Meth().IsConstructor()) return pObject; if (pObject == null) { if (InFieldInitializer() && !InStaticMethod() && ContainingAgg() == swt.Sym.parent) ErrorContext.ErrorRef(ErrorCode.ERR_FieldInitRefNonstatic, swt); else { if (!InAnonymousMethod() || InStaticMethod() || ContainingAgg() != swt.Sym.parent || !ContainingAgg().IsStruct()) return null; ErrorContext.Error(ErrorCode.ERR_ThisStructNotInAnonMeth, Array.Empty<ErrArg>()); } EXPRTHISPOINTER eXPRTHISPOINTER = GetExprFactory().CreateThis(Context.GetThisPointer(), true); eXPRTHISPOINTER.SetMismatchedStaticBit(); if (eXPRTHISPOINTER.type == null) eXPRTHISPOINTER.setType(GetTypes().GetErrorSym()); return eXPRTHISPOINTER; } CType cType = pObject.type; CType ats; if (cType.IsNullableType() && (ats = cType.AsNullableType().GetAts(GetErrorContext())) != null && ats != swt.GetType()) cType = ats; if (cType.IsTypeParameterType() || cType.IsAggregateType()) { AggregateSymbol aggregateSymbol = null; aggregateSymbol = swt.Sym.parent.AsAggregateSymbol(); if (pObject.isFIELD() && !pObject.asFIELD().fwt.Field().isAssigned && !swt.Sym.IsFieldSymbol() && cType.isStructType() && !cType.isPredefined()) pObject.asFIELD().fwt.Field().isAssigned = true; if (pfConstrained && (cType.IsTypeParameterType() || (cType.isStructType() && swt.GetType().IsRefType() && swt.Sym.IsVirtual()))) pfConstrained = true; EXPR eXPR = tryConvert(pObject, swt.GetType(), CONVERTTYPE.NOUDC); if (eXPR == null) { if (!pObject.type.isSpecialByRefType()) ErrorContext.Error(ErrorCode.ERR_WrongNestedThis, swt.GetType(), pObject.type); else ErrorContext.Error(ErrorCode.ERR_NoImplicitConv, pObject.type, swt.GetType()); } pObject = eXPR; } return pObject; } private bool IsMatchingStatic(SymWithType swt, EXPR pObject) { Symbol sym = swt.Sym; if (sym.IsMethodSymbol() && sym.AsMethodSymbol().IsConstructor()) return !sym.AsMethodSymbol().isStatic; if (swt.Sym.isStatic) { if (pObject == null || (pObject.flags & EXPRFLAG.EXF_IMPLICITTHIS) != 0) return true; if ((pObject.flags & EXPRFLAG.EXF_SAMENAMETYPE) == (EXPRFLAG)0) return false; } else if (pObject == null) { bool flag = InFieldInitializer() && !InStaticMethod() && ContainingAgg() == swt.Sym.parent; bool flag2 = InAnonymousMethod() && !InStaticMethod() && ContainingAgg() == swt.Sym.parent && ContainingAgg().IsStruct(); if (!flag && !flag2) return false; } return true; } private bool objectIsLvalue(EXPR pObject) { if (pObject != null && !isThisPointer(pObject) && ((pObject.flags & EXPRFLAG.EXF_LVALUE) == (EXPRFLAG)0 || pObject.kind == ExpressionKind.EK_PROP)) return !pObject.type.isStructOrEnum(); return true; } public static void RemapToOverride(SymbolLoader symbolLoader, SymWithType pswt, CType typeObj) { if (typeObj.IsNullableType()) { typeObj = typeObj.AsNullableType().GetAts(symbolLoader.GetErrorContext()); if (typeObj == null) { VSFAIL("Why did GetAts return null?"); return; } } if (typeObj.IsAggregateType() && !typeObj.isInterfaceType() && pswt.Sym.IsVirtual()) { symbmask_t symbmask_t = pswt.Sym.mask(); AggregateType aggregateType = typeObj.AsAggregateType(); while (aggregateType != null && aggregateType.getAggregate() != pswt.Sym.parent) { for (Symbol symbol = symbolLoader.LookupAggMember(pswt.Sym.name, aggregateType.getAggregate(), symbmask_t); symbol != null; symbol = symbolLoader.LookupNextSym(symbol, aggregateType.getAggregate(), symbmask_t)) { if (symbol.IsOverride() && (symbol.SymBaseVirtual() == pswt.Sym || symbol.SymBaseVirtual() == pswt.Sym.SymBaseVirtual())) { pswt.Set(symbol, aggregateType); return; } } aggregateType = aggregateType.GetBaseClass(); } } } protected void verifyMethodArgs(EXPR call, CType callingObjectType) { EXPR args = call.getArgs(); SymWithType symWithType = call.GetSymWithType(); MethodOrPropertySymbol mp = symWithType.Sym.AsMethodOrPropertySymbol(); TypeArray pTypeArgs = call.isCALL() ? call.asCALL().mwi.TypeArgs : null; AdjustCallArgumentsForParams(callingObjectType, symWithType.GetType(), mp, pTypeArgs, args, out EXPR newArgs); call.setArgs(newArgs); } protected void AdjustCallArgumentsForParams(CType callingObjectType, CType type, MethodOrPropertySymbol mp, TypeArray pTypeArgs, EXPR argsPtr, out EXPR newArgs) { newArgs = null; EXPR last = null; MethodOrPropertySymbol methodOrPropertySymbol = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mp, callingObjectType); int num = mp.Params.size; TypeArray params = mp.Params; int num2 = 0; bool flag = mp.IsFMETHSYM() && mp.AsFMETHSYM().isExternal; int num3 = ExpressionIterator.Count(argsPtr); if (mp.IsFMETHSYM() && mp.AsFMETHSYM().isVarargs) num--; bool flag2 = false; EXPR eXPR = null; ExpressionIterator expressionIterator = new ExpressionIterator(argsPtr); if (argsPtr != null) { while (true) { if (expressionIterator.AtEnd()) return; eXPR = expressionIterator.Current(); if (!eXPR.type.IsParameterModifierType()) { switch (num) { case 1: break; default: goto IL_00ef; case 0: goto IL_02b4; } if (mp.isParamArray && num3 > mp.Params.size) break; goto IL_00ef; } if (num != 0) num--; if (flag) SetExternalRef(eXPR.type); GetExprFactory().AppendItemToList(eXPR, ref newArgs, ref last); goto IL_02b4; IL_02b4: num2++; if (num != 0 && mp.isParamArray && num2 == num3) { eXPR = null; expressionIterator.MoveNext(); break; } expressionIterator.MoveNext(); continue; IL_00ef: EXPR eXPR2 = eXPR; EXPR eXPR3; if (eXPR2.isNamedArgumentSpecification()) { int num4 = 0; foreach (Name parameterName in methodOrPropertySymbol.ParameterNames) { if (parameterName == eXPR2.asNamedArgumentSpecification().Name) break; num4++; } CType dest = GetTypes().SubstType(params.Item(num4), type, pTypeArgs); if (!canConvert(eXPR2.asNamedArgumentSpecification().Value, dest) && mp.isParamArray && num4 == mp.Params.size - 1) { CType cType = GetTypes().SubstType(mp.Params.Item(mp.Params.size - 1), type, pTypeArgs); CType elementType = cType.AsArrayType().GetElementType(); EXPRARRINIT eXPRARRINIT = GetExprFactory().CreateArrayInit((EXPRFLAG)0, cType, null, null, null); eXPRARRINIT.GeneratedForParamArray = true; eXPRARRINIT.dimSizes = new int[1] { eXPRARRINIT.dimSize }; eXPRARRINIT.dimSize = 1; eXPRARRINIT.SetOptionalArguments(eXPR2.asNamedArgumentSpecification().Value); eXPR2.asNamedArgumentSpecification().Value = eXPRARRINIT; flag2 = true; } else eXPR2.asNamedArgumentSpecification().Value = tryConvert(eXPR2.asNamedArgumentSpecification().Value, dest); eXPR3 = eXPR2; } else { CType dest2 = GetTypes().SubstType(params.Item(num2), type, pTypeArgs); eXPR3 = tryConvert(eXPR, dest2); } if (eXPR3 == null) { if (mp.isParamArray && num == 1 && num3 >= mp.Params.size) break; return; } eXPR = eXPR3; GetExprFactory().AppendItemToList(eXPR3, ref newArgs, ref last); num--; goto IL_02b4; } } else if (!mp.isParamArray) { return; } if (!flag2) { CType cType2 = GetTypes().SubstType(mp.Params.Item(mp.Params.size - 1), type, pTypeArgs); if (cType2.IsArrayType() && cType2.AsArrayType().rank == 1) { CType elementType2 = cType2.AsArrayType().GetElementType(); EXPRARRINIT eXPRARRINIT2 = GetExprFactory().CreateArrayInit((EXPRFLAG)0, cType2, null, null, null); eXPRARRINIT2.GeneratedForParamArray = true; eXPRARRINIT2.dimSizes = new int[1] { eXPRARRINIT2.dimSize }; if (expressionIterator.AtEnd()) { eXPRARRINIT2.dimSize = 0; eXPRARRINIT2.dimSizes[0] = 0; eXPRARRINIT2.SetOptionalArguments(null); argsPtr = ((argsPtr != null) ? ((EXPR)GetExprFactory().CreateList(argsPtr, eXPRARRINIT2)) : ((EXPR)eXPRARRINIT2)); GetExprFactory().AppendItemToList(eXPRARRINIT2, ref newArgs, ref last); } else { EXPR first = null; EXPR last2 = null; int num5 = 0; while (!expressionIterator.AtEnd()) { EXPR eXPR4 = expressionIterator.Current(); num5++; if (eXPR4.isNamedArgumentSpecification()) eXPR4.asNamedArgumentSpecification().Value = tryConvert(eXPR4.asNamedArgumentSpecification().Value, elementType2); else eXPR4 = tryConvert(eXPR4, elementType2); GetExprFactory().AppendItemToList(eXPR4, ref first, ref last2); expressionIterator.MoveNext(); } eXPRARRINIT2.dimSize = num5; eXPRARRINIT2.dimSizes[0] = num5; eXPRARRINIT2.SetOptionalArguments(first); GetExprFactory().AppendItemToList(eXPRARRINIT2, ref newArgs, ref last); } } } } protected void markFieldAssigned(EXPR expr) { if (expr.isFIELD() && (expr.flags & EXPRFLAG.EXF_LVALUE) != 0) { EXPRFIELD eXPRFIELD; do { eXPRFIELD = expr.asFIELD(); eXPRFIELD.fwt.Field().isAssigned = true; expr = eXPRFIELD.GetOptionalObject(); } while (eXPRFIELD.fwt.Field().getClass().IsStruct() && !eXPRFIELD.fwt.Field().isStatic && expr != null && expr.isFIELD()); } } protected void SetExternalRef(CType type) { AggregateSymbol nakedAgg = type.GetNakedAgg(); if (nakedAgg != null && !nakedAgg.HasExternReference()) { nakedAgg.SetHasExternReference(true); foreach (Symbol item in nakedAgg.Children()) { if (item.IsFieldSymbol()) SetExternalRef(item.AsFieldSymbol().GetType()); } } } internal CType chooseArrayIndexType(EXPR args) { for (int i = 0; i < s_rgptIntOp.Length; i++) { CType reqPDT = GetReqPDT(s_rgptIntOp[i]); using (IEnumerator<EXPR> enumerator = args.ToEnumerable().GetEnumerator()) { EXPR current; do { if (!enumerator.MoveNext()) return reqPDT; current = enumerator.Current; } while (canConvert(current, reqPDT)); } } return null; } internal void FillInArgInfoFromArgList(ArgInfos argInfo, EXPR args) { CType[] array = new CType[argInfo.carg]; argInfo.fHasExprs = true; argInfo.prgexpr = new List<EXPR>(); int num = 0; EXPR eXPR = args; while (eXPR != null) { EXPR eXPR2; if (eXPR.isLIST()) { eXPR2 = eXPR.asLIST().GetOptionalElement(); eXPR = eXPR.asLIST().GetOptionalNextListNode(); } else { eXPR2 = eXPR; eXPR = null; } if (eXPR2.type != null) array[num] = eXPR2.type; else array[num] = GetTypes().GetErrorSym(); argInfo.prgexpr.Add(eXPR2); num++; } argInfo.types = GetGlobalSymbols().AllocParams(num, array); } protected bool TryGetExpandedParams(TypeArray params, int count, out TypeArray ppExpandedParams) { CType[] array; if (count < params.size - 1) { array = new CType[params.size - 1]; params.CopyItems(0, params.size - 1, array); ppExpandedParams = GetGlobalSymbols().AllocParams(params.size - 1, array); return true; } array = new CType[count]; params.CopyItems(0, params.size - 1, array); CType cType = params.Item(params.size - 1); CType cType2 = null; if (!cType.IsArrayType()) { ppExpandedParams = null; return false; } cType2 = cType.AsArrayType().GetElementType(); for (int i = params.size - 1; i < count; i++) { array[i] = cType2; } ppExpandedParams = GetGlobalSymbols().AllocParams(array); return true; } public static bool IsMethPropCallable(MethodOrPropertySymbol sym, bool requireUC) { if (!sym.isOverride || sym.isHideByName) { if (requireUC) return sym.isUserCallable(); return true; } return false; } private bool isConvInTable(List<UdConvInfo> convTable, MethodSymbol meth, AggregateType ats, bool fSrc, bool fDst) { foreach (UdConvInfo item in convTable) { if (item.mwt.Meth() == meth && item.mwt.GetType() == ats && item.fSrcImplicit == fSrc && item.fDstImplicit == fDst) return true; } return false; } public static bool isConstantInRange(EXPRCONSTANT exprSrc, CType typeDest) { return isConstantInRange(exprSrc, typeDest, false); } public static bool isConstantInRange(EXPRCONSTANT exprSrc, CType typeDest, bool realsOk) { FUNDTYPE fUNDTYPE = exprSrc.type.fundType(); FUNDTYPE fUNDTYPE2 = typeDest.fundType(); if (fUNDTYPE > FUNDTYPE.FT_U8 || fUNDTYPE2 > FUNDTYPE.FT_U8) { if (!realsOk) return false; if (fUNDTYPE > FUNDTYPE.FT_R8 || fUNDTYPE2 > FUNDTYPE.FT_R8) return false; } if (fUNDTYPE2 > FUNDTYPE.FT_U8) return true; if (fUNDTYPE > FUNDTYPE.FT_U8) { double doubleVal = exprSrc.asCONSTANT().getVal().doubleVal; switch (fUNDTYPE2) { case FUNDTYPE.FT_I1: if (doubleVal > -129 && doubleVal < 128) return true; break; case FUNDTYPE.FT_I2: if (doubleVal > -32769 && doubleVal < 32768) return true; break; case FUNDTYPE.FT_I4: if (doubleVal > (double)I64(-2147483649) && doubleVal < (double)I64(2147483648)) return true; break; case FUNDTYPE.FT_I8: if (doubleVal >= -9.223372036854776E+18 && doubleVal < 9.223372036854776E+18) return true; break; case FUNDTYPE.FT_U1: if (doubleVal > -1 && doubleVal < 256) return true; break; case FUNDTYPE.FT_U2: if (doubleVal > -1 && doubleVal < 65536) return true; break; case FUNDTYPE.FT_U4: if (doubleVal > -1 && doubleVal < (double)I64(4294967296)) return true; break; case FUNDTYPE.FT_U8: if (doubleVal > -1 && doubleVal < 1.8446744073709552E+19) return true; break; } return false; } if (fUNDTYPE == FUNDTYPE.FT_U8) { ulong u64Value = exprSrc.asCONSTANT().getU64Value(); switch (fUNDTYPE2) { case FUNDTYPE.FT_I1: if (u64Value <= 127) return true; break; case FUNDTYPE.FT_I2: if (u64Value <= 32767) return true; break; case FUNDTYPE.FT_I4: if (u64Value <= 2147483647) return true; break; case FUNDTYPE.FT_I8: if (u64Value <= 9223372036854775807) return true; break; case FUNDTYPE.FT_U1: if (u64Value <= 255) return true; break; case FUNDTYPE.FT_U2: if (u64Value <= 65535) return true; break; case FUNDTYPE.FT_U4: if (u64Value <= uint.MaxValue) return true; break; case FUNDTYPE.FT_U8: return true; } } else { long i64Value = exprSrc.asCONSTANT().getI64Value(); switch (fUNDTYPE2) { case FUNDTYPE.FT_I1: if (i64Value >= -128 && i64Value <= 127) return true; break; case FUNDTYPE.FT_I2: if (i64Value >= -32768 && i64Value <= 32767) return true; break; case FUNDTYPE.FT_I4: if (i64Value >= I64(-2147483648) && i64Value <= I64(2147483647)) return true; break; case FUNDTYPE.FT_I8: return true; case FUNDTYPE.FT_U1: if (i64Value >= 0 && i64Value <= 255) return true; break; case FUNDTYPE.FT_U2: if (i64Value >= 0 && i64Value <= 65535) return true; break; case FUNDTYPE.FT_U4: if (i64Value >= 0 && i64Value <= I64(4294967295)) return true; break; case FUNDTYPE.FT_U8: if (i64Value >= 0) return true; break; } } return false; } protected Name ekName(ExpressionKind ek) { return GetSymbolLoader().GetNameManager().GetPredefName(s_EK2NAME[(int)(ek - 42)]); } public void checkUnsafe(CType type) { checkUnsafe(type, ErrorCode.ERR_UnsafeNeeded, null); } public void checkUnsafe(CType type, ErrorCode errCode, ErrArg pArg) { if (type == null || type.isUnsafe()) { if (!isUnsafeContext() && ReportUnsafeErrors()) { if (pArg != null) ErrorContext.Error(errCode, pArg); else ErrorContext.Error(errCode, Array.Empty<ErrArg>()); } RecordUnsafeUsage(); } } protected bool InMethod() { return Context.InMethod(); } protected bool InStaticMethod() { return Context.InStaticMethod(); } protected bool InConstructor() { return Context.InConstructor(); } protected bool InAnonymousMethod() { return Context.InAnonymousMethod(); } protected bool InFieldInitializer() { return Context.InFieldInitializer(); } private Declaration ContextForMemberLookup() { return Context.ContextForMemberLookup(); } protected AggregateSymbol ContainingAgg() { return Context.ContainingAgg(); } protected bool isThisPointer(EXPR expr) { return Context.IsThisPointer(expr); } protected bool RespectReadonly() { return Context.RespectReadonly(); } protected bool isUnsafeContext() { return Context.IsUnsafeContext(); } protected bool ReportUnsafeErrors() { return Context.ReportUnsafeErrors(); } protected virtual void RecordUnsafeUsage() { RecordUnsafeUsage(Context); } protected virtual EXPR WrapShortLivedExpression(EXPR expr) { return GetExprFactory().CreateWrap(null, expr); } protected virtual EXPR GenerateOptimizedAssignment(EXPR op1, EXPR op2) { return GetExprFactory().CreateAssignment(op1, op2); } public static void RecordUnsafeUsage(BindingContext context) { if (context.GetUnsafeState() != 0 && !context.GetOutputContext().m_bUnsafeErrorGiven) context.GetOutputContext().m_bUnsafeErrorGiven = true; } internal static int CountArguments(EXPR args, out bool typeErrors) { int num = 0; typeErrors = false; EXPR eXPR = args; while (eXPR != null) { EXPR eXPR2; if (eXPR.isLIST()) { eXPR2 = eXPR.asLIST().GetOptionalElement(); eXPR = eXPR.asLIST().GetOptionalNextListNode(); } else { eXPR2 = eXPR; eXPR = null; } if (eXPR2.type == null || eXPR2.type.IsErrorType()) typeErrors = true; num++; } return num; } internal EXPR BindNubValue(EXPR exprSrc) { return m_nullable.BindValue(exprSrc); } private EXPRCALL BindNubNew(EXPR exprSrc) { return m_nullable.BindNew(exprSrc); } protected EXPR bindUserDefinedBinOp(ExpressionKind ek, BinOpArgInfo info) { MethPropWithInst ppmpwi = null; if (info.pt1 <= PredefinedType.PT_ULONG && info.pt2 <= PredefinedType.PT_ULONG) return null; EXPR eXPR = null; BinOpKind binopKind = info.binopKind; if (binopKind == BinOpKind.Logical) { EXPRCALL eXPRCALL = BindUDBinop(ek - 68 + 62, info.arg1, info.arg2, true, out ppmpwi); if (eXPRCALL != null) eXPR = ((!eXPRCALL.isOK()) ? eXPRCALL : BindUserBoolOp(ek, eXPRCALL)); } else eXPR = BindUDBinop(ek, info.arg1, info.arg2, false, out ppmpwi); if (eXPR == null) return null; return GetExprFactory().CreateUserDefinedBinop(ek, eXPR.type, info.arg1, info.arg2, eXPR, ppmpwi); } protected bool GetSpecialBinopSignatures(List<BinOpFullSig> prgbofs, BinOpArgInfo info) { if (info.pt1 <= PredefinedType.PT_ULONG && info.pt2 <= PredefinedType.PT_ULONG) return false; if (!GetDelBinOpSigs(prgbofs, info) && !GetEnumBinOpSigs(prgbofs, info) && !GetPtrBinOpSigs(prgbofs, info)) return GetRefEqualSigs(prgbofs, info); return true; } protected bool GetStandardAndLiftedBinopSignatures(List<BinOpFullSig> rgbofs, BinOpArgInfo info) { int num = (!GetSymbolLoader().FCanLift()) ? g_binopSignatures.Length : 0; for (int i = 0; i < g_binopSignatures.Length; i++) { BinOpSig binOpSig = g_binopSignatures[i]; if ((binOpSig.mask & info.mask) != 0) { CType cType = GetOptPDT(binOpSig.pt1, PredefinedTypes.isRequired(binOpSig.pt1)); CType cType2 = GetOptPDT(binOpSig.pt2, PredefinedTypes.isRequired(binOpSig.pt2)); if (cType != null && cType2 != null) { ConvKind convKind = GetConvKind(info.pt1, binOpSig.pt1); ConvKind convKind2 = GetConvKind(info.pt2, binOpSig.pt2); LiftFlags liftFlags = LiftFlags.None; switch (convKind) { default: VSFAIL("Shouldn't happen!"); break; case ConvKind.Explicit: if (!info.arg1.isCONSTANT_OK()) break; if (!canConvert(info.arg1, cType)) { if (i < num || !binOpSig.CanLift()) break; cType = GetSymbolLoader().GetTypeManager().GetNullable(cType); if (!canConvert(info.arg1, cType)) break; ConvKind convKind3 = GetConvKind(info.ptRaw1, binOpSig.pt1); liftFlags = ((convKind3 == ConvKind.Identity || convKind3 == ConvKind.Implicit) ? (liftFlags | LiftFlags.Lift1) : (liftFlags | LiftFlags.Convert1)); } goto case ConvKind.Implicit; case ConvKind.Unknown: if (!canConvert(info.arg1, cType)) { if (i < num || !binOpSig.CanLift()) break; cType = GetSymbolLoader().GetTypeManager().GetNullable(cType); if (!canConvert(info.arg1, cType)) break; ConvKind convKind3 = GetConvKind(info.ptRaw1, binOpSig.pt1); liftFlags = ((convKind3 == ConvKind.Identity || convKind3 == ConvKind.Implicit) ? (liftFlags | LiftFlags.Lift1) : (liftFlags | LiftFlags.Convert1)); } goto case ConvKind.Implicit; case ConvKind.Identity: if (convKind2 == ConvKind.Identity) { BinOpFullSig binOpFullSig = new BinOpFullSig(this, binOpSig); if (binOpFullSig.Type1() != null && binOpFullSig.Type2() != null) { rgbofs.Add(binOpFullSig); return true; } } goto case ConvKind.Implicit; case ConvKind.Implicit: switch (convKind2) { default: VSFAIL("Shouldn't happen!"); break; case ConvKind.Explicit: if (!info.arg2.isCONSTANT_OK()) break; if (!canConvert(info.arg2, cType2)) { if (i < num || !binOpSig.CanLift()) break; cType2 = GetSymbolLoader().GetTypeManager().GetNullable(cType2); if (!canConvert(info.arg2, cType2)) break; ConvKind convKind3 = GetConvKind(info.ptRaw2, binOpSig.pt2); liftFlags = ((convKind3 == ConvKind.Identity || convKind3 == ConvKind.Implicit) ? (liftFlags | LiftFlags.Lift2) : (liftFlags | LiftFlags.Convert2)); } goto case ConvKind.Identity; case ConvKind.Unknown: if (!canConvert(info.arg2, cType2)) { if (i < num || !binOpSig.CanLift()) break; cType2 = GetSymbolLoader().GetTypeManager().GetNullable(cType2); if (!canConvert(info.arg2, cType2)) break; ConvKind convKind3 = GetConvKind(info.ptRaw2, binOpSig.pt2); liftFlags = ((convKind3 == ConvKind.Identity || convKind3 == ConvKind.Implicit) ? (liftFlags | LiftFlags.Lift2) : (liftFlags | LiftFlags.Convert2)); } goto case ConvKind.Identity; case ConvKind.Identity: case ConvKind.Implicit: if (liftFlags != 0) { rgbofs.Add(new BinOpFullSig(cType, cType2, binOpSig.pfn, binOpSig.grfos, liftFlags, binOpSig.fnkind)); num = i + binOpSig.cbosSkip + 1; } else { rgbofs.Add(new BinOpFullSig(this, binOpSig)); i += binOpSig.cbosSkip; } break; case ConvKind.None: break; } break; case ConvKind.None: break; } } } } return false; } protected int FindBestSignatureInList(List<BinOpFullSig> binopSignatures, BinOpArgInfo info) { if (binopSignatures.Count == 1) return 0; int num = 0; for (int i = 1; i < binopSignatures.Count; i++) { if (num < 0) num = i; else { int num2 = WhichBofsIsBetter(binopSignatures[num], binopSignatures[i], info.type1, info.type2); if (num2 == 0) num = -1; else if (num2 > 0) { num = i; } } } if (num == -1) return -1; for (int i = 0; i < binopSignatures.Count; i++) { if (i != num && WhichBofsIsBetter(binopSignatures[num], binopSignatures[i], info.type1, info.type2) >= 0) return -1; } return num; } protected EXPRBINOP bindNullEqualityComparison(ExpressionKind ek, BinOpArgInfo info) { EXPR arg = info.arg1; EXPR p = info.arg2; if (info.binopKind == BinOpKind.Equal) { CType reqPDT = GetReqPDT(PredefinedType.PT_BOOL); EXPRBINOP eXPRBINOP = null; if (info.type1.IsNullableType() && info.type2.IsNullType()) { p = GetExprFactory().CreateZeroInit(info.type1); eXPRBINOP = GetExprFactory().CreateBinop(ek, reqPDT, arg, p); } if (info.type1.IsNullType() && info.type2.IsNullableType()) { arg = GetExprFactory().CreateZeroInit(info.type2); eXPRBINOP = GetExprFactory().CreateBinop(ek, reqPDT, arg, p); } if (eXPRBINOP != null) { eXPRBINOP.isLifted = true; return eXPRBINOP; } } EXPR expr = BadOperatorTypesError(ek, info.arg1, info.arg2, GetTypes().GetErrorSym()); return expr.asBIN(); } public EXPR BindStandardBinop(ExpressionKind ek, EXPR arg1, EXPR arg2) { EXPRFLAG flags = (EXPRFLAG)0; BinOpArgInfo binOpArgInfo = new BinOpArgInfo(arg1, arg2); if (!GetBinopKindAndFlags(ek, out binOpArgInfo.binopKind, out flags)) return BadOperatorTypesError(ek, arg1, arg2); binOpArgInfo.mask = (BinOpMask)(1 << (int)binOpArgInfo.binopKind); List<BinOpFullSig> list = new List<BinOpFullSig>(); int num = -1; EXPR eXPR = bindUserDefinedBinOp(ek, binOpArgInfo); if (eXPR != null) return eXPR; bool flag = GetSpecialBinopSignatures(list, binOpArgInfo); if (!flag) flag = GetStandardAndLiftedBinopSignatures(list, binOpArgInfo); if (flag) num = list.Count - 1; else { if (list.Count == 0) return bindNullEqualityComparison(ek, binOpArgInfo); num = FindBestSignatureInList(list, binOpArgInfo); if (num < 0) return ambiguousOperatorError(ek, arg1, arg2); } return BindStandardBinopCore(binOpArgInfo, list[num], ek, flags); } protected EXPR BindStandardBinopCore(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags) { if (bofs.pfn == null) return BadOperatorTypesError(ek, info.arg1, info.arg2); if (!bofs.isLifted() || !bofs.AutoLift()) { EXPR eXPR = info.arg1; EXPR eXPR2 = info.arg2; if (bofs.ConvertOperandsBeforeBinding()) { eXPR = mustConvert(eXPR, bofs.Type1()); eXPR2 = mustConvert(eXPR2, bofs.Type2()); } if (bofs.fnkind == BinOpFuncKind.BoolBitwiseOp) return BindBoolBitwiseOp(ek, flags, eXPR, eXPR2, bofs); return bofs.pfn(ek, flags, eXPR, eXPR2); } return BindLiftedStandardBinOp(info, bofs, ek, flags); } private EXPR BindLiftedStandardBinOp(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags) { EXPR arg = info.arg1; EXPR arg2 = info.arg2; EXPR ppLiftedArgument = null; EXPR ppLiftedArgument2 = null; EXPR ppNonLiftedArgument = null; EXPR ppNonLiftedArgument2 = null; EXPR expr = null; CType cType = null; LiftArgument(arg, bofs.Type1(), bofs.ConvertFirst(), out ppLiftedArgument, out ppNonLiftedArgument); LiftArgument(arg2, bofs.Type2(), bofs.ConvertSecond(), out ppLiftedArgument2, out ppNonLiftedArgument2); if (!ppNonLiftedArgument.isNull() && !ppNonLiftedArgument2.isNull()) expr = bofs.pfn(ek, flags, ppNonLiftedArgument, ppNonLiftedArgument2); if (info.binopKind == BinOpKind.Compare || info.binopKind == BinOpKind.Equal) cType = GetReqPDT(PredefinedType.PT_BOOL); else { cType = ((bofs.fnkind != BinOpFuncKind.EnumBinOp) ? ppLiftedArgument.type : GetEnumBinOpType(ek, ppNonLiftedArgument.type, ppNonLiftedArgument2.type, out AggregateType _)); cType = (cType.IsNullableType() ? cType : GetSymbolLoader().GetTypeManager().GetNullable(cType)); } EXPRBINOP eXPRBINOP = GetExprFactory().CreateBinop(ek, cType, ppLiftedArgument, ppLiftedArgument2); mustCast(expr, cType, (CONVERTTYPE)0); eXPRBINOP.isLifted = true; eXPRBINOP.flags |= flags; return eXPRBINOP; } private void LiftArgument(EXPR pArgument, CType pParameterType, bool bConvertBeforeLift, out EXPR ppLiftedArgument, out EXPR ppNonLiftedArgument) { EXPR eXPR = mustConvert(pArgument, pParameterType); if (eXPR != pArgument) MarkAsIntermediateConversion(eXPR); EXPR expr = pArgument; if (pParameterType.IsNullableType()) { if (expr.isNull()) expr = mustCast(expr, pParameterType); expr = mustCast(expr, pParameterType.AsNullableType().GetUnderlyingType()); if (bConvertBeforeLift) MarkAsIntermediateConversion(expr); } else expr = eXPR; ppLiftedArgument = eXPR; ppNonLiftedArgument = expr; } protected bool GetDelBinOpSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info) { if (!info.ValidForDelegate()) return false; if (!info.type1.isDelegateType() && !info.type2.isDelegateType()) return false; if ((info.mask & BinOpMask.Equal) != 0 && (info.type1.IsBoundLambdaType() || info.type2.IsBoundLambdaType())) return false; if (info.type1 == info.type2) { prgbofs.Add(new BinOpFullSig(info.type1, info.type2, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp)); return true; } bool flag = info.type2.isDelegateType() && canConvert(info.arg1, info.type2); bool flag2 = info.type1.isDelegateType() && canConvert(info.arg2, info.type1); if (flag) prgbofs.Add(new BinOpFullSig(info.type2, info.type2, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp)); if (flag2) prgbofs.Add(new BinOpFullSig(info.type1, info.type1, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp)); return false; } private bool CanConvertArg1(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt, out CType ptypeSig1, out CType ptypeSig2) { ptypeSig1 = null; ptypeSig2 = null; if (canConvert(info.arg1, typeDst)) pgrflt = LiftFlags.None; else { pgrflt = LiftFlags.None; if (!GetSymbolLoader().FCanLift()) return false; typeDst = GetSymbolLoader().GetTypeManager().GetNullable(typeDst); if (!canConvert(info.arg1, typeDst)) return false; pgrflt = LiftFlags.Convert1; } ptypeSig1 = typeDst; if (info.type2.IsNullableType()) { pgrflt |= LiftFlags.Lift2; ptypeSig2 = GetSymbolLoader().GetTypeManager().GetNullable(info.typeRaw2); } else ptypeSig2 = info.typeRaw2; return true; } private bool CanConvertArg2(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt, out CType ptypeSig1, out CType ptypeSig2) { ptypeSig1 = null; ptypeSig2 = null; if (canConvert(info.arg2, typeDst)) pgrflt = LiftFlags.None; else { pgrflt = LiftFlags.None; if (!GetSymbolLoader().FCanLift()) return false; typeDst = GetSymbolLoader().GetTypeManager().GetNullable(typeDst); if (!canConvert(info.arg2, typeDst)) return false; pgrflt = LiftFlags.Convert2; } ptypeSig2 = typeDst; if (info.type1.IsNullableType()) { pgrflt |= LiftFlags.Lift1; ptypeSig1 = GetSymbolLoader().GetTypeManager().GetNullable(info.typeRaw1); } else ptypeSig1 = info.typeRaw1; return true; } private void RecordBinOpSigFromArgs(List<BinOpFullSig> prgbofs, BinOpArgInfo info) { LiftFlags liftFlags = LiftFlags.None; CType type; if (info.type1 != info.typeRaw1) { liftFlags |= LiftFlags.Lift1; type = GetSymbolLoader().GetTypeManager().GetNullable(info.typeRaw1); } else type = info.typeRaw1; CType type2; if (info.type2 != info.typeRaw2) { liftFlags |= LiftFlags.Lift2; type2 = GetSymbolLoader().GetTypeManager().GetNullable(info.typeRaw2); } else type2 = info.typeRaw2; prgbofs.Add(new BinOpFullSig(type, type2, BindEnumBinOp, OpSigFlags.Value, liftFlags, BinOpFuncKind.EnumBinOp)); } protected bool GetEnumBinOpSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info) { if (!info.typeRaw1.isEnumType() && !info.typeRaw2.isEnumType()) return false; CType ptypeSig = null; CType ptypeSig2 = null; LiftFlags pgrflt = LiftFlags.None; if (info.typeRaw1 == info.typeRaw2) { if (!info.ValidForEnum()) return false; RecordBinOpSigFromArgs(prgbofs, info); return true; } if ((!info.typeRaw1.isEnumType()) ? (info.typeRaw1 == info.typeRaw2.underlyingEnumType() && info.ValidForUnderlyingTypeAndEnum()) : (info.typeRaw2 == info.typeRaw1.underlyingEnumType() && info.ValidForEnumAndUnderlyingType())) { RecordBinOpSigFromArgs(prgbofs, info); return true; } if ((!info.typeRaw1.isEnumType()) ? ((info.ValidForEnum() && CanConvertArg1(info, info.typeRaw2, out pgrflt, out ptypeSig, out ptypeSig2)) || (info.ValidForEnumAndUnderlyingType() && CanConvertArg1(info, info.typeRaw2.underlyingEnumType(), out pgrflt, out ptypeSig, out ptypeSig2))) : ((info.ValidForEnum() && CanConvertArg2(info, info.typeRaw1, out pgrflt, out ptypeSig, out ptypeSig2)) || (info.ValidForEnumAndUnderlyingType() && CanConvertArg2(info, info.typeRaw1.underlyingEnumType(), out pgrflt, out ptypeSig, out ptypeSig2)))) prgbofs.Add(new BinOpFullSig(ptypeSig, ptypeSig2, BindEnumBinOp, OpSigFlags.Value, pgrflt, BinOpFuncKind.EnumBinOp)); return false; } protected bool GetPtrBinOpSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info) { if (!info.type1.IsPointerType() && !info.type2.IsPointerType()) return false; if (info.type1.IsPointerType() && info.type2.IsPointerType()) { if (info.ValidForVoidPointer()) { prgbofs.Add(new BinOpFullSig(info.type1, info.type2, BindPtrCmpOp, OpSigFlags.None, LiftFlags.None, BinOpFuncKind.PtrCmpOp)); return true; } if (info.type1 == info.type2 && info.ValidForPointer()) { prgbofs.Add(new BinOpFullSig(info.type1, info.type2, BindPtrBinOp, OpSigFlags.None, LiftFlags.None, BinOpFuncKind.PtrBinOp)); return true; } return false; } if (info.type1.IsPointerType()) { if (info.type2.IsNullType()) { if (!info.ValidForVoidPointer()) return false; prgbofs.Add(new BinOpFullSig(info.type1, info.type1, BindPtrCmpOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.PtrCmpOp)); return true; } if (!info.ValidForPointerAndNumber()) return false; for (uint num = 0; num < s_rgptIntOp.Length; num++) { CType reqPDT; if (canConvert(info.arg2, reqPDT = GetReqPDT(s_rgptIntOp[num]))) { prgbofs.Add(new BinOpFullSig(info.type1, reqPDT, BindPtrBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.PtrBinOp)); return true; } } return false; } if (info.type1.IsNullType()) { if (!info.ValidForVoidPointer()) return false; prgbofs.Add(new BinOpFullSig(info.type2, info.type2, BindPtrCmpOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.PtrCmpOp)); return true; } if (!info.ValidForNumberAndPointer()) return false; for (uint num2 = 0; num2 < s_rgptIntOp.Length; num2++) { CType reqPDT; if (canConvert(info.arg1, reqPDT = GetReqPDT(s_rgptIntOp[num2]))) { prgbofs.Add(new BinOpFullSig(reqPDT, info.type2, BindPtrBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.PtrBinOp)); return true; } } return false; } protected bool GetRefEqualSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info) { if (info.mask != BinOpMask.Equal) return false; if (info.type1 != info.typeRaw1 || info.type2 != info.typeRaw2) return false; bool result = false; CType cType = info.type1; CType cType2 = info.type2; CType reqPDT = GetReqPDT(PredefinedType.PT_OBJECT); CType cType3 = null; if (cType.IsNullType() && cType2.IsNullType()) { cType3 = reqPDT; result = true; } else { CType reqPDT2 = GetReqPDT(PredefinedType.PT_DELEGATE); if (canConvert(info.arg1, reqPDT2) && canConvert(info.arg2, reqPDT2) && !cType.isDelegateType() && !cType2.isDelegateType()) prgbofs.Add(new BinOpFullSig(reqPDT2, reqPDT2, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp)); FUNDTYPE fUNDTYPE = cType.fundType(); FUNDTYPE fUNDTYPE2 = cType2.fundType(); switch (fUNDTYPE) { default: return false; case FUNDTYPE.FT_VAR: if (cType.AsTypeParameterType().IsValueType() || (!cType.AsTypeParameterType().IsReferenceType() && !cType2.IsNullType())) return false; cType = cType.AsTypeParameterType().GetEffectiveBaseClass(); break; case FUNDTYPE.FT_REF: break; } if (cType2.IsNullType()) { result = true; cType3 = reqPDT; } else { switch (fUNDTYPE2) { default: return false; case FUNDTYPE.FT_VAR: if (cType2.AsTypeParameterType().IsValueType() || (!cType2.AsTypeParameterType().IsReferenceType() && !cType.IsNullType())) return false; cType2 = cType2.AsTypeParameterType().GetEffectiveBaseClass(); break; case FUNDTYPE.FT_REF: break; } if (cType.IsNullType()) { result = true; cType3 = reqPDT; } else { if (!canCast(cType, cType2, CONVERTTYPE.NOUDC) && !canCast(cType2, cType, CONVERTTYPE.NOUDC)) return false; if (cType.isInterfaceType() || cType.isPredefType(PredefinedType.PT_STRING) || GetSymbolLoader().HasBaseConversion(cType, reqPDT2)) cType = reqPDT; else if (cType.IsArrayType()) { cType = GetReqPDT(PredefinedType.PT_ARRAY); } else if (!cType.isClassType()) { return false; } if (cType2.isInterfaceType() || cType2.isPredefType(PredefinedType.PT_STRING) || GetSymbolLoader().HasBaseConversion(cType2, reqPDT2)) cType2 = reqPDT; else if (cType2.IsArrayType()) { cType2 = GetReqPDT(PredefinedType.PT_ARRAY); } else if (!cType2.isClassType()) { return false; } if (GetSymbolLoader().HasBaseConversion(cType2, cType)) cType3 = cType; else if (GetSymbolLoader().HasBaseConversion(cType, cType2)) { cType3 = cType2; } } } } prgbofs.Add(new BinOpFullSig(cType3, cType3, BindRefCmpOp, OpSigFlags.None, LiftFlags.None, BinOpFuncKind.RefCmpOp)); return result; } private int WhichBofsIsBetter(BinOpFullSig bofs1, BinOpFullSig bofs2, CType type1, CType type2) { BetterType betterType; BetterType betterType2; if (bofs1.FPreDef() && bofs2.FPreDef()) { betterType = WhichTypeIsBetter(bofs1.pt1, bofs2.pt1, type1); betterType2 = WhichTypeIsBetter(bofs1.pt2, bofs2.pt2, type2); } else { betterType = WhichTypeIsBetter(bofs1.Type1(), bofs2.Type1(), type1); betterType2 = WhichTypeIsBetter(bofs1.Type2(), bofs2.Type2(), type2); } int num = 0; switch (betterType) { default: VSFAIL("Shouldn't happen"); break; case BetterType.Left: num--; break; case BetterType.Right: num++; break; case BetterType.Same: case BetterType.Neither: break; } switch (betterType2) { default: VSFAIL("Shouldn't happen"); break; case BetterType.Left: num--; break; case BetterType.Right: num++; break; case BetterType.Same: case BetterType.Neither: break; } return num; } private static bool CalculateExprAndUnaryOpKinds(OperatorKind op, bool bChecked, out ExpressionKind ek, out UnaOpKind uok, out EXPRFLAG flags) { flags = (EXPRFLAG)0; ek = ExpressionKind.EK_BLOCK; uok = UnaOpKind.Plus; switch (op) { case OperatorKind.OP_UPLUS: uok = UnaOpKind.Plus; ek = ExpressionKind.EK_UPLUS; break; case OperatorKind.OP_NEG: if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.Minus; ek = ExpressionKind.EK_NEG; break; case OperatorKind.OP_BITNOT: uok = UnaOpKind.Tilde; ek = ExpressionKind.EK_BITNOT; break; case OperatorKind.OP_LOGNOT: uok = UnaOpKind.Bang; ek = ExpressionKind.EK_LOGNOT; break; case OperatorKind.OP_POSTINC: flags |= EXPRFLAG.EXF_OPERATOR; if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.EK_ADD; break; case OperatorKind.OP_PREINC: if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.EK_ADD; break; case OperatorKind.OP_POSTDEC: flags |= EXPRFLAG.EXF_OPERATOR; if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.EK_SUB; break; case OperatorKind.OP_PREDEC: if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.EK_SUB; break; default: VSFAIL("Bad op"); return false; } return true; } public EXPR BindStandardUnaryOperator(OperatorKind op, EXPR pArgument) { RETAILVERIFY(pArgument != null); if (pArgument.type == null || !CalculateExprAndUnaryOpKinds(op, Context.CheckedNormal, out ExpressionKind ek, out UnaOpKind uok, out EXPRFLAG flags)) return BadOperatorTypesError(ExpressionKind.EK_UNARYOP, pArgument, null); UnaOpMask unaryOpMask = (UnaOpMask)(1 << (int)uok); CType type = pArgument.type; List<UnaOpFullSig> list = new List<UnaOpFullSig>(); EXPR ppResult = null; UnaryOperatorSignatureFindResult unaryOperatorSignatureFindResult = PopulateSignatureList(pArgument, uok, unaryOpMask, ek, flags, list, out ppResult); int num = list.Count - 1; switch (unaryOperatorSignatureFindResult) { case UnaryOperatorSignatureFindResult.Return: return ppResult; default: if (!FindApplicableSignatures(pArgument, unaryOpMask, list)) { if (list.Count == 0) return BadOperatorTypesError(ek, pArgument, null); num = 0; if (list.Count != 1) { for (int i = 1; i < list.Count; i++) { if (num < 0) num = i; else { int num2 = WhichUofsIsBetter(list[num], list[i], type); if (num2 == 0) num = -1; else if (num2 > 0) { num = i; } } } if (num < 0) return ambiguousOperatorError(ek, pArgument, null); for (int j = 0; j < list.Count; j++) { if (j != num && WhichUofsIsBetter(list[num], list[j], type) >= 0) return ambiguousOperatorError(ek, pArgument, null); } } } else num = list.Count - 1; break; case UnaryOperatorSignatureFindResult.Match: break; } RETAILVERIFY(num < list.Count); UnaOpFullSig unaOpFullSig = list[num]; if (unaOpFullSig.pfn == null) { if (uok == UnaOpKind.IncDec) return BindIncOp(ek, flags, pArgument, unaOpFullSig); return BadOperatorTypesError(ek, pArgument, null); } if (unaOpFullSig.isLifted()) return BindLiftedStandardUnop(ek, flags, pArgument, unaOpFullSig); EXPR eXPR = tryConvert(pArgument, unaOpFullSig.GetType()); if (eXPR == null) eXPR = mustCast(pArgument, unaOpFullSig.GetType(), CONVERTTYPE.NOUDC); return unaOpFullSig.pfn(ek, flags, eXPR); } private UnaryOperatorSignatureFindResult PopulateSignatureList(EXPR pArgument, UnaOpKind unaryOpKind, UnaOpMask unaryOpMask, ExpressionKind exprKind, EXPRFLAG flags, List<UnaOpFullSig> pSignatures, out EXPR ppResult) { ppResult = null; CType type = pArgument.type; CType cType = type.StripNubs(); PredefinedType predefinedType = cType.isPredefined() ? cType.getPredefType() : PredefinedType.PT_COUNT; if (predefinedType > PredefinedType.PT_ULONG) { if (cType.isEnumType()) { if ((unaryOpMask & (UnaOpMask)20) != 0) { LiftFlags grflt = LiftFlags.None; CType cType2 = type; if (cType2.IsNullableType()) { if (cType2.AsNullableType().GetUnderlyingType() != cType) cType2 = GetSymbolLoader().GetTypeManager().GetNullable(cType); grflt = LiftFlags.Lift1; } if (unaryOpKind == UnaOpKind.Tilde) pSignatures.Add(new UnaOpFullSig(cType2.getAggregate().GetUnderlyingType(), BindEnumUnaOp, grflt, UnaOpFuncKind.EnumUnaOp)); else pSignatures.Add(new UnaOpFullSig(cType2.getAggregate().GetUnderlyingType(), null, grflt, UnaOpFuncKind.None)); return UnaryOperatorSignatureFindResult.Match; } } else if (unaryOpKind == UnaOpKind.IncDec) { if (type.IsPointerType()) { pSignatures.Add(new UnaOpFullSig(type, null, LiftFlags.None, UnaOpFuncKind.None)); return UnaryOperatorSignatureFindResult.Match; } EXPRMULTIGET eXPRMULTIGET = GetExprFactory().CreateMultiGet((EXPRFLAG)0, type, null); EXPR eXPR = bindUDUnop(exprKind - 55 + 46, eXPRMULTIGET); if (eXPR != null) { if (eXPR.type != null && !eXPR.type.IsErrorType() && eXPR.type != type) eXPR = mustConvert(eXPR, type); EXPRMULTI eXPRMULTI = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, type, pArgument, eXPR); eXPRMULTIGET.SetOptionalMulti(eXPRMULTI); if (!checkLvalue(pArgument, CheckLvalueKind.Increment)) eXPRMULTI.SetError(); ppResult = eXPRMULTI; return UnaryOperatorSignatureFindResult.Return; } } else { EXPR eXPR2 = bindUDUnop(exprKind, pArgument); if (eXPR2 != null) { ppResult = eXPR2; return UnaryOperatorSignatureFindResult.Return; } } } return UnaryOperatorSignatureFindResult.Continue; } private bool FindApplicableSignatures(EXPR pArgument, UnaOpMask unaryOpMask, List<UnaOpFullSig> pSignatures) { long num = (!GetSymbolLoader().FCanLift()) ? g_rguos.Length : 0; CType type = pArgument.type; CType cType = type.StripNubs(); PredefinedType ptSrc = type.isPredefined() ? type.getPredefType() : PredefinedType.PT_COUNT; PredefinedType ptSrc2 = cType.isPredefined() ? cType.getPredefType() : PredefinedType.PT_COUNT; for (int i = 0; i < g_rguos.Length; i++) { UnaOpSig unaOpSig = g_rguos[i]; if ((unaOpSig.grfuom & unaryOpMask) != 0) { ConvKind convKind = GetConvKind(ptSrc, g_rguos[i].pt); CType cType2 = null; switch (convKind) { default: VSFAIL("Shouldn't happen!"); break; case ConvKind.Explicit: if (!pArgument.isCONSTANT_OK()) break; if (!canConvert(pArgument, cType2 = GetOptPDT(unaOpSig.pt))) { if (i < num) break; cType2 = GetSymbolLoader().GetTypeManager().GetNullable(cType2); if (!canConvert(pArgument, cType2)) break; } goto case ConvKind.Implicit; case ConvKind.Unknown: if (!canConvert(pArgument, cType2 = GetOptPDT(unaOpSig.pt))) { if (i < num) break; cType2 = GetSymbolLoader().GetTypeManager().GetNullable(cType2); if (!canConvert(pArgument, cType2)) break; } goto case ConvKind.Implicit; case ConvKind.Identity: { UnaOpFullSig unaOpFullSig = new UnaOpFullSig(this, unaOpSig); if (unaOpFullSig.GetType() != null) { pSignatures.Add(unaOpFullSig); return true; } goto case ConvKind.Implicit; } case ConvKind.Implicit: if (cType2 != null && cType2.IsNullableType()) { LiftFlags liftFlags = LiftFlags.None; ConvKind convKind2 = GetConvKind(ptSrc2, unaOpSig.pt); liftFlags = ((convKind2 == ConvKind.Identity || convKind2 == ConvKind.Implicit) ? (liftFlags | LiftFlags.Lift1) : (liftFlags | LiftFlags.Convert1)); pSignatures.Add(new UnaOpFullSig(cType2, unaOpSig.pfn, liftFlags, unaOpSig.fnkind)); num = i + unaOpSig.cuosSkip + 1; } else { UnaOpFullSig unaOpFullSig2 = new UnaOpFullSig(this, unaOpSig); if (unaOpFullSig2.GetType() != null) pSignatures.Add(unaOpFullSig2); i += unaOpSig.cuosSkip; } break; case ConvKind.None: break; } } } return false; } private EXPR BindLiftedStandardUnop(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs) { NullableType nullableType = uofs.GetType().AsNullableType(); if (arg.type.IsNullType()) return BadOperatorTypesError(ek, arg, null, nullableType); EXPR ppLiftedArgument = null; EXPR ppNonLiftedArgument = null; LiftArgument(arg, uofs.GetType(), uofs.Convert(), out ppLiftedArgument, out ppNonLiftedArgument); EXPR expr = uofs.pfn(ek, flags, ppNonLiftedArgument); EXPRUNARYOP eXPRUNARYOP = GetExprFactory().CreateUnaryOp(ek, nullableType, ppLiftedArgument); mustCast(expr, nullableType, (CONVERTTYPE)0); eXPRUNARYOP.flags |= flags; return eXPRUNARYOP; } private int WhichUofsIsBetter(UnaOpFullSig uofs1, UnaOpFullSig uofs2, CType typeArg) { switch ((!uofs1.FPreDef() || !uofs2.FPreDef()) ? WhichTypeIsBetter(uofs1.GetType(), uofs2.GetType(), typeArg) : WhichTypeIsBetter(uofs1.pt, uofs2.pt, typeArg)) { default: VSFAIL("Shouldn't happen"); return 0; case BetterType.Same: case BetterType.Neither: return 0; case BetterType.Left: return -1; case BetterType.Right: return 1; } } private EXPR BindIntBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { return BindIntOp(ek, flags, arg1, arg2, arg1.type.getPredefType()); } private EXPR BindIntUnaOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg) { return BindIntOp(ek, flags, arg, null, arg.type.getPredefType()); } private EXPR BindRealBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { return bindFloatOp(ek, flags, arg1, arg2); } private EXPR BindRealUnaOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg) { return bindFloatOp(ek, flags, arg, null); } private EXPR BindIncOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs) { if (!checkLvalue(arg, CheckLvalueKind.Increment)) { EXPR eXPR = GetExprFactory().CreateBinop(ek, arg.type, arg, null); eXPR.SetError(); return eXPR; } CType cType = uofs.GetType().StripNubs(); FUNDTYPE fUNDTYPE = cType.fundType(); if (fUNDTYPE == FUNDTYPE.FT_R8 || fUNDTYPE == FUNDTYPE.FT_R4) flags = (EXPRFLAG)(-262145); if (uofs.isLifted()) return BindLiftedIncOp(ek, flags, arg, uofs); return BindNonliftedIncOp(ek, flags, arg, uofs); } private EXPR BindIncOpCore(ExpressionKind ek, EXPRFLAG flags, EXPR exprVal, CType type) { CONSTVAL cONSTVAL = new CONSTVAL(); EXPR pExprResult = null; if (type.isEnumType() && type.fundType() > FUNDTYPE.FT_U8) type = GetReqPDT(PredefinedType.PT_INT); FUNDTYPE fUNDTYPE = type.fundType(); CType typeTmp = type; switch (fUNDTYPE) { default: { ek = ((ek == ExpressionKind.EK_ADD) ? ExpressionKind.EK_DECIMALINC : ExpressionKind.EK_DECIMALDEC); PREDEFMETH predefMeth = (ek == ExpressionKind.EK_DECIMALINC) ? PREDEFMETH.PM_DECIMAL_OPINCREMENT : PREDEFMETH.PM_DECIMAL_OPDECREMENT; return CreateUnaryOpForPredefMethodCall(ek, predefMeth, type, exprVal); } case FUNDTYPE.FT_PTR: cONSTVAL.iVal = 1; return BindPtrBinOp(ek, flags, exprVal, GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), cONSTVAL)); case FUNDTYPE.FT_I1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_U2: typeTmp = GetReqPDT(PredefinedType.PT_INT); cONSTVAL.iVal = 1; return LScalar(ek, flags, exprVal, type, cONSTVAL, pExprResult, typeTmp); case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: cONSTVAL.iVal = 1; return LScalar(ek, flags, exprVal, type, cONSTVAL, pExprResult, typeTmp); case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: cONSTVAL = GetExprConstants().Create(1); return LScalar(ek, flags, exprVal, type, cONSTVAL, pExprResult, typeTmp); case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: cONSTVAL = GetExprConstants().Create(1); return LScalar(ek, flags, exprVal, type, cONSTVAL, pExprResult, typeTmp); } } private EXPR LScalar(ExpressionKind ek, EXPRFLAG flags, EXPR exprVal, CType type, CONSTVAL cv, EXPR pExprResult, CType typeTmp) { CType cType = type; if (cType.isEnumType()) cType = cType.underlyingEnumType(); pExprResult = GetExprFactory().CreateBinop(ek, typeTmp, exprVal, GetExprFactory().CreateConstant(cType, cv)); pExprResult.flags |= flags; if (typeTmp != type) pExprResult = mustCast(pExprResult, type, CONVERTTYPE.NOUDC); return pExprResult; } private EXPRMULTI BindNonliftedIncOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs) { EXPRMULTIGET eXPRMULTIGET = GetExprFactory().CreateMultiGet(EXPRFLAG.EXF_ASSGOP, arg.type, null); EXPR expr = eXPRMULTIGET; CType type = uofs.GetType(); expr = mustCast(expr, type); expr = BindIncOpCore(ek, flags, expr, type); EXPR pOp = mustCast(expr, arg.type, CONVERTTYPE.NOUDC); EXPRMULTI eXPRMULTI = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.type, arg, pOp); eXPRMULTIGET.SetOptionalMulti(eXPRMULTI); return eXPRMULTI; } private EXPRMULTI BindLiftedIncOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs) { NullableType nullableType = uofs.GetType().AsNullableType(); EXPRMULTIGET eXPRMULTIGET = GetExprFactory().CreateMultiGet(EXPRFLAG.EXF_ASSGOP, arg.type, null); EXPR eXPR = eXPRMULTIGET; EXPR eXPR2 = null; EXPR expr = eXPR; expr = mustCast(expr, nullableType.GetUnderlyingType()); eXPR2 = BindIncOpCore(ek, flags, expr, nullableType.GetUnderlyingType()); eXPR = mustCast(eXPR, nullableType); EXPRUNARYOP eXPRUNARYOP = GetExprFactory().CreateUnaryOp((ek == ExpressionKind.EK_ADD) ? ExpressionKind.EK_INC : ExpressionKind.EK_DEC, arg.type, eXPR); mustCast(mustCast(eXPR2, nullableType), arg.type); eXPRUNARYOP.flags |= flags; EXPRMULTI eXPRMULTI = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.type, arg, eXPRUNARYOP); eXPRMULTIGET.SetOptionalMulti(eXPRMULTI); return eXPRMULTI; } private EXPR BindDecBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { CType optPDT = GetOptPDT(PredefinedType.PT_DECIMAL); EXPR const = arg1.GetConst(); EXPR const2 = arg2.GetConst(); CType pType = null; switch (ek) { default: VSFAIL("Bad kind"); break; case ExpressionKind.EK_ADD: case ExpressionKind.EK_SUB: case ExpressionKind.EK_MUL: case ExpressionKind.EK_DIV: case ExpressionKind.EK_MOD: pType = optPDT; break; case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: pType = GetReqPDT(PredefinedType.PT_BOOL); break; } if (const2 == null || const == null) return GetExprFactory().CreateBinop(ek, pType, arg1, arg2); decimal value = default(decimal); bool value2 = false; bool flag = false; decimal decVal = const.asCONSTANT().getVal().decVal; decimal decVal2 = const2.asCONSTANT().getVal().decVal; switch (ek) { case ExpressionKind.EK_ADD: value = decVal + decVal2; break; case ExpressionKind.EK_SUB: value = decVal - decVal2; break; case ExpressionKind.EK_MUL: value = decVal * decVal2; break; case ExpressionKind.EK_DIV: if (decVal2 == decimal.Zero) { GetErrorContext().Error(ErrorCode.ERR_IntDivByZero, Array.Empty<ErrArg>()); EXPR eXPR2 = GetExprFactory().CreateBinop(ek, optPDT, arg1, arg2); eXPR2.SetError(); return eXPR2; } value = decVal / decVal2; break; case ExpressionKind.EK_MOD: { if (decVal2 == decimal.Zero) { GetErrorContext().Error(ErrorCode.ERR_IntDivByZero, Array.Empty<ErrArg>()); EXPR eXPR = GetExprFactory().CreateBinop(ek, optPDT, arg1, arg2); eXPR.SetError(); return eXPR; } decimal num = decVal % decVal2; break; } default: flag = true; switch (ek) { default: VSFAIL("Bad ek"); break; case ExpressionKind.EK_EQ: value2 = (decVal == decVal2); break; case ExpressionKind.EK_NE: value2 = (decVal != decVal2); break; case ExpressionKind.EK_LE: value2 = (decVal <= decVal2); break; case ExpressionKind.EK_LT: value2 = (decVal < decVal2); break; case ExpressionKind.EK_GE: value2 = (decVal >= decVal2); break; case ExpressionKind.EK_GT: value2 = (decVal > decVal2); break; } break; } CONSTVAL constVal; if (!flag) { constVal = GetExprConstants().Create(value); return GetExprFactory().CreateConstant(optPDT, constVal); } constVal = ConstValFactory.GetBool(value2); return GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_BOOL), constVal); } private EXPR BindDecUnaOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg) { CType optPDT = GetOptPDT(PredefinedType.PT_DECIMAL); ek = ((ek == ExpressionKind.EK_NEG) ? ExpressionKind.EK_DECIMALNEG : ExpressionKind.EK_UPLUS); EXPR const = arg.GetConst(); if (const == null) { if (ek == ExpressionKind.EK_DECIMALNEG) { PREDEFMETH predefMeth = PREDEFMETH.PM_DECIMAL_OPUNARYMINUS; return CreateUnaryOpForPredefMethodCall(ek, predefMeth, optPDT, arg); } return GetExprFactory().CreateUnaryOp(ek, optPDT, arg); } if (ek == ExpressionKind.EK_UPLUS) return arg; decimal decVal = const.asCONSTANT().getVal().decVal; decVal *= decimal.MinusOne; CONSTVAL constVal = GetExprConstants().Create(decVal); return GetExprFactory().CreateConstant(optPDT, constVal); } private EXPR BindStrBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { return bindStringConcat(arg1, arg2); } private EXPR BindShiftOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { PredefinedType predefType = arg1.type.getPredefType(); EXPR const = arg1.GetConst(); EXPR const2 = arg2.GetConst(); if (const == null || const2 == null) return GetExprFactory().CreateBinop(ek, arg1.type, arg1, arg2); CONSTVAL cONSTVAL = new CONSTVAL(); int num = (predefType == PredefinedType.PT_LONG || predefType == PredefinedType.PT_ULONG) ? 63 : 31; cONSTVAL.iVal = (const2.asCONSTANT().getVal().iVal & num); num = cONSTVAL.iVal; if (predefType == PredefinedType.PT_LONG || predefType == PredefinedType.PT_ULONG) { ulong ulongVal = const.asCONSTANT().getVal().ulongVal; ulong value; switch (ek) { case ExpressionKind.EK_LSHIFT: value = ulongVal << num; break; case ExpressionKind.EK_RSHIFT: value = (ulong)((predefType == PredefinedType.PT_LONG) ? ((long)ulongVal >> num) : ((long)(ulongVal >> num))); break; default: VSFAIL("Unknown op"); value = 0; break; } cONSTVAL = GetExprConstants().Create(value); } else { uint uiVal = const.asCONSTANT().getVal().uiVal; switch (ek) { case ExpressionKind.EK_LSHIFT: cONSTVAL.uiVal = uiVal << num; break; case ExpressionKind.EK_RSHIFT: cONSTVAL.uiVal = (uint)((predefType == PredefinedType.PT_INT) ? ((int)uiVal >> num) : ((int)(uiVal >> num))); break; default: VSFAIL("Unknown op"); cONSTVAL.uiVal = 0; break; } } return GetExprFactory().CreateConstant(GetReqPDT(predefType), cONSTVAL); } private EXPR BindBoolBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { return GetExprFactory().CreateBinop(ek, GetReqPDT(PredefinedType.PT_BOOL), arg1, arg2); } private EXPR BindBoolBitwiseOp(ExpressionKind ek, EXPRFLAG flags, EXPR expr1, EXPR expr2, BinOpFullSig bofs) { if (expr1.type.IsNullableType() || expr2.type.IsNullableType()) { CType reqPDT = GetReqPDT(PredefinedType.PT_BOOL); CType nullable = GetSymbolLoader().GetTypeManager().GetNullable(reqPDT); EXPR eXPR = CNullable.StripNullableConstructor(expr1); EXPR eXPR2 = CNullable.StripNullableConstructor(expr2); EXPR eXPR3 = null; if (!eXPR.type.IsNullableType() && !eXPR2.type.IsNullableType()) eXPR3 = BindBoolBinOp(ek, flags, eXPR, eXPR2); EXPRBINOP eXPRBINOP = GetExprFactory().CreateBinop(ek, nullable, expr1, expr2); if (eXPR3 != null) mustCast(eXPR3, nullable, (CONVERTTYPE)0); eXPRBINOP.isLifted = true; eXPRBINOP.flags |= flags; return eXPRBINOP; } return BindBoolBinOp(ek, flags, expr1, expr2); } private EXPR BindLiftedBoolBitwiseOp(ExpressionKind ek, EXPRFLAG flags, EXPR expr1, EXPR expr2) { return null; } private EXPR BindBoolUnaOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg) { CType reqPDT = GetReqPDT(PredefinedType.PT_BOOL); EXPR const = arg.GetConst(); if (const == null) return GetExprFactory().CreateUnaryOp(ExpressionKind.EK_LOGNOT, reqPDT, arg); bool flag = const.asCONSTANT().getVal().iVal != 0; return GetExprFactory().CreateConstant(reqPDT, ConstValFactory.GetBool(!flag)); } private EXPR BindStrCmpOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { PREDEFMETH predefMeth = (ek == ExpressionKind.EK_EQ) ? PREDEFMETH.PM_STRING_OPEQUALITY : PREDEFMETH.PM_STRING_OPINEQUALITY; ek = ((ek == ExpressionKind.EK_EQ) ? ExpressionKind.EK_STRINGEQ : ExpressionKind.EK_STRINGNE); return CreateBinopForPredefMethodCall(ek, predefMeth, GetReqPDT(PredefinedType.PT_BOOL), arg1, arg2); } private EXPR BindRefCmpOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { arg1 = mustConvert(arg1, GetReqPDT(PredefinedType.PT_OBJECT), CONVERTTYPE.NOUDC); arg2 = mustConvert(arg2, GetReqPDT(PredefinedType.PT_OBJECT), CONVERTTYPE.NOUDC); return GetExprFactory().CreateBinop(ek, GetReqPDT(PredefinedType.PT_BOOL), arg1, arg2); } private EXPR BindDelBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { PREDEFMETH predefMeth = PREDEFMETH.PM_FIRST; CType retType = null; switch (ek) { case ExpressionKind.EK_ADD: predefMeth = PREDEFMETH.PM_DELEGATE_COMBINE; retType = arg1.type; ek = ExpressionKind.EK_DELEGATEADD; break; case ExpressionKind.EK_SUB: predefMeth = PREDEFMETH.PM_DELEGATE_REMOVE; retType = arg1.type; ek = ExpressionKind.EK_DELEGATESUB; break; case ExpressionKind.EK_EQ: predefMeth = PREDEFMETH.PM_DELEGATE_OPEQUALITY; retType = GetReqPDT(PredefinedType.PT_BOOL); ek = ExpressionKind.EK_DELEGATEEQ; break; case ExpressionKind.EK_NE: predefMeth = PREDEFMETH.PM_DELEGATE_OPINEQUALITY; retType = GetReqPDT(PredefinedType.PT_BOOL); ek = ExpressionKind.EK_DELEGATENE; break; } return CreateBinopForPredefMethodCall(ek, predefMeth, retType, arg1, arg2); } private EXPR BindEnumBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { AggregateType ppEnumType = null; AggregateType enumBinOpType = GetEnumBinOpType(ek, arg1.type, arg2.type, out ppEnumType); PredefinedType predefinedType; switch (ppEnumType.fundType()) { default: predefinedType = PredefinedType.PT_INT; break; case FUNDTYPE.FT_U4: predefinedType = PredefinedType.PT_UINT; break; case FUNDTYPE.FT_I8: predefinedType = PredefinedType.PT_LONG; break; case FUNDTYPE.FT_U8: predefinedType = PredefinedType.PT_ULONG; break; } CType reqPDT = GetReqPDT(predefinedType); arg1 = mustCast(arg1, reqPDT, CONVERTTYPE.NOUDC); arg2 = mustCast(arg2, reqPDT, CONVERTTYPE.NOUDC); EXPR eXPR = BindIntOp(ek, flags, arg1, arg2, predefinedType); if (!eXPR.isOK()) return eXPR; if (eXPR.type != enumBinOpType) eXPR = mustCast(eXPR, enumBinOpType, CONVERTTYPE.NOUDC); return eXPR; } private EXPR BindEnumUnaOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg) { CType type = arg.asCAST().GetArgument().type; PredefinedType predefinedType; switch (type.fundType()) { default: predefinedType = PredefinedType.PT_INT; break; case FUNDTYPE.FT_U4: predefinedType = PredefinedType.PT_UINT; break; case FUNDTYPE.FT_I8: predefinedType = PredefinedType.PT_LONG; break; case FUNDTYPE.FT_U8: predefinedType = PredefinedType.PT_ULONG; break; } CType reqPDT = GetReqPDT(predefinedType); arg = mustCast(arg, reqPDT, CONVERTTYPE.NOUDC); EXPR eXPR = BindIntOp(ek, flags, arg, null, predefinedType); if (!eXPR.isOK()) return eXPR; return mustCastInUncheckedContext(eXPR, type, CONVERTTYPE.NOUDC); } private EXPR BindPtrBinOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { return null; } private EXPR BindPtrCmpOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg1, EXPR arg2) { return null; } private bool GetBinopKindAndFlags(ExpressionKind ek, out BinOpKind pBinopKind, out EXPRFLAG flags) { flags = (EXPRFLAG)0; switch (ek) { case ExpressionKind.EK_ADD: if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Add; break; case ExpressionKind.EK_SUB: if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Sub; break; case ExpressionKind.EK_DIV: case ExpressionKind.EK_MOD: flags |= EXPRFLAG.EXF_ASSGOP; if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Mul; break; case ExpressionKind.EK_MUL: if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Mul; break; case ExpressionKind.EK_BITAND: case ExpressionKind.EK_BITOR: pBinopKind = BinOpKind.Bitwise; break; case ExpressionKind.EK_BITXOR: pBinopKind = BinOpKind.BitXor; break; case ExpressionKind.EK_LSHIFT: case ExpressionKind.EK_RSHIFT: pBinopKind = BinOpKind.Shift; break; case ExpressionKind.EK_LOGAND: case ExpressionKind.EK_LOGOR: pBinopKind = BinOpKind.Logical; break; case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: pBinopKind = BinOpKind.Compare; break; case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: pBinopKind = BinOpKind.Equal; break; default: VSFAIL("Bad ek"); pBinopKind = BinOpKind.Add; return false; } return true; } private static bool isDivByZero(ExpressionKind kind, EXPR op2) { return false; } private EXPR FoldIntegerConstants(ExpressionKind kind, EXPRFLAG flags, EXPR op1, EXPR op2, PredefinedType ptOp) { CType reqPDT = GetReqPDT(ptOp); EXPRCONSTANT eXPRCONSTANT = op1.GetConst().asCONSTANT(); EXPRCONSTANT eXPRCONSTANT2 = op2?.GetConst().asCONSTANT(); if (eXPRCONSTANT != null && (op2 == null || eXPRCONSTANT2 != null)) { if (ptOp == PredefinedType.PT_LONG || ptOp == PredefinedType.PT_ULONG) return FoldConstI8Op(kind, op1, eXPRCONSTANT, op2, eXPRCONSTANT2, ptOp); return FoldConstI4Op(kind, op1, eXPRCONSTANT, op2, eXPRCONSTANT2, ptOp); } return null; } private EXPR BindIntOp(ExpressionKind kind, EXPRFLAG flags, EXPR op1, EXPR op2, PredefinedType ptOp) { CType reqPDT = GetReqPDT(ptOp); if (isDivByZero(kind, op2)) { GetErrorContext().Error(ErrorCode.ERR_IntDivByZero, Array.Empty<ErrArg>()); EXPR eXPR = GetExprFactory().CreateBinop(kind, reqPDT, op1, op2); eXPR.SetError(); return eXPR; } EXPR eXPR2 = FoldIntegerConstants(kind, flags, op1, op2, ptOp); if (eXPR2 != null) return eXPR2; if (kind == ExpressionKind.EK_NEG) return BindIntegerNeg(flags, op1, ptOp); CType pType = kind.isRelational() ? GetReqPDT(PredefinedType.PT_BOOL) : reqPDT; EXPR eXPR3 = GetExprFactory().CreateOperator(kind, pType, op1, op2); eXPR3.flags |= flags; return eXPR3; } private EXPR BindIntegerNeg(EXPRFLAG flags, EXPR op, PredefinedType ptOp) { CType reqPDT = GetReqPDT(ptOp); switch (ptOp) { case PredefinedType.PT_ULONG: return BadOperatorTypesError(ExpressionKind.EK_NEG, op, null); case PredefinedType.PT_UINT: if (op.type.fundType() == FUNDTYPE.FT_U4) { EXPRCLASS destExpr = GetExprFactory().MakeClass(GetReqPDT(PredefinedType.PT_LONG)); op = mustConvertCore(op, destExpr, CONVERTTYPE.NOUDC); } break; } return GetExprFactory().CreateNeg(flags, op); } private EXPR FoldConstI4Op(ExpressionKind kind, EXPR op1, EXPRCONSTANT opConst1, EXPR op2, EXPRCONSTANT opConst2, PredefinedType ptOp) { bool flag = ptOp == PredefinedType.PT_INT; uint uiVal = opConst1.asCONSTANT().getVal().uiVal; uint num = opConst2?.asCONSTANT().getVal().uiVal ?? 0; uint num2 = 2147483648; uint num3; switch (kind) { case ExpressionKind.EK_ADD: num3 = uiVal + num; if (flag) EnsureChecked((((uiVal ^ num) | (uiVal ^ num3 ^ num2)) & num2) != 0); else EnsureChecked(num3 >= uiVal); break; case ExpressionKind.EK_SUB: num3 = uiVal - num; if (flag) EnsureChecked((((uiVal ^ num ^ num2) | (uiVal ^ num3 ^ num2)) & num2) != 0); else EnsureChecked(num3 <= uiVal); break; case ExpressionKind.EK_MUL: num3 = uiVal * num; if (uiVal != 0 && num != 0) { if (flag) EnsureChecked((num != num3 || uiVal == 1) && (int)num3 / (int)uiVal == (int)num); else EnsureChecked(num3 / uiVal == num); } break; case ExpressionKind.EK_DIV: if (!flag) num3 = uiVal / num; else if (num != 0) { num3 = (uint)((int)uiVal / (int)num); } else { num3 = 0 - uiVal; EnsureChecked(uiVal != num2); } break; case ExpressionKind.EK_MOD: num3 = (uint)((!flag) ? ((int)(uiVal % num)) : ((num != 0) ? ((int)uiVal % (int)num) : 0)); break; case ExpressionKind.EK_NEG: if (!flag) { CONSTVAL constVal = GetExprConstants().Create(0 - uiVal); return GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_LONG), constVal); } num3 = 0 - uiVal; EnsureChecked(uiVal != num2); break; case ExpressionKind.EK_UPLUS: num3 = uiVal; break; case ExpressionKind.EK_BITAND: num3 = (uiVal & num); break; case ExpressionKind.EK_BITOR: num3 = (uiVal | num); break; case ExpressionKind.EK_BITXOR: num3 = (uiVal ^ num); break; case ExpressionKind.EK_BITNOT: num3 = ~uiVal; break; case ExpressionKind.EK_EQ: num3 = (uint)((uiVal == num) ? 1 : 0); break; case ExpressionKind.EK_NE: num3 = (uint)((uiVal != num) ? 1 : 0); break; case ExpressionKind.EK_LE: num3 = (uint)((flag ? ((int)uiVal <= (int)num) : (uiVal <= num)) ? 1 : 0); break; case ExpressionKind.EK_LT: num3 = (uint)((flag ? ((int)uiVal < (int)num) : (uiVal < num)) ? 1 : 0); break; case ExpressionKind.EK_GE: num3 = (uint)((flag ? ((int)uiVal >= (int)num) : (uiVal >= num)) ? 1 : 0); break; case ExpressionKind.EK_GT: num3 = (uint)((flag ? ((int)uiVal > (int)num) : (uiVal > num)) ? 1 : 0); break; default: VSFAIL("Unknown op"); num3 = 0; break; } CType optPDT = GetOptPDT(kind.isRelational() ? PredefinedType.PT_BOOL : ptOp); return GetExprFactory().CreateConstant(optPDT, ConstValFactory.GetUInt(num3)); } private void EnsureChecked(bool b) { if (!b && Context.CheckedConstant) GetErrorContext().Error(ErrorCode.ERR_CheckedOverflow, Array.Empty<ErrArg>()); } private EXPR FoldConstI8Op(ExpressionKind kind, EXPR op1, EXPRCONSTANT opConst1, EXPR op2, EXPRCONSTANT opConst2, PredefinedType ptOp) { bool flag = ptOp == PredefinedType.PT_LONG; bool flag2 = false; CONSTVAL cONSTVAL = new CONSTVAL(); CType pType; if (flag) { long longVal = opConst1.asCONSTANT().getVal().longVal; long num = opConst2?.asCONSTANT().getVal().longVal ?? 0; long value = 0; switch (kind) { case ExpressionKind.EK_ADD: value = longVal + num; break; case ExpressionKind.EK_SUB: value = longVal - num; break; case ExpressionKind.EK_MUL: value = longVal * num; break; case ExpressionKind.EK_DIV: value = longVal / num; break; case ExpressionKind.EK_MOD: value = longVal % num; break; case ExpressionKind.EK_NEG: value = -longVal; break; case ExpressionKind.EK_UPLUS: value = longVal; break; case ExpressionKind.EK_BITAND: value = (longVal & num); break; case ExpressionKind.EK_BITOR: value = (longVal | num); break; case ExpressionKind.EK_BITXOR: value = (longVal ^ num); break; case ExpressionKind.EK_BITNOT: value = ~longVal; break; case ExpressionKind.EK_EQ: flag2 = (longVal == num); break; case ExpressionKind.EK_NE: flag2 = (longVal != num); break; case ExpressionKind.EK_LE: flag2 = (longVal <= num); break; case ExpressionKind.EK_LT: flag2 = (longVal < num); break; case ExpressionKind.EK_GE: flag2 = (longVal >= num); break; case ExpressionKind.EK_GT: flag2 = (longVal > num); break; default: VSFAIL("Unknown op"); value = 0; break; } if (kind.isRelational()) { cONSTVAL.iVal = (flag2 ? 1 : 0); pType = GetReqPDT(PredefinedType.PT_BOOL); } else { cONSTVAL = GetExprConstants().Create(value); pType = GetOptPDT(ptOp); } } else { ulong ulongVal = opConst1.asCONSTANT().getVal().ulongVal; ulong num2 = opConst2?.asCONSTANT().getVal().ulongVal ?? 0; ulong value2 = 0; switch (kind) { case ExpressionKind.EK_ADD: value2 = ulongVal + num2; break; case ExpressionKind.EK_SUB: value2 = ulongVal - num2; break; case ExpressionKind.EK_MUL: value2 = ulongVal * num2; break; case ExpressionKind.EK_DIV: value2 = ulongVal / num2; break; case ExpressionKind.EK_MOD: value2 = ulongVal % num2; break; case ExpressionKind.EK_NEG: return BadOperatorTypesError(kind, op1, op2); case ExpressionKind.EK_UPLUS: value2 = ulongVal; break; case ExpressionKind.EK_BITAND: value2 = (ulongVal & num2); break; case ExpressionKind.EK_BITOR: value2 = (ulongVal | num2); break; case ExpressionKind.EK_BITXOR: value2 = (ulongVal ^ num2); break; case ExpressionKind.EK_BITNOT: value2 = ~ulongVal; break; case ExpressionKind.EK_EQ: flag2 = (ulongVal == num2); break; case ExpressionKind.EK_NE: flag2 = (ulongVal != num2); break; case ExpressionKind.EK_LE: flag2 = (ulongVal <= num2); break; case ExpressionKind.EK_LT: flag2 = (ulongVal < num2); break; case ExpressionKind.EK_GE: flag2 = (ulongVal >= num2); break; case ExpressionKind.EK_GT: flag2 = (ulongVal > num2); break; default: VSFAIL("Unknown op"); value2 = 0; break; } if (kind.isRelational()) { cONSTVAL.iVal = (flag2 ? 1 : 0); pType = GetReqPDT(PredefinedType.PT_BOOL); } else { cONSTVAL = GetExprConstants().Create(value2); pType = GetOptPDT(ptOp); } } return GetExprFactory().CreateConstant(pType, cONSTVAL); } private EXPR bindFloatOp(ExpressionKind kind, EXPRFLAG flags, EXPR op1, EXPR op2) { EXPR const = op1.GetConst(); EXPR eXPR = op2?.GetConst(); EXPR eXPR2; if (const != null && (op2 == null || eXPR != null)) { double doubleVal = const.asCONSTANT().getVal().doubleVal; double num = eXPR?.asCONSTANT().getVal().doubleVal ?? 0; double value = 0; bool flag = false; switch (kind) { case ExpressionKind.EK_ADD: value = doubleVal + num; break; case ExpressionKind.EK_SUB: value = doubleVal - num; break; case ExpressionKind.EK_MUL: value = doubleVal * num; break; case ExpressionKind.EK_DIV: value = doubleVal / num; break; case ExpressionKind.EK_NEG: value = 0 - doubleVal; break; case ExpressionKind.EK_UPLUS: value = doubleVal; break; case ExpressionKind.EK_MOD: value = doubleVal % num; break; case ExpressionKind.EK_EQ: flag = (doubleVal == num); break; case ExpressionKind.EK_NE: flag = (doubleVal != num); break; case ExpressionKind.EK_LE: flag = (doubleVal <= num); break; case ExpressionKind.EK_LT: flag = (doubleVal < num); break; case ExpressionKind.EK_GE: flag = (doubleVal >= num); break; case ExpressionKind.EK_GT: flag = (doubleVal > num); break; default: value = 0; break; } CONSTVAL cONSTVAL = new CONSTVAL(); CType pType; if (kind.isRelational()) { cONSTVAL.iVal = (flag ? 1 : 0); pType = GetReqPDT(PredefinedType.PT_BOOL); } else { cONSTVAL = GetExprConstants().Create(value); pType = op1.type; } eXPR2 = GetExprFactory().CreateConstant(pType, cONSTVAL); } else { CType pType2 = kind.isRelational() ? GetReqPDT(PredefinedType.PT_BOOL) : op1.type; eXPR2 = GetExprFactory().CreateOperator(kind, pType2, op1, op2); flags = (EXPRFLAG)(-262145); eXPR2.flags |= flags; } return eXPR2; } private EXPR bindStringConcat(EXPR op1, EXPR op2) { return GetExprFactory().CreateConcat(op1, op2); } private EXPR ambiguousOperatorError(ExpressionKind ek, EXPR op1, EXPR op2) { RETAILVERIFY(op1 != null); string errorString = op1.errorString; if (op2 != null) GetErrorContext().Error(ErrorCode.ERR_AmbigBinaryOps, errorString, op1.type, op2.type); else GetErrorContext().Error(ErrorCode.ERR_AmbigUnaryOp, errorString, op1.type); EXPR eXPR = GetExprFactory().CreateOperator(ek, null, op1, op2); eXPR.SetError(); return eXPR; } private EXPR BindUserBoolOp(ExpressionKind kind, EXPRCALL pCall) { RETAILVERIFY(pCall != null); RETAILVERIFY(pCall.mwi.Meth() != null); RETAILVERIFY(pCall.GetOptionalArguments() != null); CType type = pCall.type; if (!GetTypes().SubstEqualTypes(type, pCall.mwi.Meth().Params.Item(0), type) || !GetTypes().SubstEqualTypes(type, pCall.mwi.Meth().Params.Item(1), type)) { MethWithInst mwi = new MethWithInst(null, null); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, mwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, null, null, pMemberGroup, null); eXPRCALL.SetError(); GetErrorContext().Error(ErrorCode.ERR_BadBoolOp, pCall.mwi); return GetExprFactory().CreateUserLogOpError(type, eXPRCALL, pCall); } EXPR optionalElement = pCall.GetOptionalArguments().asLIST().GetOptionalElement(); EXPR eXPR = WrapShortLivedExpression(optionalElement); pCall.GetOptionalArguments().asLIST().SetOptionalElement(eXPR); SymbolLoader.RuntimeBinderSymbolTable.PopulateSymbolTableWithName("op_True", null, eXPR.type.AssociatedSystemType); SymbolLoader.RuntimeBinderSymbolTable.PopulateSymbolTableWithName("op_False", null, eXPR.type.AssociatedSystemType); EXPR eXPR2 = bindUDUnop(ExpressionKind.EK_TRUE, eXPR); EXPR eXPR3 = bindUDUnop(ExpressionKind.EK_FALSE, eXPR); if (eXPR2 == null || eXPR3 == null) { EXPR eXPR4 = (eXPR2 != null) ? eXPR2 : eXPR3; if (eXPR4 == null) { MethWithInst mwi2 = new MethWithInst(null, null); EXPRMEMGRP pMemberGroup2 = GetExprFactory().CreateMemGroup(null, mwi2); eXPR4 = GetExprFactory().CreateCall((EXPRFLAG)0, null, eXPR, pMemberGroup2, null); pCall.SetError(); } GetErrorContext().Error(ErrorCode.ERR_MustHaveOpTF, type); return GetExprFactory().CreateUserLogOpError(type, eXPR4, pCall); } eXPR2 = mustConvert(eXPR2, GetReqPDT(PredefinedType.PT_BOOL)); eXPR3 = mustConvert(eXPR3, GetReqPDT(PredefinedType.PT_BOOL)); return GetExprFactory().CreateUserLogOp(type, (kind == ExpressionKind.EK_LOGAND) ? eXPR3 : eXPR2, pCall); } private AggregateType GetUserDefinedBinopArgumentType(CType type) { while (true) { switch (type.GetTypeKind()) { case TypeKind.TK_NullableType: type = type.StripNubs(); break; case TypeKind.TK_TypeParameterType: type = type.AsTypeParameterType().GetEffectiveBaseClass(); break; case TypeKind.TK_AggregateType: if ((type.isClassType() || type.isStructType()) && !type.AsAggregateType().getAggregate().IsSkipUDOps()) return type.AsAggregateType(); return null; default: return null; } } } private int GetUserDefinedBinopArgumentTypes(CType type1, CType type2, AggregateType[] rgats) { int num = 0; rgats[0] = GetUserDefinedBinopArgumentType(type1); if (rgats[0] != null) num++; rgats[num] = GetUserDefinedBinopArgumentType(type2); if (rgats[num] != null) num++; if (num == 2 && rgats[0] == rgats[1]) num = 1; return num; } private bool UserDefinedBinaryOperatorCanBeLifted(ExpressionKind ek, MethodSymbol method, AggregateType ats, TypeArray Params) { if (!Params.Item(0).IsNonNubValType()) return false; if (!Params.Item(1).IsNonNubValType()) return false; CType cType = GetTypes().SubstType(method.RetType, ats); if (cType.IsNonNubValType()) { switch (ek) { case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: if (!cType.isPredefType(PredefinedType.PT_BOOL)) return false; if (Params.Item(0) != Params.Item(1)) return false; return true; case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: if (!cType.isPredefType(PredefinedType.PT_BOOL)) return false; return true; default: return true; } } return false; } private bool UserDefinedBinaryOperatorIsApplicable(List<CandidateFunctionMember> candidateList, ExpressionKind ek, MethodSymbol method, AggregateType ats, EXPR arg1, EXPR arg2, bool fDontLift) { if (!method.isOperator || method.Params.size != 2) return false; TypeArray typeArray = GetTypes().SubstTypeArray(method.Params, ats); if (canConvert(arg1, typeArray.Item(0)) && canConvert(arg2, typeArray.Item(1))) { candidateList.Add(new CandidateFunctionMember(new MethPropWithInst(method, ats, BSYMMGR.EmptyTypeArray()), typeArray, 0, false)); return true; } if (fDontLift || !GetSymbolLoader().FCanLift() || !UserDefinedBinaryOperatorCanBeLifted(ek, method, ats, typeArray)) return false; CType[] array = new CType[2] { GetTypes().GetNullable(typeArray.Item(0)), GetTypes().GetNullable(typeArray.Item(1)) }; if (!canConvert(arg1, array[0]) || !canConvert(arg2, array[1])) return false; candidateList.Add(new CandidateFunctionMember(new MethPropWithInst(method, ats, BSYMMGR.EmptyTypeArray()), GetGlobalSymbols().AllocParams(2, array), 2, false)); return true; } private bool GetApplicableUserDefinedBinaryOperatorCandidates(List<CandidateFunctionMember> candidateList, ExpressionKind ek, AggregateType type, EXPR arg1, EXPR arg2, bool fDontLift) { Name name = ekName(ek); bool result = false; for (MethodSymbol methodSymbol = GetSymbolLoader().LookupAggMember(name, type.getAggregate(), symbmask_t.MASK_MethodSymbol).AsMethodSymbol(); methodSymbol != null; methodSymbol = GetSymbolLoader().LookupNextSym(methodSymbol, type.getAggregate(), symbmask_t.MASK_MethodSymbol).AsMethodSymbol()) { if (UserDefinedBinaryOperatorIsApplicable(candidateList, ek, methodSymbol, type, arg1, arg2, fDontLift)) result = true; } return result; } private AggregateType GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(List<CandidateFunctionMember> candidateList, ExpressionKind ek, AggregateType type, EXPR arg1, EXPR arg2, bool fDontLift, AggregateType atsStop) { AggregateType aggregateType = type; while (aggregateType != null && aggregateType != atsStop) { if (GetApplicableUserDefinedBinaryOperatorCandidates(candidateList, ek, aggregateType, arg1, arg2, fDontLift)) return aggregateType; aggregateType = aggregateType.GetBaseClass(); } return null; } private EXPRCALL BindUDBinop(ExpressionKind ek, EXPR arg1, EXPR arg2, bool fDontLift, out MethPropWithInst ppmpwi) { List<CandidateFunctionMember> list = new List<CandidateFunctionMember>(); ppmpwi = null; AggregateType[] array = new AggregateType[2]; switch (GetUserDefinedBinopArgumentTypes(arg1.type, arg2.type, array)) { case 0: return null; case 1: GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(list, ek, array[0], arg1, arg2, fDontLift, null); break; default: { AggregateType applicableUserDefinedBinaryOperatorCandidatesInBaseTypes = GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(list, ek, array[0], arg1, arg2, fDontLift, null); GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(list, ek, array[1], arg1, arg2, fDontLift, applicableUserDefinedBinaryOperatorCandidatesInBaseTypes); break; } } if (list.IsEmpty()) return null; EXPRLIST args = GetExprFactory().CreateList(arg1, arg2); ArgInfos argInfos = new ArgInfos(); argInfos.carg = 2; FillInArgInfoFromArgList(argInfos, args); CandidateFunctionMember methAmbig; CandidateFunctionMember methAmbig2; CandidateFunctionMember candidateFunctionMember = FindBestMethod(list, null, argInfos, out methAmbig, out methAmbig2); if (candidateFunctionMember == null) { GetErrorContext().Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi, methAmbig2.mpwi); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, methAmbig.mpwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, null, GetExprFactory().CreateList(arg1, arg2), pMemberGroup, null); eXPRCALL.SetError(); return eXPRCALL; } if (GetSemanticChecker().CheckBogus(candidateFunctionMember.mpwi.Meth())) { GetErrorContext().ErrorRef(ErrorCode.ERR_BindToBogus, candidateFunctionMember.mpwi); EXPRMEMGRP pMemberGroup2 = GetExprFactory().CreateMemGroup(null, candidateFunctionMember.mpwi); EXPRCALL eXPRCALL2 = GetExprFactory().CreateCall((EXPRFLAG)0, null, GetExprFactory().CreateList(arg1, arg2), pMemberGroup2, null); eXPRCALL2.SetError(); return eXPRCALL2; } ppmpwi = candidateFunctionMember.mpwi; if (candidateFunctionMember.ctypeLift != 0) return BindLiftedUDBinop(ek, arg1, arg2, candidateFunctionMember.params, candidateFunctionMember.mpwi); CType typeRet = GetTypes().SubstType(candidateFunctionMember.mpwi.Meth().RetType, candidateFunctionMember.mpwi.GetType()); return BindUDBinopCall(arg1, arg2, candidateFunctionMember.params, typeRet, candidateFunctionMember.mpwi); } private EXPRCALL BindUDBinopCall(EXPR arg1, EXPR arg2, TypeArray Params, CType typeRet, MethPropWithInst mpwi) { arg1 = mustConvert(arg1, Params.Item(0)); arg2 = mustConvert(arg2, Params.Item(1)); EXPRLIST pOptionalArguments = GetExprFactory().CreateList(arg1, arg2); checkUnsafe(arg1.type); checkUnsafe(arg2.type); checkUnsafe(typeRet); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, typeRet, pOptionalArguments, pMemberGroup, null); eXPRCALL.mwi = new MethWithInst(mpwi); verifyMethodArgs(eXPRCALL, mpwi.GetType()); return eXPRCALL; } private EXPRCALL BindLiftedUDBinop(ExpressionKind ek, EXPR arg1, EXPR arg2, TypeArray Params, MethPropWithInst mpwi) { EXPR eXPR = arg1; EXPR eXPR2 = arg2; CType cType = GetTypes().SubstType(mpwi.Meth().RetType, mpwi.GetType()); TypeArray typeArray = GetTypes().SubstTypeArray(mpwi.Meth().Params, mpwi.GetType()); if (!canConvert(arg1.type.StripNubs(), typeArray.Item(0), CONVERTTYPE.NOUDC)) eXPR = mustConvert(arg1, Params.Item(0)); if (!canConvert(arg2.type.StripNubs(), typeArray.Item(1), CONVERTTYPE.NOUDC)) eXPR2 = mustConvert(arg2, Params.Item(1)); EXPR arg3 = mustCast(eXPR, typeArray.Item(0)); EXPR arg4 = mustCast(eXPR2, typeArray.Item(1)); CType cType2; switch (ek) { default: cType2 = GetTypes().GetNullable(cType); break; case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: cType2 = cType; break; case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: cType2 = cType; break; } EXPRCALL expr = BindUDBinopCall(arg3, arg4, typeArray, cType, mpwi); EXPRLIST pOptionalArguments = GetExprFactory().CreateList(eXPR, eXPR2); EXPRMEMGRP pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); EXPRCALL eXPRCALL = GetExprFactory().CreateCall((EXPRFLAG)0, cType2, pOptionalArguments, pMemberGroup, null); eXPRCALL.mwi = new MethWithInst(mpwi); switch (ek) { case ExpressionKind.EK_EQ: eXPRCALL.nubLiftKind = NullableCallLiftKind.EqualityOperator; break; case ExpressionKind.EK_NE: eXPRCALL.nubLiftKind = NullableCallLiftKind.InequalityOperator; break; default: eXPRCALL.nubLiftKind = NullableCallLiftKind.Operator; break; } eXPRCALL.castOfNonLiftedResultToLiftedType = mustCast(expr, cType2, (CONVERTTYPE)0); return eXPRCALL; } private AggregateType GetEnumBinOpType(ExpressionKind ek, CType argType1, CType argType2, out AggregateType ppEnumType) { AggregateType aggregateType = argType1.AsAggregateType(); AggregateType aggregateType2 = argType2.AsAggregateType(); AggregateType aggregateType3 = aggregateType.isEnumType() ? aggregateType : aggregateType2; AggregateType result = aggregateType3; switch (ek) { case ExpressionKind.EK_SUB: if (aggregateType == aggregateType2) result = aggregateType3.underlyingEnumType(); break; default: result = GetReqPDT(PredefinedType.PT_BOOL); break; case ExpressionKind.EK_ADD: case ExpressionKind.EK_BITAND: case ExpressionKind.EK_BITOR: case ExpressionKind.EK_BITXOR: break; } ppEnumType = aggregateType3; return result; } private EXPRBINOP CreateBinopForPredefMethodCall(ExpressionKind ek, PREDEFMETH predefMeth, CType RetType, EXPR arg1, EXPR arg2) { MethodSymbol method = GetSymbolLoader().getPredefinedMembers().GetMethod(predefMeth); EXPRBINOP eXPRBINOP = GetExprFactory().CreateBinop(ek, RetType, arg1, arg2); if (method != null) { AggregateSymbol class = method.getClass(); AggregateType aggregate = GetTypes().GetAggregate(class, BSYMMGR.EmptyTypeArray()); eXPRBINOP.predefinedMethodToCall = new MethWithInst(method, aggregate, null); eXPRBINOP.SetUserDefinedCallMethod(eXPRBINOP.predefinedMethodToCall); } else eXPRBINOP.SetError(); return eXPRBINOP; } private EXPRUNARYOP CreateUnaryOpForPredefMethodCall(ExpressionKind ek, PREDEFMETH predefMeth, CType pRetType, EXPR pArg) { MethodSymbol method = GetSymbolLoader().getPredefinedMembers().GetMethod(predefMeth); EXPRUNARYOP eXPRUNARYOP = GetExprFactory().CreateUnaryOp(ek, pRetType, pArg); if (method != null) { AggregateSymbol class = method.getClass(); AggregateType aggregate = GetTypes().GetAggregate(class, BSYMMGR.EmptyTypeArray()); eXPRUNARYOP.predefinedMethodToCall = new MethWithInst(method, aggregate, null); eXPRUNARYOP.UserDefinedCallMethod = eXPRUNARYOP.predefinedMethodToCall; } else eXPRUNARYOP.SetError(); return eXPRUNARYOP; } } }