Ejemplo n.º 1
0
        /////////////////////////////////////////////////////////////////////////////////

        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;
        }
Ejemplo n.º 2
0
        /////////////////////////////////////////////////////////////////////////////////
        // Bind a standard unary operator. Takes care of user defined operators, predefined operators
        // and lifting over nullable.

        private static bool CalculateExprAndUnaryOpKinds(
                OperatorKind op,
                bool bChecked,
                out /*out*/ ExpressionKind ek,
                out /*out*/ UnaOpKind uok,
                out /*out*/ EXPRFLAG flags)
        {
            flags = 0;
            ek = 0;
            uok = 0;
            switch (op)
            {
                case OperatorKind.OP_UPLUS:
                    uok = UnaOpKind.Plus;
                    ek = ExpressionKind.EK_UPLUS;
                    break;

                case OperatorKind.OP_NEG:
                    if (bChecked)
                    {
                        flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                    }
                    uok = UnaOpKind.Minus;
                    ek = ExpressionKind.EK_NEG;
                    break;

                case OperatorKind.OP_BITNOT:
                    uok = UnaOpKind.Tilde;
                    ek = ExpressionKind.EK_BITNOT;
                    break;

                case OperatorKind.OP_LOGNOT:
                    uok = UnaOpKind.Bang;
                    ek = ExpressionKind.EK_LOGNOT;
                    break;

                case OperatorKind.OP_POSTINC:
                    flags |= EXPRFLAG.EXF_ISPOSTOP;
                    if (bChecked)
                    {
                        flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                    }
                    uok = UnaOpKind.IncDec;
                    ek = ExpressionKind.EK_ADD;
                    break;

                case OperatorKind.OP_PREINC:
                    if (bChecked)
                    {
                        flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                    }
                    uok = UnaOpKind.IncDec;
                    ek = ExpressionKind.EK_ADD;
                    break;

                case OperatorKind.OP_POSTDEC:
                    flags |= EXPRFLAG.EXF_ISPOSTOP;
                    if (bChecked)
                    {
                        flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                    }
                    uok = UnaOpKind.IncDec;
                    ek = ExpressionKind.EK_SUB;
                    break;

                case OperatorKind.OP_PREDEC:
                    if (bChecked)
                    {
                        flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                    }
                    uok = UnaOpKind.IncDec;
                    ek = ExpressionKind.EK_SUB;
                    break;

                default:
                    VSFAIL("Bad op");
                    return false;
            }
            return true;
        }