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

ExpressionBinder

sealed class ExpressionBinder
using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Syntax; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal sealed class ExpressionBinder { private sealed 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; } } private class BinOpSig { public PredefinedType pt1; public PredefinedType pt2; public BinOpMask mask; public int cbosSkip; public PfnBindBinOp pfn; public OpSigFlags grfos; public BinOpFuncKind fnkind; protected 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; } } private sealed class BinOpFullSig : BinOpSig { private readonly LiftFlags _grflt; private readonly CType _type1; private readonly 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, ExprClass pDestinationTypeExpr, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, out Expr ppDestinationExpr, CONVERTTYPE flags); private sealed class ExplicitConversion { private readonly ExpressionBinder _binder; private Expr _exprSrc; private readonly CType _typeSrc; private readonly CType _typeDest; private readonly ExprClass _exprTypeDest; private readonly CType _pDestinationTypeForLambdaErrorReporting; private Expr _exprDest; private readonly bool _needsExprDest; private readonly CONVERTTYPE _flags; public Expr ExprDest => _exprDest; public ExplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc, ExprClass typeDest, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, CONVERTTYPE flags) { _binder = binder; _exprSrc = exprSrc; _typeSrc = typeSrc; _typeDest = typeDest.Type; _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; } ExprUserDefinedConversion exprUserDefinedConversion; if ((exprUserDefinedConversion = (_exprDest as ExprUserDefinedConversion)) != null) exprUserDefinedConversion.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().IsSZArray || !_typeDest.isInterfaceType() || _typeDest.AsAggregateType().GetTypeArgsAll().Count != 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()[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.IsSZArray || !_typeSrc.isInterfaceType() || _typeSrc.AsAggregateType().GetTypeArgsAll().Count != 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()[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 || arraySrc.IsSZArray != arrayDest.IsSZArray) 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 { ExpressionBinder binder = _binder; Expr exprSrc = _exprSrc; ExprClass exprTypeDest = _exprTypeDest; ref Expr exprDest = ref _exprDest; Expr exprSrc2 = _exprSrc; binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, EXPRFLAG.EXF_OPERATOR | ((exprSrc2 != null) ? (exprSrc2.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) { ExpressionBinder binder2 = _binder; Expr exprSrc3 = _exprSrc; ExprClass exprTypeDest2 = _exprTypeDest; ref Expr exprDest2 = ref _exprDest; Expr exprSrc4 = _exprSrc; binder2.bindSimpleCast(exprSrc3, exprTypeDest2, out exprDest2, EXPRFLAG.EXF_OPERATOR | ((exprSrc4 != null) ? (exprSrc4.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.EXF_OPERATOR | EXPRFLAG.EXF_UNREALIZEDGOTO); 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(); } } private delegate Expr PfnBindBinOp (ExpressionKind ek, EXPRFLAG flags, Expr op1, Expr op2); private delegate Expr PfnBindUnaOp (ExpressionKind ek, EXPRFLAG flags, Expr op); internal sealed class GroupToArgsBinder { private enum Result { Success, Failure_SearchForExpanded, Failure_NoSearchForExpanded } private readonly ExpressionBinder _pExprBinder; private bool _fCandidatesUnsupported; private readonly BindingFlag _fBindFlags; private readonly ExprMemberGroup _pGroup; private readonly ArgInfos _pArguments; private readonly ArgInfos _pOriginalArguments; private readonly bool _bHasNamedArguments; private readonly AggregateType _pDelegate; private AggregateType _pCurrentType; private MethodOrPropertySymbol _pCurrentSym; private TypeArray _pCurrentTypeArgs; private TypeArray _pCurrentParameters; private TypeArray _pBestParameters; private int _nArgBest; private readonly SymWithType[] _swtWrongCount = new SymWithType[20]; private int _nWrongCount; private bool _bIterateToEndOfNsList; private bool _bBindingCollectionAddArgs; private readonly GroupToArgsBinderResult _results; private readonly List<CandidateFunctionMember> _methList; private readonly MethPropWithInst _mpwiParamTypeConstraints; private readonly MethPropWithInst _mpwiBogus; private readonly MethPropWithInst _mpwiCantInferInstArg; private readonly MethWithType _mwtBadArity; private Name _pInvalidSpecifiedName; private Name _pNameUsedInPositionalArgument; private Name _pDuplicateSpecifiedName; private readonly List<CType> _HiddenTypes; private bool _bArgumentsChangedForNamedOrOptionalArguments; public GroupToArgsBinder(ExpressionBinder exprBinder, BindingFlag bindFlags, ExprMemberGroup 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(); } private static CType GetTypeQualifier(ExprMemberGroup pGroup) { CType cType = null; if ((pGroup.Flags & EXPRFLAG.EXF_ASFINALLYLEAVE) == (EXPRFLAG)0) { if ((pGroup.Flags & EXPRFLAG.EXF_CTOR) == (EXPRFLAG)0) { if (pGroup.OptionalObject == null) return null; return pGroup.OptionalObject.Type; } return pGroup.ParentType; } 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.SymKind); CType pObject = _pGroup.OptionalObject?.Type; CMemberLookupResults.CMethodIterator methodIterator = _pGroup.MemberLookupResults.GetMethodIterator(GetSemanticChecker(), GetSymbolLoader(), pObject, GetTypeQualifier(_pGroup), _pExprBinder.ContextForMemberLookup(), true, false, _pGroup.TypeArgs.Count, _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.Count != _pArguments.carg) { if (_nWrongCount < num && (!_pCurrentSym.isParamArray || _pArguments.carg < _pCurrentParameters.Count - 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.Count; i++) { AggregateType item = ifacesAll[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.OptionalObject?.Type; 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.Count != methAmbig2.mpwi.MethProp().Params.Count || 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.OptionalObject); if (methodOrPropertySymbol == null) return false; int count = _pCurrentParameters.Count; if (count == 0 || count < _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, ExprMemberGroup pGroup, ArgInfos pArguments, TypeManager typeManager, ExprFactory exprFactory, SymbolLoader symbolLoader) { int count = pCurrentParameters.Count; Expr[] array = new Expr[count]; int num = 0; Expr expr = null; TypeArray typeArray = typeManager.SubstTypeArray(pCurrentParameters, pCurrentType, pGroup.TypeArgs); foreach (Name parameterName in methprop.ParameterNames) { if (num >= pCurrentParameters.Count) break; ExprArrayInit exprArrayInit; if (methprop.isParamArray && num < pArguments.carg && (exprArrayInit = (pArguments.prgexpr[num] as ExprArrayInit)) != null && exprArrayInit.GeneratedForParamArray) expr = pArguments.prgexpr[num]; ExprArrayInit exprArrayInit2; if (num < pArguments.carg && !(pArguments.prgexpr[num] is ExprNamedArgumentSpecification) && ((exprArrayInit2 = (pArguments.prgexpr[num] as ExprArrayInit)) == null || !exprArrayInit2.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[num], num); else { if (expr == null || num != methprop.Params.Count - 1) return false; expr2 = expr; } } array[num++] = expr2; } } CType[] array2 = new CType[pCurrentParameters.Count]; for (int i = 0; i < count; 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.Count; pArguments.types = symbolLoader.getBSymmgr().AllocParams(pCurrentParameters.Count, 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, ConstVal.Get(DateTime.FromBinary(defaultParameterValue.Int64Val))); } } else if (type.isPredefType(PredefinedType.PT_OBJECT)) { if (methprop.MarshalAsObject(index)) expr = exprFactory.CreateNull(); else { AggregateSymbol optPredefAgg = symbolLoader.GetOptPredefAgg(PredefinedType.PT_MISSING); Name predefinedName = NameManager.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, fWT); 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; MethodSymbol methodSymbol2 = methodSymbol.swtSlot?.Meth(); if (methodSymbol2 != null) methodSymbol = methodSymbol2; 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.OptionalObject)?.HasOptionalParameters() ?? false; } private bool AddArgumentsForOptionalParameters() { if (_pCurrentParameters.Count <= _pArguments.carg) return true; MethodOrPropertySymbol methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.OptionalObject); 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.Count - num]; while (num < typeArray.Count) { if (!methodOrPropertySymbol.IsParameterOptional(num)) return false; array[num2] = GenerateOptionalArgument(GetSymbolLoader(), _pExprBinder.GetExprFactory(), methodOrPropertySymbol, typeArray[num], num); num++; num2++; } for (int i = 0; i < num2; i++) { _pArguments.prgexpr.Add(array[i]); } CType[] array2 = new CType[typeArray.Count]; for (int j = 0; j < typeArray.Count; j++) { array2[j] = _pArguments.prgexpr[j].Type; } _pArguments.types = GetSymbolLoader().getBSymmgr().AllocParams(typeArray.Count, array2); _pArguments.carg = typeArray.Count; _bArgumentsChangedForNamedOrOptionalArguments = true; return true; } private static Expr FindArgumentWithName(ArgInfos pArguments, Name pName) { List<Expr> prgexpr = pArguments.prgexpr; for (int i = 0; i < pArguments.carg; i++) { Expr expr = prgexpr[i]; ExprNamedArgumentSpecification exprNamedArgumentSpecification; if ((exprNamedArgumentSpecification = (expr as ExprNamedArgumentSpecification)) != null && exprNamedArgumentSpecification.Name == pName) return expr; } 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++) { ExprNamedArgumentSpecification exprNamedArgumentSpecification; if ((exprNamedArgumentSpecification = (_pArguments.prgexpr[i] as ExprNamedArgumentSpecification)) == null) { if (!list.IsEmpty()) list = list.Tail(); } else { Name name = exprNamedArgumentSpecification.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.Add(name)) { if (_pDuplicateSpecifiedName == null) _pDuplicateSpecifiedName = name; return false; } } } 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.OptionalObject != 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.Count; i++) { if (_pCurrentSym.IsParameterOptional(i)) num++; } if (_pArguments.carg + num < _pCurrentParameters.Count - 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.Count != typeArgs.Count) { MethodSymbol methodSymbol = _pCurrentSym.AsMethodSymbol(); if (typeArgs.Count > 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.Count == _pCurrentTypeArgs.Count) _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[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[j]; flag |= DoesTypeArgumentsContainErrorSym(cType2); bool flag3; if (_pArguments.fHasExprs) { Expr expr = _pArguments.prgexpr[j]; ExprNamedArgumentSpecification exprNamedArgumentSpecification; if ((exprNamedArgumentSpecification = (expr as ExprNamedArgumentSpecification)) != null) expr = exprNamedArgumentSpecification.Value; flag3 = _pExprBinder.canConvert(expr, cType2); } else flag3 = _pExprBinder.canConvert(_pArguments.types[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[j] != cType2) { CType cType3 = _pArguments.types[j].IsParameterModifierType() ? _pArguments.types[j].AsParameterModifierType().GetParameterType() : _pArguments.types[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.Count == 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.Count; i++) { Expr expr = _pArguments.prgexpr[i]; if (expr.IsOptionalArgument) { CType cType = _pCurrentParameters[i]; if (cType != expr.Type) { if (methodOrPropertySymbol == null) methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.OptionalObject); 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.Count; i++) { CType cType = typeArgsAll[i]; if (cType.IsErrorType()) return true; if (cType.IsAggregateType() && DoesTypeArgumentsContainErrorSym(cType)) return true; } return false; } private void ReportErrorsOnSuccess() { if (_results.GetBestResult().MethProp().name == NameManager.GetPredefinedName(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.SymKind == SYMKIND.SK_MethodSymbol && _results.GetBestResult().TypeArgs.Count > 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.OptionalObject != null && _pGroup.OptionalObject.Type != null && _pGroup.OptionalObject.Type.isDelegateType() && _pGroup.Name == NameManager.GetPredefinedName(PredefinedName.PN_INVOKE)) { flag = true; name = _pGroup.OptionalObject.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.OptionalObject != null) cType = _pGroup.OptionalObject.Type; else if (_pGroup.OptionalLHS != null) { cType = _pGroup.OptionalLHS.Type; } MethWithType methWithType = new MethWithType(); methWithType.Set(_results.GetUninferableResult().Meth(), _results.GetUninferableResult().GetType()); GetErrorContext().Error(ErrorCode.ERR_CantInferMethTypeArgs, methWithType); } else if ((bool)_mwtBadArity) { int count = _mwtBadArity.Meth().typeVars.Count; GetErrorContext().ErrorRef((count > 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.OptionalObject != null && _pGroup.OptionalObject.Type.IsAggregateType() && _pGroup.OptionalObject.Type.AsAggregateType().GetOwningAggregate().IsDelegate()) GetErrorContext().Error(ErrorCode.ERR_BadNamedArgumentForDelegateInvoke, _pGroup.OptionalObject.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.ParentType, _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.OptionalObject != null) { GetErrorContext().Error(ErrorCode.ERR_BadExtensionArgTypes, _pGroup.OptionalObject.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[i]; if (!_pExprBinder.canConvert(_pArguments.prgexpr[i], cType)) { CType cType2 = _pArguments.types[i].IsParameterModifierType() ? _pArguments.types[i].AsParameterModifierType().GetParameterType() : _pArguments.types[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[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.OptionalObject != null && !_pExprBinder.canConvertInstanceParamForExtension(_pGroup.OptionalObject, sym.AsMethodSymbol().Params[0])) { if (!_pGroup.OptionalObject.Type.getBogus()) GetErrorContext().Error(ErrorCode.ERR_BadInstanceArgType, _pGroup.OptionalObject.Type, cType); } else GetErrorContext().Error(ErrorCode.ERR_BadArgType, i + 1, new ErrArg(_pArguments.types[i], ErrArgFlags.Unique), new ErrArg(cType, ErrArgFlags.Unique)); } } } } } private bool ReportErrorsForCollectionAdd() { for (int i = 0; i < _pArguments.carg; i++) { CType cType = _pBestParameters[i]; if (cType.IsParameterModifierType()) { GetErrorContext().ErrorRef(ErrorCode.ERR_InitializerAddHasParamModifiers, _results.GetBestResult()); return true; } } return false; } } internal sealed class GroupToArgsBinderResult { public MethPropWithInst BestResult; public MethPropWithInst AmbiguousResult; private MethPropWithInst InaccessibleResult; private MethPropWithInst UninferableResult; private MethPropWithInst InconvertibleResult; private readonly 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.Count; i++) { if (pTypeArgs[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.Count > pTypeArgs2.Count) ? pTypeArgs2.Count : pTypeArgs1.Count; for (int i = 0; i < num3; i++) { if (pTypeArgs1[i].IsAggregateType()) num += NumberOfErrorTypes(pTypeArgs1[i].AsAggregateType().GetTypeArgsAll()); if (pTypeArgs2[i].IsAggregateType()) num2 += NumberOfErrorTypes(pTypeArgs2[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 sealed class ImplicitConversion { private Expr _exprDest; private readonly ExpressionBinder _binder; private readonly Expr _exprSrc; private readonly CType _typeSrc; private readonly CType _typeDest; private readonly ExprClass _exprTypeDest; private readonly bool _needsExprDest; private CONVERTTYPE _flags; public Expr ExprDest => _exprDest; public ImplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc, ExprClass typeDest, bool needsExprDest, CONVERTTYPE flags) { _binder = binder; _exprSrc = exprSrc; _typeSrc = typeSrc; _typeDest = typeDest.Type; _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: { ExprMemberGroup grp; if ((grp = (_exprSrc as ExprMemberGroup)) != null) { ExprCall pexprDst; bool result = _binder.BindGrpConversion(grp, _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; } object obj = _exprSrc?.RuntimeObject; if (obj != null && _typeDest.AssociatedSystemType.IsInstanceOfType(obj) && _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 as ExprUserDefinedConversion; if (exprUserDefinedConversion != null) ppDestinationExpr = exprUserDefinedConversion.UserDefinedCall; for (int i = 0; i < pcnub; i++) { ExprCall exprCall = _binder.BindNubNew(ppDestinationExpr); ppDestinationExpr = exprCall; exprCall.NullableCallLiftKind = NullableCallLiftKind.NullableConversionConstructor; } if (exprUserDefinedConversion != null) { exprUserDefinedConversion.UserDefinedCall = ppDestinationExpr; 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); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, mwi); ExprCall exprCall2 = 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; } exprCall2.CastOfNonLiftedResultToLiftedType = _binder.mustCast(ppDestinationExpr2, nubDst, (CONVERTTYPE)0); exprCall2.NullableCallLiftKind = NullableCallLiftKind.NullableConversion; exprCall2.PConversions = exprCall2.CastOfNonLiftedResultToLiftedType; _exprDest = exprCall2; } 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().Count == 1 && (_typeDest.AsAggregateType().GetTypeArgsAll()[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.EXF_CTOR | EXPRFLAG.EXF_CANTBENULL); 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.EXF_CTOR | EXPRFLAG.EXF_CANTBENULL); 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, ConstVal.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; ExprConstant exprSrc; ConvKind convKind; if ((exprSrc = (_exprSrc as ExprConstant)) == null || !_exprSrc.IsOK || ((predefType != PredefinedType.PT_INT || predefType2 == PredefinedType.PT_BOOL || predefType2 == PredefinedType.PT_CHAR) && (predefType != PredefinedType.PT_LONG || predefType2 != PredefinedType.PT_ULONG)) || !isConstantInRange(exprSrc, _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.Count) return false; cType = bounds[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(); } } private class UnaOpSig { public PredefinedType pt; public UnaOpMask grfuom; public int cuosSkip; public PfnBindUnaOp pfn; public UnaOpFuncKind fnkind; protected 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; } } private sealed class UnaOpFullSig : UnaOpSig { private readonly LiftFlags _grflt; private readonly 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 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 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 } }; private BindingContext Context; private 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 }; private readonly BinOpSig[] g_binopSignatures; private readonly UnaOpSig[] g_rguos; private SymbolLoader SymbolLoader => Context.SymbolLoader; private CSemanticChecker SemanticChecker => Context.SemanticChecker; private ErrorHandling ErrorContext => SymbolLoader.ErrorContext; private TypeManager TypeManager => SymbolLoader.TypeManager; private ExprFactory ExprFactory => Context.ExprFactory; private CType VoidType => GetSymbolLoader().GetTypeManager().GetVoid(); private 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.Count != 0) { if (mpwi2.TypeArgs.Count == 0) return BetterType.Right; } else if (mpwi2.TypeArgs.Count != 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.Count]; MethodOrPropertySymbol methodOrPropertySymbol = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi.MethProp(), pType); for (int i = 0; i < pta.Count; i++) { array[i] = pta[i]; } List<Expr> prgexpr = args.prgexpr; for (int j = 0; j < args.carg; j++) { ExprNamedArgumentSpecification exprNamedArgumentSpecification; if ((exprNamedArgumentSpecification = (prgexpr[j] as ExprNamedArgumentSpecification)) != null) { int num = FindName(methodOrPropertySymbol.ParameterNames, exprNamedArgumentSpecification.Name); CType cType = pta[num]; for (int k = j; k < num; k++) { array[k + 1] = array[k]; } array[j] = cType; } } return GetSymbolLoader().getBSymmgr().AllocParams(pta.Count, array); } private 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[i]; CType p = typeArray[i]; CType p2 = typeArray2[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.Count != typeArray2.Count && betterType == BetterType.Neither) { if (node1.fExpanded && !node2.fExpanded) return BetterType.Right; if (node2.fExpanded && !node1.fExpanded) return BetterType.Left; if (typeArray.Count == args.carg) return BetterType.Left; if (typeArray2.Count == args.carg) return BetterType.Right; return BetterType.Neither; } return betterType; } private BetterType WhichConversionIsBetter(Expr arg, CType argType, CType p1, CType p2) { if (p1 == p2) return BetterType.Same; return WhichConversionIsBetter(argType, p1, p2); } private 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; } private 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; } private 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); } private void ReportReadOnlyError(ExprField field, CheckLvalueKind kind, bool isNested) { bool isStatic = field.FieldWithType.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.FieldWithType); else ErrorContext.Error(id, Array.Empty<ErrArg>()); } private bool TryReportLvalueFailure(Expr expr, CheckLvalueKind kind) { bool flag = false; while (true) { ExprLocal exprLocal; if ((exprLocal = (expr as ExprLocal)) != null && exprLocal.IsOK) { ReportLocalError(exprLocal.Local, kind, flag); return true; } Expr expr2 = null; ExprProperty exprProperty; ExprField exprField; if ((exprProperty = (expr as ExprProperty)) != null) expr2 = exprProperty.MemberGroup.OptionalObject; else if ((exprField = (expr as ExprField)) != null) { if (exprField.FieldWithType.Field().isReadOnly) { ReportReadOnlyError(exprField, kind, flag); return true; } if (!exprField.FieldWithType.Field().isStatic) expr2 = exprField.OptionalObject; } if (expr2 != null && expr2.Type.isStructOrEnum()) { IExprWithArgs exprWithArgs; if ((exprWithArgs = (expr2 as IExprWithArgs)) != null) { ErrorContext.Error(ErrorCode.ERR_ReturnNotLValue, exprWithArgs.GetSymWithType()); return true; } if (expr2 is ExprCast) { expr2.Flags |= EXPRFLAG.EXF_USERCALLABLE; return false; } } if (expr2 == null || expr2.isLvalue() || (!(expr is ExprField) && (flag || !(expr is ExprProperty)))) break; expr = expr2; 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; } private 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); } private bool canConvert(Expr expr, CType dest) { return canConvert(expr, dest, (CONVERTTYPE)0); } private bool canConvert(Expr expr, CType dest, CONVERTTYPE flags) { ExprClass pDestinationTypeExpr = ExprFactory.MakeClass(dest); return BindImplicitConversion(expr, expr.Type, pDestinationTypeExpr, dest, flags); } private Expr mustConvertCore(Expr expr, ExprClass destExpr) { return mustConvertCore(expr, destExpr, (CONVERTTYPE)0); } private Expr mustConvertCore(Expr expr, ExprClass destExpr, CONVERTTYPE flags) { CType type = destExpr.Type; if (BindImplicitConversion(expr, expr.Type, destExpr, type, out Expr ppDestinationExpr, flags)) { checkUnsafe(expr.Type); checkUnsafe(type); return ppDestinationExpr; } if (expr.IsOK && !type.IsErrorType()) { FUNDTYPE fUNDTYPE = expr.Type.fundType(); FUNDTYPE fUNDTYPE2 = type.fundType(); ExprConstant exprConstant; if ((exprConstant = (expr as ExprConstant)) != null && exprConstant.IsOK && expr.Type.isSimpleType() && type.isSimpleType()) { if ((fUNDTYPE == FUNDTYPE.FT_I4 && (fUNDTYPE2 <= FUNDTYPE.FT_U4 || fUNDTYPE2 == FUNDTYPE.FT_U8)) || (fUNDTYPE == FUNDTYPE.FT_I8 && fUNDTYPE2 == FUNDTYPE.FT_U8)) { string psz = exprConstant.Int64Value.ToString(CultureInfo.InvariantCulture); ErrorContext.Error(ErrorCode.ERR_ConstOutOfRange, psz, type); ppDestinationExpr = ExprFactory.CreateCast((EXPRFLAG)0, destExpr, expr); ppDestinationExpr.SetError(); return ppDestinationExpr; } if (fUNDTYPE == FUNDTYPE.FT_R8 && (expr.Flags & EXPRFLAG.EXF_LITERALCONST) != 0 && (type.isPredefType(PredefinedType.PT_FLOAT) || type.isPredefType(PredefinedType.PT_DECIMAL))) { ErrorContext.Error(ErrorCode.ERR_LiteralDoubleCast, type.isPredefType(PredefinedType.PT_DECIMAL) ? "M" : "F", type); ppDestinationExpr = ExprFactory.CreateCast((EXPRFLAG)0, destExpr, expr); ppDestinationExpr.SetError(); return ppDestinationExpr; } } ExprMemberGroup grp; if (expr.Type is NullType && type.fundType() != FUNDTYPE.FT_REF) ErrorContext.Error((type is TypeParameterType) ? ErrorCode.ERR_TypeVarCantBeNull : ErrorCode.ERR_ValueCantBeNull, type); else if ((grp = (expr as ExprMemberGroup)) != null) { BindGrpConversion(grp, type, true); } else if (!TypeManager.TypeContainsAnonymousTypes(type) && canCast(expr.Type, type, flags)) { ErrorContext.Error(ErrorCode.ERR_NoImplicitConvCast, new ErrArg(expr.Type, ErrArgFlags.Unique), new ErrArg(type, ErrArgFlags.Unique)); } else { ErrorContext.Error(ErrorCode.ERR_NoImplicitConv, new ErrArg(expr.Type, ErrArgFlags.Unique), new ErrArg(type, 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); } private 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); } private Expr mustConvert(Expr expr, CType dest, CONVERTTYPE flags) { ExprClass dest2 = ExprFactory.MakeClass(dest); return mustConvert(expr, dest2, flags); } private Expr mustConvert(Expr expr, ExprClass dest, CONVERTTYPE flags) { return mustConvertCore(expr, dest, flags); } private Expr mustCastCore(Expr expr, ExprClass destExpr, CONVERTTYPE flags) { CType type = destExpr.Type; SemanticChecker.CheckForStaticClass(null, type, ErrorCode.ERR_ConvertToStaticClass); Expr ppDestinationExpr; if (expr.IsOK) { if (BindExplicitConversion(expr, expr.Type, destExpr, type, out ppDestinationExpr, flags)) { checkUnsafe(expr.Type); checkUnsafe(type); return ppDestinationExpr; } if (type != null && !(type is ErrorType)) { string psz = ""; Expr const = expr.GetConst(); FUNDTYPE fUNDTYPE = expr.Type.fundType(); bool flag = const != null && expr.Type.isSimpleOrEnum() && type.isSimpleOrEnum(); ConstVal val; ExprMemberGroup grp; if (flag && fUNDTYPE == FUNDTYPE.FT_STRUCT) { ErrorHandling errorContext = ErrorContext; ErrArg[] obj = new ErrArg[2]; val = ((ExprConstant)const).Val; obj[0] = val.DecimalVal.ToString(CultureInfo.InvariantCulture); obj[1] = type; errorContext.Error(ErrorCode.ERR_ConstOutOfRange, obj); } else if (flag && Context.CheckedConstant) { if (!canExplicitConversionBeBoundInUncheckedContext(expr, expr.Type, destExpr, flags | CONVERTTYPE.NOUDC)) CantConvert(expr, type); else { if (fUNDTYPE <= FUNDTYPE.FT_U8) psz = ((!expr.Type.isUnsigned()) ? ((ExprConstant)const).Int64Value.ToString(CultureInfo.InvariantCulture) : ((ulong)((ExprConstant)const).Int64Value).ToString((IFormatProvider)CultureInfo.InvariantCulture)); else if (fUNDTYPE <= FUNDTYPE.FT_R8) { val = ((ExprConstant)const).Val; psz = val.DoubleVal.ToString(CultureInfo.InvariantCulture); } ErrorContext.Error(ErrorCode.ERR_ConstOutOfRangeChecked, psz, type); } } else if (expr.Type is NullType && type.fundType() != FUNDTYPE.FT_REF) { ErrorContext.Error(ErrorCode.ERR_ValueCantBeNull, type); } else if ((grp = (expr as ExprMemberGroup)) != null) { BindGrpConversion(grp, type, true); } else { CantConvert(expr, type); } } } 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) { BindingContext context = new BindingContext(Context); 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); } private bool BindGrpConversion(ExprMemberGroup grp, CType typeDst, bool fReportErrors) { ExprCall pexprDst; return BindGrpConversion(grp, typeDst, false, out pexprDst, fReportErrors); } private bool BindGrpConversion(ExprMemberGroup 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.Count < args.Count && pMWI.Meth().IsExtension()) { flag = true; TypeArray typeArray = GetTypes().SubstTypeArray(pMWI.Meth().Params, pMWI.GetType()); if (typeArray[0].IsTypeParameterType() ? (!args[0].IsRefType()) : (!typeArray[0].IsRefType())) ErrorContext.Error(ErrorCode.ERR_ValueTypeExtDelegate, pMWI, typeArray[0].IsTypeParameterType() ? args[0] : typeArray[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.Count; i++) { CType cType3 = args[i]; CType cType4 = typeArray2[i]; if (cType3 != cType4 && !CConversions.FImpRefConv(GetSymbolLoader(), cType3, cType4)) { ErrorContext.ErrorRef(ErrorCode.ERR_MethDelegateMismatch, pMWI, typeDst); flag2 = true; break; } } } Expr pObject = (!flag) ? grp.OptionalObject : 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.OptionalObject : pObject); if (pMWI.TypeArgs.Count > 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.OptionalObject = pObject; if (pObject != null && pObject.Type.fundType() != FUNDTYPE.FT_REF) pObject = mustConvert(pObject, GetReqPDT(PredefinedType.PT_OBJECT)); } else { exprFuncPtr.OptionalObject = null; pObject = ExprFactory.CreateNull(); } MethWithInst mWI = new MethWithInst(methodSymbol, aggregateType); grp.OptionalObject = null; ExprCall exprCall = pexprDst = ExprFactory.CreateCall(EXPRFLAG.EXF_LITERALCONST | EXPRFLAG.EXF_CANTBENULL, aggregateType, ExprFactory.CreateList(pObject, exprFuncPtr), grp, mWI); return true; } private bool BindGrpConversionCore(out MethPropWithInst pmpwi, BindingFlag bindFlags, ExprMemberGroup grp, ref TypeArray args, AggregateType atsDelegate, bool fReportErrors, out MethPropWithInst pmpwiAmbig) { bool flag = false; int count = args.Count; ArgInfos argInfos = new ArgInfos(); argInfos.carg = args.Count; 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) { CType cType = exprSrc?.Type; if (cType != null) return canConvertInstanceParamForExtension(cType, typeDest); return false; } 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, ExprClass 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, ExprClass 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, ExprClass 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, ExprClass 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, ExprClass 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, ExprClass 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.Count == 1 && (!fImplicitOnly || methodSymbol.isImplicit()) && !GetSemanticChecker().CheckBogus(methodSymbol)) { cType5 = GetTypes().SubstType(methodSymbol.Params[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[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[0], methWithInst.GetType()); cType6 = GetTypes().SubstType(methWithInst.Meth().RetType, methWithInst.GetType()); Expr ppTransformedArgument = exprSrc; Expr call; if ((num10 > 0 && !cType5.IsNullableType()) & flag3) { ExprMemberGroup pMemberGroup = ExprFactory.CreateMemGroup(null, methWithInst); ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, typeDst, exprSrc, pMemberGroup, methWithInst); call = exprCall; Expr expr = mustCast(exprSrc, cType5); MarkAsIntermediateConversion(expr); Expr expr2 = BindUDConversionCore(expr, cType5, cType6, typeDst, methWithInst); exprCall.CastOfNonLiftedResultToLiftedType = mustCast(expr2, typeDst); exprCall.NullableCallLiftKind = 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); } ExprCall exprCall2 = ExprFactory.CreateCall((EXPRFLAG)0, typeDst, expr3, pMemberGroup, methWithInst); exprCall2.NullableCallLiftKind = NullableCallLiftKind.NotLiftedIntermediateConversion; exprCall.PConversions = exprCall2; } else { Expr expr4 = BindUDConversionCore(expr, cType5, cType6, typeDst, methWithInst); MarkAsIntermediateConversion(expr4); exprCall.PConversions = expr4; } } else call = BindUDConversionCore(exprSrc, cType5, cType6, typeDst, methWithInst, out ppTransformedArgument); pexprDst = ExprFactory.CreateUserDefinedConversion(ppTransformedArgument, call, 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) { while (true) { ExprCall exprCall; if ((exprCall = (pExpr as ExprCall)) != null) { switch (exprCall.NullableCallLiftKind) { default: return; case NullableCallLiftKind.NotLifted: exprCall.NullableCallLiftKind = NullableCallLiftKind.NotLiftedIntermediateConversion; return; case NullableCallLiftKind.NullableConversion: exprCall.NullableCallLiftKind = NullableCallLiftKind.NullableIntermediateConversion; return; case NullableCallLiftKind.NullableConversionConstructor: break; } pExpr = exprCall.OptionalArguments; } else { ExprUserDefinedConversion exprUserDefinedConversion; if ((exprUserDefinedConversion = (pExpr as ExprUserDefinedConversion)) == null) break; pExpr = exprUserDefinedConversion.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); ExprMemberGroup pMemberGroup = ExprFactory.CreateMemGroup(null, mwiBest); ExprCall expr2 = ExprFactory.CreateCall((EXPRFLAG)0, pTypeTo, expr, pMemberGroup, mwiBest); ExprClass destExpr2 = ExprFactory.MakeClass(pTypeDestination); Expr result = mustCastCore(expr2, destExpr2, CONVERTTYPE.NOUDC); ppTransformedArgument = expr; return result; } private ConstCastResult bindConstantCast(Expr exprSrc, ExprClass exprTypeDest, bool needExprDest, out Expr pexprDest, bool explicitConversion) { pexprDest = null; long num = 0; double num2 = 0; CType type = exprTypeDest.Type; FUNDTYPE fUNDTYPE = exprSrc.Type.fundType(); FUNDTYPE fUNDTYPE2 = type.fundType(); bool flag = fUNDTYPE <= FUNDTYPE.FT_U8; bool flag2 = fUNDTYPE <= FUNDTYPE.FT_R8; ExprConstant exprConstant = (ExprConstant)exprSrc.GetConst(); 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, type, 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 = ConstVal.Get(exprConstant.UInt64Value); pexprDest = ExprFactory.CreateConstant(type, constVal); return ConstCastResult.Success; } num = ((long)exprConstant.UInt64Value & -1); } else num = exprConstant.Int64Value; } else { if (!flag2) return ConstCastResult.Failure; num2 = exprConstant.Val.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 constVal2 = (fUNDTYPE2 == FUNDTYPE.FT_U4) ? ConstVal.Get((uint)num) : ((fUNDTYPE2 <= FUNDTYPE.FT_U4) ? ConstVal.Get((int)num) : ((fUNDTYPE2 > FUNDTYPE.FT_U8) ? ConstVal.Get(num2) : ConstVal.Get(num))); ExprConstant exprConstant2 = (ExprConstant)(pexprDest = ExprFactory.CreateConstant(type, constVal2)); 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(ExprClass exprDestType, CType srcType, ExprConstant src) { CType type = exprDestType.Type; CType optPredefType = SymbolLoader.GetOptPredefType(PredefinedType.PT_DECIMAL); if (optPredefType == null) return null; ConstVal val; if (type == optPredefType) { decimal value; switch (srcType.fundType()) { case FUNDTYPE.FT_I1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_I4: val = src.Val; value = Convert.ToDecimal(val.Int32Val); break; case FUNDTYPE.FT_U1: case FUNDTYPE.FT_U2: case FUNDTYPE.FT_U4: val = src.Val; value = Convert.ToDecimal(val.UInt32Val); break; case FUNDTYPE.FT_R4: val = src.Val; value = Convert.ToDecimal((float)val.DoubleVal); break; case FUNDTYPE.FT_R8: val = src.Val; value = Convert.ToDecimal(val.DoubleVal); break; case FUNDTYPE.FT_U8: val = src.Val; value = Convert.ToDecimal((ulong)val.Int64Val); break; case FUNDTYPE.FT_I8: val = src.Val; value = Convert.ToDecimal(val.Int64Val); break; default: return null; } ConstVal constVal = ConstVal.Get(value); return ExprFactory.CreateConstant(optPredefType, constVal); } if (srcType == optPredefType) { decimal value2 = default(decimal); FUNDTYPE fUNDTYPE = type.fundType(); ConstVal constVal; try { if (fUNDTYPE != FUNDTYPE.FT_R4 && fUNDTYPE != FUNDTYPE.FT_R8) { val = src.Val; value2 = decimal.Truncate(val.DecimalVal); } switch (fUNDTYPE) { case FUNDTYPE.FT_I1: constVal = ConstVal.Get(Convert.ToSByte(value2)); break; case FUNDTYPE.FT_U1: constVal = ConstVal.Get((uint)Convert.ToByte(value2)); break; case FUNDTYPE.FT_I2: constVal = ConstVal.Get(Convert.ToInt16(value2)); break; case FUNDTYPE.FT_U2: constVal = ConstVal.Get((uint)Convert.ToUInt16(value2)); break; case FUNDTYPE.FT_I4: constVal = ConstVal.Get(Convert.ToInt32(value2)); break; case FUNDTYPE.FT_U4: constVal = ConstVal.Get(Convert.ToUInt32(value2)); break; case FUNDTYPE.FT_I8: constVal = ConstVal.Get(Convert.ToInt64(value2)); break; case FUNDTYPE.FT_U8: constVal = ConstVal.Get(Convert.ToUInt64(value2)); break; case FUNDTYPE.FT_R4: val = src.Val; constVal = ConstVal.Get(Convert.ToSingle(val.DecimalVal)); break; case FUNDTYPE.FT_R8: val = src.Val; constVal = ConstVal.Get(Convert.ToDouble(val.DecimalVal)); break; default: return null; } } catch (OverflowException) { return null; } return ExprFactory.CreateConstant(type, constVal); } return null; } private bool canExplicitConversionBeBoundInUncheckedContext(Expr exprSrc, CType typeSrc, ExprClass typeDest, CONVERTTYPE flags) { BindingContext context = new BindingContext(Context); return new ExpressionBinder(context).BindExplicitConversion(exprSrc, typeSrc, typeDest, typeDest.Type, 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) }; } private SymbolLoader GetSymbolLoader() { return SymbolLoader; } public CSemanticChecker GetSemanticChecker() { return SemanticChecker; } private ErrorHandling GetErrorContext() { return ErrorContext; } private BSYMMGR GetGlobalSymbols() { return GetSymbolLoader().getBSymmgr(); } private TypeManager GetTypes() { return TypeManager; } private ExprFactory GetExprFactory() { return ExprFactory; } private AggregateType GetReqPDT(PredefinedType pt) { return GetReqPDT(pt, GetSymbolLoader()); } private static AggregateType GetReqPDT(PredefinedType pt, SymbolLoader symbolLoader) { return symbolLoader.GetReqPredefType(pt, true); } private AggregateType GetOptPDT(PredefinedType pt) { return GetOptPDT(pt, true); } private AggregateType GetOptPDT(PredefinedType pt, bool WarnIfNotFound) { if (WarnIfNotFound) return GetSymbolLoader().GetOptPredefTypeErr(pt, true); return GetSymbolLoader().GetOptPredefType(pt, true); } private CType getVoidType() { return VoidType; } private 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) { if (!checkLvalue(op1, CheckLvalueKind.Assignment)) { ExprAssignment exprAssignment = GetExprFactory().CreateAssignment(op1, op2); exprAssignment.SetError(); return exprAssignment; } op2 = GenerateAssignmentConversion(op1, op2, allowExplicit); 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; ExprClass pType = GetExprFactory().MakeClass(pDestType); return GetExprFactory().CreateCast(EXPRFLAG.EXF_LITERALCONST, 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.EXF_ASSGOP | EXPRFLAG.EXF_LVALUE); if (flag) expr.SetError(); return expr; } private 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); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(pObject, mwi); ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, type, args, pMemberGroup, null); exprCall.SetError(); return exprCall; } Name predefinedName = NameManager.GetPredefinedName(PredefinedName.PN_INDEXERINTERNAL); MemberLookup memberLookup = new MemberLookup(); if (!memberLookup.Lookup(GetSemanticChecker(), type, pObject, ContextForMemberLookup(), predefinedName, 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; } ExprMemberGroup exprMemberGroup = null; if (symbol != null) { exprMemberGroup = GetExprFactory().CreateMemGroup((EXPRFLAG)memberLookup.GetFlags(), predefinedName, BSYMMGR.EmptyTypeArray(), symbol.getKind(), memberLookup.GetSourceType(), null, memberLookup.GetObject(), memberLookup.GetResults()); exprMemberGroup.SetInaccessibleBit(); } else { MethWithInst mwi2 = new MethWithInst(null, null); exprMemberGroup = GetExprFactory().CreateMemGroup(memberLookup.GetObject(), mwi2); } ExprCall exprCall2 = GetExprFactory().CreateCall((EXPRFLAG)0, type, args, exprMemberGroup, null); exprCall2.SetError(); return exprCall2; } ExprMemberGroup grp = GetExprFactory().CreateMemGroup((EXPRFLAG)memberLookup.GetFlags(), predefinedName, BSYMMGR.EmptyTypeArray(), memberLookup.SymFirst().getKind(), memberLookup.GetSourceType(), null, memberLookup.GetObject(), memberLookup.GetResults()); Expr expr = BindMethodGroupToArguments(bindFlags, grp, args); IExprWithObject exprWithObject = expr as IExprWithObject; if (exprWithObject?.OptionalObject == null) { if (exprWithObject != null) exprWithObject.OptionalObject = pObject; expr.SetError(); } return expr; } private void bindSimpleCast(Expr exprSrc, ExprClass typeDest, out Expr pexprDest) { bindSimpleCast(exprSrc, typeDest, out pexprDest, (EXPRFLAG)0); } private void bindSimpleCast(Expr exprSrc, ExprClass exprTypeDest, out Expr pexprDest, EXPRFLAG exprFlags) { CType type = exprTypeDest.Type; pexprDest = null; Expr const = exprSrc.GetConst(); ExprCast exprCast = GetExprFactory().CreateCast(exprFlags, exprTypeDest, exprSrc); if (Context.CheckedNormal) exprCast.Flags |= EXPRFLAG.EXF_CHECKOVERFLOW; ExprConstant exprConstant; if ((exprConstant = (const as ExprConstant)) != null && exprFlags == (EXPRFLAG)0 && exprSrc.Type.fundType() == type.fundType() && (!exprSrc.Type.isPredefType(PredefinedType.PT_STRING) || exprConstant.Val.IsNullRef)) { ExprConstant exprConstant2 = (ExprConstant)(pexprDest = GetExprFactory().CreateConstant(type, exprConstant.Val)); } else pexprDest = exprCast; } private ExprCall BindToMethod(MethWithInst mwi, Expr pArguments, ExprMemberGroup pMemGroup, MemLookFlags flags) { Expr optionalObject = pMemGroup.OptionalObject; CType callingObjectType = optionalObject?.Type; PostBindMethod((flags & MemLookFlags.BaseCall) != MemLookFlags.None, ref mwi, optionalObject); optionalObject = (pMemGroup.OptionalObject = AdjustMemberObject(mwi, optionalObject, out bool pfConstrained, out bool pIsMatchingStatic)); 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.EXF_LITERALCONST | EXPRFLAG.EXF_CANTBENULL); 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 pOptionalObject, FieldWithType fwt, BindingFlag bindFlags) { CType cType = GetTypes().SubstType(fwt.Field().GetType(), fwt.GetType()); if (pOptionalObject != null && !pOptionalObject.IsOK) { ExprField exprField = GetExprFactory().CreateField((EXPRFLAG)0, cType, pOptionalObject, fwt); exprField.SetError(); return exprField; } pOptionalObject = AdjustMemberObject(fwt, pOptionalObject, out bool _, out bool pIsMatchingStatic); checkUnsafe(cType); bool flag = (pOptionalObject != null && pOptionalObject.Type.IsPointerType()) || objectIsLvalue(pOptionalObject); if (fwt.Field().isReadOnly) flag = false; CType cType2 = null; if (fwt.Field().isEvent && fwt.Field().getEvent(GetSymbolLoader()) != null && fwt.Field().getEvent(GetSymbolLoader()).IsWindowsRuntimeEvent) { cType2 = fwt.Field().GetType(); if (cType2.IsAggregateType()) cType = GetTypes().GetParameterModifier(cType, false); else cType2 = null; } ExprField exprField2 = GetExprFactory().CreateField(flag ? EXPRFLAG.EXF_LVALUE : ((EXPRFLAG)0), cType, pOptionalObject, fwt); if (!pIsMatchingStatic) exprField2.SetMismatchedStaticBit(); if (cType.IsErrorType()) exprField2.SetError(); exprField2.Flags |= (EXPRFLAG)(bindFlags & BindingFlag.BIND_MEMBERSET); if (cType2 != null) { Name predefinedName = NameManager.GetPredefinedName(PredefinedName.PN_GETORCREATEEVENTREGISTRATIONTOKENTABLE); GetSymbolLoader().RuntimeBinderSymbolTable.PopulateSymbolTableWithName(predefinedName.Text, null, cType2.AssociatedSystemType); MethodSymbol mps = GetSymbolLoader().LookupAggMember(predefinedName, cType2.getAggregate(), symbmask_t.MASK_MethodSymbol).AsMethodSymbol(); MethPropWithInst methPropWithInst = new MethPropWithInst(mps, cType2.AsAggregateType()); ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, methPropWithInst); Expr pObject = BindToMethod(new MethWithInst(methPropWithInst), exprField2, pMemGroup, MemLookFlags.None); AggregateSymbol owningAggregate = cType2.AsAggregateType().GetOwningAggregate(); Name predefinedName2 = NameManager.GetPredefinedName(PredefinedName.PN_INVOCATIONLIST); GetSymbolLoader().RuntimeBinderSymbolTable.PopulateSymbolTableWithName(predefinedName2.Text, null, cType2.AssociatedSystemType); PropertySymbol propertySymbol = GetSymbolLoader().LookupAggMember(predefinedName2, owningAggregate, symbmask_t.MASK_PropertySymbol).AsPropertySymbol(); MethPropWithInst mwi = new MethPropWithInst(propertySymbol, cType2.AsAggregateType()); ExprMemberGroup pMemGroup2 = GetExprFactory().CreateMemGroup(pObject, mwi); PropWithType pwt = new PropWithType(propertySymbol, cType2.AsAggregateType()); return BindToProperty(pObject, pwt, bindFlags, null, null, pMemGroup2); } return exprField2; } internal Expr BindToProperty(Expr pObject, PropWithType pwt, BindingFlag bindFlags, Expr args, AggregateType pOtherType, ExprMemberGroup 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.OptionalObject = pObject; CType pType = GetTypes().SubstType(pwt.Prop().RetType, pwt.GetType()); if (pObject != null && !pObject.IsOK) { ExprProperty exprProperty = GetExprFactory().CreateProperty(pType, expr, args, pMemGroup, pwt, null, null); if (!pIsMatchingStatic) exprProperty.SetMismatchedStaticBit(); exprProperty.SetError(); return exprProperty; } 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); } } } ExprProperty exprProperty2 = GetExprFactory().CreateProperty(pType, expr, args, pMemGroup, pwt, pmwtGet, pmwtSet); if (!pIsMatchingStatic) exprProperty2.SetMismatchedStaticBit(); if ((BindingFlag.BIND_BASECALL & bindFlags) != 0) exprProperty2.Flags |= EXPRFLAG.EXF_ASFINALLYLEAVE; else if (pfConstrained && pObject != null) { exprProperty2.Flags |= EXPRFLAG.EXF_UNREALIZEDGOTO; } if (exprProperty2.OptionalArguments != null) verifyMethodArgs(exprProperty2, expr?.Type); if ((bool)pmwtSet && objectIsLvalue(exprProperty2.MemberGroup.OptionalObject)) exprProperty2.Flags |= EXPRFLAG.EXF_LVALUE; if (pOtherType != null) exprProperty2.Flags |= EXPRFLAG.EXF_SAMENAMETYPE; return exprProperty2; } 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.Count == 1) { TypeArray typeArray = GetTypes().SubstTypeArray(methodSymbol.Params, aggregateType); CType cType2 = typeArray[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); ExprMemberGroup 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); ExprMemberGroup 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[0], candidateFunctionMember.mpwi) : BindLiftedUDUnop(arg, candidateFunctionMember.params[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); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, cType2, arg, pMemberGroup, null); exprCall.MethWithInst = new MethWithInst(mpwi); exprCall.CastOfNonLiftedResultToLiftedType = mustCast(expr, cType2, (CONVERTTYPE)0); exprCall.NullableCallLiftKind = NullableCallLiftKind.Operator; return exprCall; } private ExprCall BindUDUnopCall(Expr arg, CType typeArg, MethPropWithInst mpwi) { CType cType = GetTypes().SubstType(mpwi.Meth().RetType, mpwi.GetType()); checkUnsafe(cType); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, cType, mustConvert(arg, typeArg), pMemberGroup, null); exprCall.MethWithInst = new MethWithInst(mpwi); verifyMethodArgs(exprCall, mpwi.GetType()); return exprCall; } private bool BindMethodGroupToArgumentsCore(out GroupToArgsBinderResult pResults, BindingFlag bindFlags, ExprMemberGroup grp, ref Expr args, int carg, bool bindingCollectionAdd, bool bHasNamedArgumentSpecifiers) { ArgInfos argInfos = new ArgInfos { carg = carg }; FillInArgInfoFromArgList(argInfos, args); ArgInfos argInfos2 = new ArgInfos { carg = carg }; FillInArgInfoFromArgList(argInfos2, args); GroupToArgsBinder groupToArgsBinder = new GroupToArgsBinder(this, bindFlags, grp, argInfos, argInfos2, bHasNamedArgumentSpecifiers, null); bool result = bindingCollectionAdd ? groupToArgsBinder.BindCollectionAddArgs() : groupToArgsBinder.Bind(true); pResults = groupToArgsBinder.GetResultsOfBind(); return result; } internal Expr BindMethodGroupToArguments(BindingFlag bindFlags, ExprMemberGroup grp, Expr args) { bool typeErrors; int carg = CountArguments(args, out typeErrors); Expr optionalObject = grp.OptionalObject; 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.SymKind != SYMKIND.SK_PropertySymbol) return BindToMethod(new MethWithInst(bestResult), args, grp, (MemLookFlags)grp.Flags); return BindToProperty(grp.OptionalObject, 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) { ExprList exprList; Expr expr2; if ((exprList = (expr as ExprList)) != null) { expr2 = exprList.OptionalElement; expr = exprList.OptionalNextListNode; } else { expr2 = expr; expr = null; } if (expr2 is ExprNamedArgumentSpecification) seenNamed = true; else if (seenNamed) { GetErrorContext().Error(ErrorCode.ERR_NamedArgumentSpecificationBeforeFixedArgument, Array.Empty<ErrArg>()); return false; } } return true; } private ExprOperator BadOperatorTypesError(ExpressionKind ek, Expr pOperand1, Expr pOperand2) { return BadOperatorTypesError(ek, pOperand1, pOperand2, null); } private ExprOperator 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); ExprOperator exprOperator = GetExprFactory().CreateOperator(ek, pTypeErr, pOperand1, pOperand2); exprOperator.SetError(); return exprOperator; } private Expr UnwrapExpression(Expr pExpression) { ExprWrap exprWrap; while ((exprWrap = (pExpression as ExprWrap)) != null) { Expr optionalExpression = exprWrap.OptionalExpression; if (optionalExpression == null) break; pExpression = optionalExpression; } return pExpression; } 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; } } private void CheckLvalueProp(ExprProperty prop) { if (prop.IsBaseCall && prop.MethWithTypeSet.Meth().isAbstract) ErrorContext.Error(ErrorCode.ERR_AbstractBaseCall, prop.MethWithTypeSet); else { CType type = null; if (prop.OptionalObjectThrough != null) type = prop.OptionalObjectThrough.Type; CheckPropertyAccess(prop.MethWithTypeSet, prop.PropWithTypeSlot, type); } } private 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; } } private bool checkLvalue(Expr expr, CheckLvalueKind kind) { if (!expr.IsOK) return false; if (expr.isLvalue()) { ExprProperty prop; if ((prop = (expr as ExprProperty)) != null) CheckLvalueProp(prop); markFieldAssigned(expr); return true; } ExpressionKind kind2 = expr.Kind; if (kind2 <= ExpressionKind.Constant) { switch (kind2) { case ExpressionKind.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.Constant: break; default: goto IL_0167; } } else { switch (kind2) { case ExpressionKind.Property: goto IL_0069; case ExpressionKind.MemberGroup: { ErrorCode id = (kind == CheckLvalueKind.OutParameter) ? ErrorCode.ERR_RefReadonlyLocalCause : ErrorCode.ERR_AssgReadonlyLocalCause; ErrorContext.Error(id, ((ExprMemberGroup)expr).Name, new ErrArgIds(MessageID.MethodGroup)); return false; } } if ((uint)(kind2 - 30) > 1) goto IL_0167; } ErrorContext.Error(GetStandardLvalueError(kind), Array.Empty<ErrArg>()); return false; IL_0167: return !TryReportLvalueFailure(expr, kind); IL_0069: if (kind == CheckLvalueKind.OutParameter) { ErrorContext.Error(ErrorCode.ERR_RefProperty, Array.Empty<ErrArg>()); return true; } ExprProperty exprProperty = (ExprProperty)expr; if (!(bool)exprProperty.MethWithTypeSet) { ErrorContext.Error(ErrorCode.ERR_AssgReadonlyProp, exprProperty.PropWithTypeSlot); return true; } goto IL_0167; } private 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.Count; i++) { CType cType = params[i]; if (cType.isUnsafe()) checkUnsafe(cType); if (flag && cType.IsParameterModifierType()) SetExternalRef(cType); } } } private 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) return null; 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(); ExprField exprField; if ((exprField = (pObject as ExprField)) != null && !exprField.FieldWithType.Field().isAssigned && !swt.Sym.IsFieldSymbol() && cType.isStructType() && !cType.isPredefined()) exprField.FieldWithType.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) { return false; } return true; } private bool objectIsLvalue(Expr pObject) { if (pObject != null && ((pObject.Flags & EXPRFLAG.EXF_LVALUE) == (EXPRFLAG)0 || pObject.Kind == ExpressionKind.Property)) return !pObject.Type.isStructOrEnum(); return true; } private 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(); } } } private void verifyMethodArgs(IExprWithArgs call, CType callingObjectType) { Expr optionalArguments = call.OptionalArguments; SymWithType symWithType = call.GetSymWithType(); MethodOrPropertySymbol mp = symWithType.Sym.AsMethodOrPropertySymbol(); TypeArray pTypeArgs = (call as ExprCall)?.MethWithInst.TypeArgs; AdjustCallArgumentsForParams(callingObjectType, symWithType.GetType(), mp, pTypeArgs, optionalArguments, out Expr newArgs); call.OptionalArguments = newArgs; } private 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.Count; 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; ExpressionIterator expressionIterator = new ExpressionIterator(argsPtr); if (argsPtr != null) { while (true) { if (expressionIterator.AtEnd()) return; Expr expr = expressionIterator.Current(); if (!expr.Type.IsParameterModifierType()) { switch (num) { case 1: break; default: goto IL_00ec; case 0: goto IL_0296; } if (mp.isParamArray && num3 > mp.Params.Count) break; goto IL_00ec; } if (num != 0) num--; if (flag) SetExternalRef(expr.Type); GetExprFactory().AppendItemToList(expr, ref newArgs, ref last); goto IL_0296; IL_0296: num2++; if (num != 0 && mp.isParamArray && num2 == num3) { expr = null; expressionIterator.MoveNext(); break; } expressionIterator.MoveNext(); continue; IL_00ec: Expr expr2 = expr; ExprNamedArgumentSpecification exprNamedArgumentSpecification; Expr expr3; if ((exprNamedArgumentSpecification = (expr2 as ExprNamedArgumentSpecification)) != null) { int num4 = 0; foreach (Name parameterName in methodOrPropertySymbol.ParameterNames) { if (parameterName == exprNamedArgumentSpecification.Name) break; num4++; } CType dest = GetTypes().SubstType(params[num4], type, pTypeArgs); if (!canConvert(exprNamedArgumentSpecification.Value, dest) && mp.isParamArray && num4 == mp.Params.Count - 1) { CType cType = GetTypes().SubstType(mp.Params[mp.Params.Count - 1], type, pTypeArgs); CType elementType = cType.AsArrayType().GetElementType(); ExprArrayInit exprArrayInit = GetExprFactory().CreateArrayInit((EXPRFLAG)0, cType, null, null, null); exprArrayInit.GeneratedForParamArray = true; exprArrayInit.DimensionSizes = new int[1] { exprArrayInit.DimensionSize }; exprArrayInit.DimensionSize = 1; exprArrayInit.OptionalArguments = exprNamedArgumentSpecification.Value; exprNamedArgumentSpecification.Value = exprArrayInit; flag2 = true; } else exprNamedArgumentSpecification.Value = tryConvert(exprNamedArgumentSpecification.Value, dest); expr3 = expr2; } else { CType dest2 = GetTypes().SubstType(params[num2], type, pTypeArgs); expr3 = tryConvert(expr, dest2); } if (expr3 == null) { if (mp.isParamArray && num == 1 && num3 >= mp.Params.Count) break; return; } expr = expr3; GetExprFactory().AppendItemToList(expr3, ref newArgs, ref last); num--; goto IL_0296; } } else if (!mp.isParamArray) { return; } if (!flag2) { CType cType2 = GetTypes().SubstType(mp.Params[mp.Params.Count - 1], type, pTypeArgs); if (cType2.IsArrayType() && cType2.AsArrayType().IsSZArray) { CType elementType2 = cType2.AsArrayType().GetElementType(); ExprArrayInit exprArrayInit2 = GetExprFactory().CreateArrayInit((EXPRFLAG)0, cType2, null, null, null); exprArrayInit2.GeneratedForParamArray = true; exprArrayInit2.DimensionSizes = new int[1] { exprArrayInit2.DimensionSize }; if (expressionIterator.AtEnd()) { exprArrayInit2.DimensionSize = 0; exprArrayInit2.DimensionSizes[0] = 0; exprArrayInit2.OptionalArguments = null; argsPtr = ((argsPtr != null) ? ((Expr)GetExprFactory().CreateList(argsPtr, exprArrayInit2)) : ((Expr)exprArrayInit2)); GetExprFactory().AppendItemToList(exprArrayInit2, ref newArgs, ref last); } else { Expr first = null; Expr last2 = null; int num5 = 0; while (!expressionIterator.AtEnd()) { Expr expr4 = expressionIterator.Current(); num5++; ExprNamedArgumentSpecification exprNamedArgumentSpecification2; if ((exprNamedArgumentSpecification2 = (expr4 as ExprNamedArgumentSpecification)) != null) exprNamedArgumentSpecification2.Value = tryConvert(exprNamedArgumentSpecification2.Value, elementType2); else expr4 = tryConvert(expr4, elementType2); GetExprFactory().AppendItemToList(expr4, ref first, ref last2); expressionIterator.MoveNext(); } exprArrayInit2.DimensionSize = num5; exprArrayInit2.DimensionSizes[0] = num5; exprArrayInit2.OptionalArguments = first; GetExprFactory().AppendItemToList(exprArrayInit2, ref newArgs, ref last); } } } } private void markFieldAssigned(Expr expr) { ExprField exprField; if ((expr.Flags & EXPRFLAG.EXF_LVALUE) != 0 && (exprField = (expr as ExprField)) != null) { FieldSymbol fieldSymbol; do { fieldSymbol = exprField.FieldWithType.Field(); fieldSymbol.isAssigned = true; expr = exprField.OptionalObject; } while (fieldSymbol.getClass().IsStruct() && !fieldSymbol.isStatic && expr != null && (exprField = (expr as ExprField)) != null); } } private 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) { ExprList exprList; Expr expr2; if ((exprList = (expr as ExprList)) != null) { expr2 = exprList.OptionalElement; expr = exprList.OptionalNextListNode; } 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); } private bool TryGetExpandedParams(TypeArray params, int count, out TypeArray ppExpandedParams) { CType[] array; if (count < params.Count - 1) { array = new CType[params.Count - 1]; params.CopyItems(0, params.Count - 1, array); ppExpandedParams = GetGlobalSymbols().AllocParams(params.Count - 1, array); return true; } array = new CType[count]; params.CopyItems(0, params.Count - 1, array); CType cType = params[params.Count - 1]; CType cType2 = null; if (!cType.IsArrayType()) { ppExpandedParams = null; return false; } cType2 = cType.AsArrayType().GetElementType(); for (int i = params.Count - 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; } private static bool isConstantInRange(ExprConstant exprSrc, CType typeDest) { return isConstantInRange(exprSrc, typeDest, false); } private 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.Val.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 uInt64Value = exprSrc.UInt64Value; switch (fUNDTYPE2) { case FUNDTYPE.FT_I1: if (uInt64Value <= 127) return true; break; case FUNDTYPE.FT_I2: if (uInt64Value <= 32767) return true; break; case FUNDTYPE.FT_I4: if (uInt64Value <= 2147483647) return true; break; case FUNDTYPE.FT_I8: if (uInt64Value <= 9223372036854775807) return true; break; case FUNDTYPE.FT_U1: if (uInt64Value <= 255) return true; break; case FUNDTYPE.FT_U2: if (uInt64Value <= 65535) return true; break; case FUNDTYPE.FT_U4: if (uInt64Value <= uint.MaxValue) return true; break; case FUNDTYPE.FT_U8: return true; } } else { long int64Value = exprSrc.Int64Value; switch (fUNDTYPE2) { case FUNDTYPE.FT_I1: if (int64Value >= -128 && int64Value <= 127) return true; break; case FUNDTYPE.FT_I2: if (int64Value >= -32768 && int64Value <= 32767) return true; break; case FUNDTYPE.FT_I4: if (int64Value >= I64(-2147483648) && int64Value <= I64(2147483647)) return true; break; case FUNDTYPE.FT_I8: return true; case FUNDTYPE.FT_U1: if (int64Value >= 0 && int64Value <= 255) return true; break; case FUNDTYPE.FT_U2: if (int64Value >= 0 && int64Value <= 65535) return true; break; case FUNDTYPE.FT_U4: if (int64Value >= 0 && int64Value <= I64(4294967295)) return true; break; case FUNDTYPE.FT_U8: if (int64Value >= 0) return true; break; } } return false; } private Name ekName(ExpressionKind ek) { return NameManager.GetPredefinedName(s_EK2NAME[(int)(ek - 38)]); } private void checkUnsafe(CType type) { checkUnsafe(type, ErrorCode.ERR_UnsafeNeeded, null); } private void checkUnsafe(CType type, ErrorCode errCode, ErrArg pArg) { if (type == null || type.isUnsafe()) { if (ReportUnsafeErrors()) { if (pArg != null) ErrorContext.Error(errCode, pArg); else ErrorContext.Error(errCode, Array.Empty<ErrArg>()); } RecordUnsafeUsage(); } } private Declaration ContextForMemberLookup() { return Context.ContextForMemberLookup; } private bool ReportUnsafeErrors() { return Context.ReportUnsafeErrors; } private void RecordUnsafeUsage() { RecordUnsafeUsage(Context); } private ExprWrap WrapShortLivedExpression(Expr expr) { return GetExprFactory().CreateWrap(null, expr); } private ExprAssignment GenerateOptimizedAssignment(Expr op1, Expr op2) { return GetExprFactory().CreateAssignment(op1, op2); } private static void RecordUnsafeUsage(BindingContext context) { context.ReportUnsafeErrors = false; } internal static int CountArguments(Expr args, out bool typeErrors) { int num = 0; typeErrors = false; Expr expr = args; while (expr != null) { ExprList exprList; Expr expr2; if ((exprList = (expr as ExprList)) != null) { expr2 = exprList.OptionalElement; expr = exprList.OptionalNextListNode; } else { expr2 = expr; expr = null; } if (expr2.Type == null || expr2.Type.IsErrorType()) typeErrors = true; num++; } return num; } private Expr BindNubValue(Expr exprSrc) { return m_nullable.BindValue(exprSrc); } private ExprCall BindNubNew(Expr exprSrc) { return m_nullable.BindNew(exprSrc); } private ExprBinOp 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 - 64 + 58, 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); } private 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; } private 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 = (((uint)(convKind3 - 1) <= 1) ? (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 = (((uint)(convKind3 - 1) <= 1) ? (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 = (((uint)(convKind3 - 1) <= 1) ? (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 = (((uint)(convKind3 - 1) <= 1) ? (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; } private 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; } private 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 (ExprBinOp)expr; } 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; ExprBinOp exprBinOp = BindUserDefinedBinOp(ek, binOpArgInfo); if (exprBinOp != null) return exprBinOp; 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); } private 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); } if (IsEnumArithmeticBinOp(ek, info)) { Expr expr3 = info.arg1; Expr expr4 = info.arg2; if (bofs.ConvertOperandsBeforeBinding()) { expr3 = mustConvert(expr3, bofs.Type1()); expr4 = mustConvert(expr4, bofs.Type2()); } return BindLiftedEnumArithmeticBinOp(ek, flags, expr3, expr4); } return BindLiftedStandardBinOp(info, bofs, ek, flags); } private ExprBinOp 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 expr2 = pArgument; if (pParameterType.IsNullableType()) { if (expr2.isNull()) expr2 = mustCast(expr2, pParameterType); expr2 = mustCast(expr2, pParameterType.AsNullableType().GetUnderlyingType()); if (bConvertBeforeLift) MarkAsIntermediateConversion(expr2); } else expr2 = expr; ppLiftedArgument = expr; ppNonLiftedArgument = expr2; } private 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)); } private 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; } private bool IsEnumArithmeticBinOp(ExpressionKind ek, BinOpArgInfo info) { switch (ek) { case ExpressionKind.Add: return info.typeRaw1.isEnumType() ^ info.typeRaw2.isEnumType(); case ExpressionKind.Subtract: return info.typeRaw1.isEnumType() | info.typeRaw2.isEnumType(); default: return false; } } private 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; } private 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.Block; uok = UnaOpKind.Plus; switch (op) { case OperatorKind.OP_UPLUS: uok = UnaOpKind.Plus; ek = ExpressionKind.UnaryPlus; break; case OperatorKind.OP_NEG: if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.Minus; ek = ExpressionKind.Negate; break; case OperatorKind.OP_BITNOT: uok = UnaOpKind.Tilde; ek = ExpressionKind.BitwiseNot; break; case OperatorKind.OP_LOGNOT: uok = UnaOpKind.Bang; ek = ExpressionKind.LogicalNot; break; case OperatorKind.OP_POSTINC: flags |= EXPRFLAG.EXF_OPERATOR; if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.Add; break; case OperatorKind.OP_PREINC: if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.Add; break; case OperatorKind.OP_POSTDEC: flags |= EXPRFLAG.EXF_OPERATOR; if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.Subtract; break; case OperatorKind.OP_PREDEC: if (bChecked) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; uok = UnaOpKind.IncDec; ek = ExpressionKind.Subtract; 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.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 - 51 + 42, exprMultiGet); if (expr != null) { if (expr.Type != null && !expr.Type.IsErrorType() && expr.Type != type) expr = mustConvert(expr, type); ExprMulti exprMulti2 = exprMultiGet.OptionalMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, type, pArgument, expr); if (!checkLvalue(pArgument, CheckLvalueKind.Increment)) exprMulti2.SetError(); ppResult = exprMulti2; 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 = (((uint)(convKind2 - 1) <= 1) ? (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 ExprOperator 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 ExprOperator BindIntBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { return BindIntOp(ek, flags, arg1, arg2, arg1.Type.getPredefType()); } private ExprOperator BindIntUnaOp(ExpressionKind ek, EXPRFLAG flags, Expr arg) { return BindIntOp(ek, flags, arg, null, arg.Type.getPredefType()); } private ExprOperator BindRealBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { return bindFloatOp(ek, flags, arg1, arg2); } private ExprOperator 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.EXF_CHECKOVERFLOW; 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) { 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.Add) ? ExpressionKind.DecimalInc : ExpressionKind.DecimalDec); PREDEFMETH predefMeth = (ek == ExpressionKind.DecimalInc) ? PREDEFMETH.PM_DECIMAL_OPINCREMENT : PREDEFMETH.PM_DECIMAL_OPDECREMENT; return CreateUnaryOpForPredefMethodCall(ek, predefMeth, type, exprVal); } case FUNDTYPE.FT_PTR: { ConstVal cv = ConstVal.Get(1); return BindPtrBinOp(ek, flags, exprVal, GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), cv)); } case FUNDTYPE.FT_I1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_U2: { typeTmp = GetReqPDT(PredefinedType.PT_INT); ConstVal cv = ConstVal.Get(1); return LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); } case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: { ConstVal cv = ConstVal.Get(1); return LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); } case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: { ConstVal cv = ConstVal.Get(1); return LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); } case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: { ConstVal cv = ConstVal.Get(1); return LScalar(ek, flags, exprVal, type, cv, 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); return exprMultiGet.OptionalMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.Type, arg, pOp); } 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 = expr; expr2 = mustCast(expr2, nullableType.GetUnderlyingType()); Expr expr3 = BindIncOpCore(ek, flags, expr2, nullableType.GetUnderlyingType()); expr = mustCast(expr, nullableType); ExprUnaryOp exprUnaryOp = GetExprFactory().CreateUnaryOp((ek == ExpressionKind.Add) ? ExpressionKind.Inc : ExpressionKind.Dec, arg.Type, expr); mustCast(mustCast(expr3, nullableType), arg.Type); exprUnaryOp.Flags |= flags; return exprMultiGet.OptionalMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.Type, arg, exprUnaryOp); } private ExprBinOp BindDecBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { CType optPDT = GetOptPDT(PredefinedType.PT_DECIMAL); CType pType; if ((uint)(ek - 45) > 5) { if ((uint)(ek - 51) > 4) { VSFAIL("Bad kind"); pType = null; } else pType = optPDT; } else pType = GetReqPDT(PredefinedType.PT_BOOL); return GetExprFactory().CreateBinop(ek, pType, arg1, arg2); } private ExprUnaryOp BindDecUnaOp(ExpressionKind ek, EXPRFLAG flags, Expr arg) { CType optPDT = GetOptPDT(PredefinedType.PT_DECIMAL); if (ek == ExpressionKind.Negate) { PREDEFMETH predefMeth = PREDEFMETH.PM_DECIMAL_OPUNARYMINUS; return CreateUnaryOpForPredefMethodCall(ExpressionKind.DecimalNegate, predefMeth, optPDT, arg); } return GetExprFactory().CreateUnaryOp(ExpressionKind.UnaryPlus, optPDT, arg); } private Expr BindStrBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { return bindStringConcat(arg1, arg2); } private ExprBinOp BindShiftOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { PredefinedType predefType = arg1.Type.getPredefType(); return GetExprFactory().CreateBinop(ek, arg1.Type, arg1, arg2); } private ExprBinOp BindBoolBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { return GetExprFactory().CreateBinop(ek, GetReqPDT(PredefinedType.PT_BOOL), arg1, arg2); } private ExprOperator 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 expr3 = CNullable.StripNullableConstructor(expr1); Expr expr4 = CNullable.StripNullableConstructor(expr2); Expr expr5 = null; if (!expr3.Type.IsNullableType() && !expr4.Type.IsNullableType()) expr5 = BindBoolBinOp(ek, flags, expr3, expr4); ExprBinOp exprBinOp = GetExprFactory().CreateBinop(ek, nullable, expr1, expr2); if (expr5 != null) mustCast(expr5, 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.LogicalNot, reqPDT, arg); return GetExprFactory().CreateConstant(reqPDT, ConstVal.Get(((ExprConstant)const).Val.Int32Val == 0)); } private ExprBinOp BindStrCmpOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { PREDEFMETH predefMeth = (ek == ExpressionKind.Eq) ? PREDEFMETH.PM_STRING_OPEQUALITY : PREDEFMETH.PM_STRING_OPINEQUALITY; ek = ((ek == ExpressionKind.Eq) ? ExpressionKind.StringEq : ExpressionKind.StringNotEq); return CreateBinopForPredefMethodCall(ek, predefMeth, GetReqPDT(PredefinedType.PT_BOOL), arg1, arg2); } private ExprBinOp 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.Add: predefMeth = PREDEFMETH.PM_DELEGATE_COMBINE; retType = arg1.Type; ek = ExpressionKind.DelegateAdd; break; case ExpressionKind.Subtract: predefMeth = PREDEFMETH.PM_DELEGATE_REMOVE; retType = arg1.Type; ek = ExpressionKind.DelegateSubtract; break; case ExpressionKind.Eq: predefMeth = PREDEFMETH.PM_DELEGATE_OPEQUALITY; retType = GetReqPDT(PredefinedType.PT_BOOL); ek = ExpressionKind.DelegateEq; break; case ExpressionKind.NotEq: predefMeth = PREDEFMETH.PM_DELEGATE_OPINEQUALITY; retType = GetReqPDT(PredefinedType.PT_BOOL); ek = ExpressionKind.DelegateNotEq; 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 BindLiftedEnumArithmeticBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2) { CType cType = arg1.Type.IsNullableType() ? arg1.Type.AsNullableType().UnderlyingType : arg1.Type; CType cType2 = arg2.Type.IsNullableType() ? arg2.Type.AsNullableType().UnderlyingType : arg2.Type; if (cType.IsNullType()) cType = cType2.underlyingEnumType(); else if (cType2.IsNullType()) { cType2 = cType.underlyingEnumType(); } AggregateType ppEnumType; NullableType nullable = GetTypes().GetNullable(GetEnumBinOpType(ek, cType, cType2, out ppEnumType)); PredefinedType pt; switch (ppEnumType.fundType()) { default: pt = PredefinedType.PT_INT; break; case FUNDTYPE.FT_U4: pt = PredefinedType.PT_UINT; break; case FUNDTYPE.FT_I8: pt = PredefinedType.PT_LONG; break; case FUNDTYPE.FT_U8: pt = PredefinedType.PT_ULONG; break; } NullableType nullable2 = GetTypes().GetNullable(GetReqPDT(pt)); arg1 = mustCast(arg1, nullable2, CONVERTTYPE.NOUDC); arg2 = mustCast(arg2, nullable2, CONVERTTYPE.NOUDC); ExprBinOp exprBinOp = GetExprFactory().CreateBinop(ek, nullable2, arg1, arg2); exprBinOp.IsLifted = true; exprBinOp.Flags |= flags; if (!exprBinOp.IsOK) return exprBinOp; if (exprBinOp.Type != nullable) return mustCast(exprBinOp, nullable, CONVERTTYPE.NOUDC); return exprBinOp; } private Expr BindEnumUnaOp(ExpressionKind ek, EXPRFLAG flags, Expr arg) { CType type = ((ExprCast)arg).Argument.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.Add: if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Add; break; case ExpressionKind.Subtract: if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Sub; break; case ExpressionKind.Divide: case ExpressionKind.Modulo: flags |= EXPRFLAG.EXF_ASSGOP; if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Mul; break; case ExpressionKind.Multiply: if (Context.CheckedNormal) flags |= EXPRFLAG.EXF_CHECKOVERFLOW; pBinopKind = BinOpKind.Mul; break; case ExpressionKind.BitwiseAnd: case ExpressionKind.BitwiseOr: pBinopKind = BinOpKind.Bitwise; break; case ExpressionKind.BitwiseExclusiveOr: pBinopKind = BinOpKind.BitXor; break; case ExpressionKind.LeftShirt: case ExpressionKind.RightShift: pBinopKind = BinOpKind.Shift; break; case ExpressionKind.LogicalAnd: case ExpressionKind.LogicalOr: pBinopKind = BinOpKind.Logical; break; case ExpressionKind.LessThan: case ExpressionKind.LessThanOrEqual: case ExpressionKind.GreaterThan: case ExpressionKind.GreaterThanOrEqual: pBinopKind = BinOpKind.Compare; break; case ExpressionKind.Eq: case ExpressionKind.NotEq: pBinopKind = BinOpKind.Equal; break; default: VSFAIL("Bad ek"); pBinopKind = BinOpKind.Add; return false; } return true; } private ExprOperator BindIntOp(ExpressionKind kind, EXPRFLAG flags, Expr op1, Expr op2, PredefinedType ptOp) { CType reqPDT = GetReqPDT(ptOp); if (kind == ExpressionKind.Negate) return BindIntegerNeg(flags, op1, ptOp); CType pType = kind.IsRelational() ? GetReqPDT(PredefinedType.PT_BOOL) : reqPDT; ExprOperator exprOperator = GetExprFactory().CreateOperator(kind, pType, op1, op2); exprOperator.Flags |= flags; return exprOperator; } private ExprOperator BindIntegerNeg(EXPRFLAG flags, Expr op, PredefinedType ptOp) { CType reqPDT = GetReqPDT(ptOp); switch (ptOp) { case PredefinedType.PT_ULONG: return BadOperatorTypesError(ExpressionKind.Negate, 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 ExprOperator bindFloatOp(ExpressionKind kind, EXPRFLAG flags, Expr op1, Expr op2) { CType pType = kind.IsRelational() ? GetReqPDT(PredefinedType.PT_BOOL) : op1.Type; ExprOperator exprOperator = GetExprFactory().CreateOperator(kind, pType, op1, op2); flags = ~EXPRFLAG.EXF_CHECKOVERFLOW; exprOperator.Flags |= flags; return exprOperator; } private ExprConcat bindStringConcat(Expr op1, Expr op2) { return GetExprFactory().CreateConcat(op1, op2); } private ExprOperator 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); ExprOperator exprOperator = GetExprFactory().CreateOperator(ek, null, op1, op2); exprOperator.SetError(); return exprOperator; } private Expr BindUserBoolOp(ExpressionKind kind, ExprCall pCall) { RETAILVERIFY(pCall != null); RETAILVERIFY(pCall.MethWithInst.Meth() != null); RETAILVERIFY(pCall.OptionalArguments != null); CType type = pCall.Type; if (!GetTypes().SubstEqualTypes(type, pCall.MethWithInst.Meth().Params[0], type) || !GetTypes().SubstEqualTypes(type, pCall.MethWithInst.Meth().Params[1], type)) { MethWithInst mwi = new MethWithInst(null, null); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, mwi); ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, null, null, pMemberGroup, null); exprCall.SetError(); GetErrorContext().Error(ErrorCode.ERR_BadBoolOp, pCall.MethWithInst); return GetExprFactory().CreateUserLogOpError(type, exprCall, pCall); } ExprList exprList = (ExprList)pCall.OptionalArguments; Expr optionalElement = exprList.OptionalElement; ExprWrap exprWrap = (ExprWrap)(exprList.OptionalElement = WrapShortLivedExpression(optionalElement)); SymbolLoader.RuntimeBinderSymbolTable.PopulateSymbolTableWithName("op_True", null, exprWrap.Type.AssociatedSystemType); SymbolLoader.RuntimeBinderSymbolTable.PopulateSymbolTableWithName("op_False", null, exprWrap.Type.AssociatedSystemType); Expr expr2 = bindUDUnop(ExpressionKind.True, exprWrap); Expr expr3 = bindUDUnop(ExpressionKind.False, exprWrap); if (expr2 == null || expr3 == null) { Expr expr4 = (expr2 != null) ? expr2 : expr3; if (expr4 == null) { MethWithInst mwi2 = new MethWithInst(null, null); ExprMemberGroup pMemberGroup2 = GetExprFactory().CreateMemGroup(null, mwi2); expr4 = GetExprFactory().CreateCall((EXPRFLAG)0, null, exprWrap, 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.LogicalAnd) ? 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[0].IsNonNubValType()) return false; if (!Params[1].IsNonNubValType()) return false; CType cType = GetTypes().SubstType(method.RetType, ats); if (!cType.IsNonNubValType()) return false; if ((uint)(ek - 45) <= 1) { if (!cType.isPredefType(PredefinedType.PT_BOOL)) return false; if (Params[0] != Params[1]) return false; return true; } if ((uint)(ek - 47) <= 3) { if (!cType.isPredefType(PredefinedType.PT_BOOL)) return false; return true; } return true; } private bool UserDefinedBinaryOperatorIsApplicable(List<CandidateFunctionMember> candidateList, ExpressionKind ek, MethodSymbol method, AggregateType ats, Expr arg1, Expr arg2, bool fDontLift) { if (!method.isOperator || method.Params.Count != 2) return false; TypeArray typeArray = GetTypes().SubstTypeArray(method.Params, ats); if (canConvert(arg1, typeArray[0]) && canConvert(arg2, typeArray[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[0]), GetTypes().GetNullable(typeArray[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); ExprMemberGroup 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); ExprMemberGroup 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[0]); arg2 = mustConvert(arg2, Params[1]); ExprList pOptionalArguments = GetExprFactory().CreateList(arg1, arg2); checkUnsafe(arg1.Type); checkUnsafe(arg2.Type); checkUnsafe(typeRet); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, typeRet, pOptionalArguments, pMemberGroup, null); exprCall.MethWithInst = 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[0], CONVERTTYPE.NOUDC)) expr = mustConvert(arg1, Params[0]); if (!canConvert(arg2.Type.StripNubs(), typeArray[1], CONVERTTYPE.NOUDC)) expr2 = mustConvert(arg2, Params[1]); Expr arg3 = mustCast(expr, typeArray[0]); Expr arg4 = mustCast(expr2, typeArray[1]); CType cType2 = ((uint)(ek - 45) <= 1) ? cType : (((uint)(ek - 47) <= 3) ? cType : GetTypes().GetNullable(cType)); ExprCall expr3 = BindUDBinopCall(arg3, arg4, typeArray, cType, mpwi); ExprList pOptionalArguments = GetExprFactory().CreateList(expr, expr2); ExprMemberGroup pMemberGroup = GetExprFactory().CreateMemGroup(null, mpwi); ExprCall exprCall = GetExprFactory().CreateCall((EXPRFLAG)0, cType2, pOptionalArguments, pMemberGroup, null); exprCall.MethWithInst = new MethWithInst(mpwi); switch (ek) { case ExpressionKind.Eq: exprCall.NullableCallLiftKind = NullableCallLiftKind.EqualityOperator; break; case ExpressionKind.NotEq: exprCall.NullableCallLiftKind = NullableCallLiftKind.InequalityOperator; break; default: exprCall.NullableCallLiftKind = NullableCallLiftKind.Operator; break; } exprCall.CastOfNonLiftedResultToLiftedType = mustCast(expr3, 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) { default: if ((uint)(ek - 58) > 2) result = GetReqPDT(PredefinedType.PT_BOOL); break; case ExpressionKind.Subtract: if (aggregateType == aggregateType2) result = aggregateType3.underlyingEnumType(); break; case ExpressionKind.Add: 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.UserDefinedCallMethod = 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; } } }