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 bool FindApplicableSignatures( EXPR pArgument, UnaOpMask unaryOpMask, List<UnaOpFullSig> pSignatures) { // All callers should already assert this to be the case. Debug.Assert(pArgument != null); Debug.Assert(pArgument.type != null); long iuosMinLift = GetSymbolLoader().FCanLift() ? 0 : g_rguos.Length; CType pArgumentType = pArgument.type; CType pRawType = pArgumentType.StripNubs(); PredefinedType pt = pArgumentType.isPredefined() ? pArgumentType.getPredefType() : PredefinedType.PT_COUNT; PredefinedType ptRaw = pRawType.isPredefined() ? pRawType.getPredefType() : PredefinedType.PT_COUNT; for (int index = 0; index < g_rguos.Length; index++) { UnaOpSig uos = g_rguos[index]; if ((uos.grfuom & unaryOpMask) == 0) { continue; } ConvKind cv = GetConvKind(pt, g_rguos[index].pt); CType typeSig = null; switch (cv) { default: VSFAIL("Shouldn't happen!"); continue; case ConvKind.None: continue; case ConvKind.Explicit: if (!pArgument.isCONSTANT_OK()) { continue; } if (canConvert(pArgument, typeSig = GetOptPDT(uos.pt))) { break; } if (index < iuosMinLift) { continue; } typeSig = GetSymbolLoader().GetTypeManager().GetNullable(typeSig); if (!canConvert(pArgument, typeSig)) { continue; } break; case ConvKind.Unknown: if (canConvert(pArgument, typeSig = GetOptPDT(uos.pt))) { break; } if (index < iuosMinLift) { continue; } typeSig = GetSymbolLoader().GetTypeManager().GetNullable(typeSig); if (!canConvert(pArgument, typeSig)) { continue; } break; case ConvKind.Implicit: break; case ConvKind.Identity: { UnaOpFullSig result = new UnaOpFullSig(this, uos); if (result.GetType() != null) { pSignatures.Add(result); return true; } } break; } if (typeSig != null && typeSig.IsNullableType()) { // Need to use a lifted signature. LiftFlags grflt = LiftFlags.None; switch (GetConvKind(ptRaw, uos.pt)) { default: grflt = grflt | LiftFlags.Convert1; break; case ConvKind.Implicit: case ConvKind.Identity: grflt = grflt | LiftFlags.Lift1; break; } pSignatures.Add(new UnaOpFullSig(typeSig, uos.pfn, grflt, uos.fnkind)); // NOTE: Can't skip any if we use the lifted signature because the // type might convert to int? and to long (but not to int) in which // case we should get an ambiguity. But we can skip the lifted ones.... iuosMinLift = index + uos.cuosSkip + 1; } else { // Record it as applicable and skip accordingly. UnaOpFullSig newResult = new UnaOpFullSig(this, uos); if (newResult.GetType() != null) { pSignatures.Add(newResult); } index += uos.cuosSkip; } } return false; }
///////////////////////////////////////////////////////////////////////////////// private UnaryOperatorSignatureFindResult PopulateSignatureList(EXPR pArgument, UnaOpKind unaryOpKind, UnaOpMask unaryOpMask, ExpressionKind exprKind, EXPRFLAG flags, List<UnaOpFullSig> pSignatures, out EXPR ppResult) { // We should have already checked argument != null and argument.type != null. Debug.Assert(pArgument != null); Debug.Assert(pArgument.type != null); ppResult = null; CType pArgumentType = pArgument.type; CType pRawType = pArgumentType.StripNubs(); PredefinedType ptRaw = pRawType.isPredefined() ? pRawType.getPredefType() : PredefinedType.PT_COUNT; // Find all applicable operator signatures. // First check for special ones (enum, ptr) and check for user defined ops. if (ptRaw > PredefinedType.PT_ULONG) { // Enum types are special in that they carry a set of "predefined" operators (~ and inc/dec). if (pRawType.isEnumType()) { if ((unaryOpMask & (UnaOpMask.Tilde | UnaOpMask.IncDec)) != 0) { // We have an exact match. LiftFlags liftFlags = LiftFlags.None; CType typeSig = pArgumentType; if (typeSig.IsNullableType()) { if (typeSig.AsNullableType().GetUnderlyingType() != pRawType) { typeSig = GetSymbolLoader().GetTypeManager().GetNullable(pRawType); } liftFlags = LiftFlags.Lift1; } if (unaryOpKind == UnaOpKind.Tilde) { pSignatures.Add(new UnaOpFullSig( typeSig.getAggregate().GetUnderlyingType(), BindEnumUnaOp, liftFlags, UnaOpFuncKind.EnumUnaOp)); } else { // For enums, we want to add the signature as the underlying type so that we'll // perform the conversions to and from the enum type. pSignatures.Add(new UnaOpFullSig( typeSig.getAggregate().GetUnderlyingType(), null, liftFlags, UnaOpFuncKind.None)); } return UnaryOperatorSignatureFindResult.Match; } } else if (unaryOpKind == UnaOpKind.IncDec) { // Check for pointers if (pArgumentType.IsPointerType()) { pSignatures.Add(new UnaOpFullSig( pArgumentType, null, LiftFlags.None, UnaOpFuncKind.None)); return UnaryOperatorSignatureFindResult.Match; } // Check for user defined inc/dec #if !CSEE EXPRMULTIGET exprGet = GetExprFactory().CreateMultiGet(0, pArgumentType, null); #else // CSEE EXPR exprGet = pArgument; #endif // CSEE EXPR exprVal = bindUDUnop((ExpressionKind)(exprKind - ExpressionKind.EK_ADD + ExpressionKind.EK_INC), exprGet); if (exprVal != null) { if (exprVal.type != null && !exprVal.type.IsErrorType() && exprVal.type != pArgumentType) { exprVal = mustConvert(exprVal, pArgumentType); } Debug.Assert(pArgument != null); EXPRMULTI exprMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, pArgumentType, pArgument, exprVal); #if ! CSEE exprGet.SetOptionalMulti(exprMulti); #endif // !CSEE // Check whether Lvalue can be assigned. checkLvalue may return true // despite reporting an error. if (!checkLvalue(pArgument, CheckLvalueKind.Increment)) { // This seems like it can never be reached - exprVal is only valid if // we have a UDUnop, and in order for checkLValue to return false, either the // arg has to not be OK, in which case we shouldn't get here, or we have an // AnonMeth, Lambda, or Constant, all of which cannot have UDUnops defined for them. exprMulti.SetError(); } ppResult = exprMulti; return UnaryOperatorSignatureFindResult.Return; } // Try for a predefined increment operator. } else { // Check for user defined. EXPR expr = bindUDUnop(exprKind, pArgument); if (expr != null) { ppResult = expr; return UnaryOperatorSignatureFindResult.Return; } } } return UnaryOperatorSignatureFindResult.Continue; }