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;
}
}
}