예제 #1
0
        private void CheckLiftedUnaryOp(BoundUnaryOperator node)
        {
            Debug.Assert(node != null);

            if (!node.OperatorKind.IsLifted())
            {
                return;
            }

            // CS0458: The result of the expression is always 'null' of type '{0}'
            if (node.Operand.NullableNeverHasValue())
            {
                Error(ErrorCode.WRN_AlwaysNull, node, node.Type);
            }
        }
예제 #2
0
        /// <summary>
        /// This rewriter lowers pre-/post- increment/decrement operations (initially represented as
        /// unary operators). We use BoundSequenceExpressions because we need to capture the RHS of the
        /// assignment in a temp variable.
        /// </summary>
        /// <remarks>
        /// This rewriter assumes that it will be run before decimal rewriting (so that it does not have
        /// to lower decimal constants and operations) and call rewriting (so that it does not have to
        /// lower property accesses).
        /// </remarks>
        public override BoundNode VisitUnaryOperator(BoundUnaryOperator node)
        {
            switch (node.OperatorKind.Operator())
            {
            case UnaryOperatorKind.PrefixDecrement:
            case UnaryOperatorKind.PrefixIncrement:
            case UnaryOperatorKind.PostfixDecrement:
            case UnaryOperatorKind.PostfixIncrement:
                Debug.Assert(false);     // these should have been represented as a BoundIncrementOperator
                return(base.VisitUnaryOperator(node));
            }

            BoundExpression loweredOperand = VisitExpression(node.Operand);

            return(MakeUnaryOperator(node, node.OperatorKind, node.Syntax, node.MethodOpt, loweredOperand, node.Type));
        }
예제 #3
0
        private BoundExpression VisitUnaryOperator(BoundUnaryOperator node)
        {
            var arg        = node.Operand;
            var loweredArg = Visit(arg);
            var opKind     = node.OperatorKind;
            var op         = opKind & UnaryOperatorKind.OpMask;
            var isChecked  = (opKind & UnaryOperatorKind.Checked) != 0;

            string opname;

            switch (op)
            {
            case UnaryOperatorKind.UnaryPlus:
                if ((object)node.MethodOpt == null)
                {
                    return(loweredArg);
                }
                opname = "UnaryPlus";
                break;

            case UnaryOperatorKind.UnaryMinus:
                opname = isChecked ? "NegateChecked" : "Negate";
                break;

            case UnaryOperatorKind.BitwiseComplement:
            case UnaryOperatorKind.LogicalNegation:
                opname = "Not";
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(op);
            }

            if (node.OperatorKind.OperandTypes() == UnaryOperatorKind.Enum && (opKind & UnaryOperatorKind.Lifted) != 0)
            {
                Debug.Assert((object)node.MethodOpt == null);
                var promotedType = PromotedType(arg.Type.StrippedType().GetEnumUnderlyingType());
                promotedType = _nullableType.Construct(promotedType);
                loweredArg   = Convert(loweredArg, arg.Type, promotedType, isChecked, false);
                var result = ExprFactory(opname, loweredArg);
                return(Demote(result, node.Type, isChecked));
            }

            return(((object)node.MethodOpt == null)
                ? ExprFactory(opname, loweredArg)
                : ExprFactory(opname, loweredArg, _bound.MethodInfo(node.MethodOpt)));
        }
예제 #4
0
        public override BoundNode VisitFromEndIndexExpression(BoundFromEndIndexExpression node)
        {
            Debug.Assert(node.MethodOpt != null);

            //NamedTypeSymbol booleanType = _compilation.GetSpecialType(SpecialType.System_Boolean);
            //BoundExpression fromEnd = MakeLiteral(node.Syntax, ConstantValue.Create(true), booleanType);

            BoundExpression operand = VisitExpression(node.Operand);

            if (NullableNeverHasValue(operand))
            {
                operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
            }

            operand = NullableAlwaysHasValue(operand) ?? operand;

            if (!node.Type.IsNullableType())
            {
                var notOperand = new BoundUnaryOperator(node.Syntax, UnaryOperatorKind.IntBitwiseComplement, operand, null, null, LookupResultKind.Viable, ImmutableArray <MethodSymbol> .Empty, operand.Type);
                return(new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, binderOpt: null, notOperand));
            }

            throw new NotImplementedException("TODO: rewriter of BoundFromEndIndexExpression for ?int is not implemented");

            ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance();

            ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance();

            // operand.HasValue
            operand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals);
            BoundExpression condition = MakeOptimizedHasValue(operand.Syntax, operand);


            // new Index(operand, fromEnd: true)
            BoundExpression boundOperandGetValueOrDefault = MakeOptimizedGetValueOrDefault(operand.Syntax, operand);
            BoundExpression indexCreation = new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, binderOpt: null, boundOperandGetValueOrDefault);

            if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
            {
                return(BadExpression(node.Syntax, node.Type, operand));
            }

            // new Nullable(new Index(operand, fromEnd: true))
            BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, indexCreation);

            // default
            BoundExpression alternative = new BoundDefaultExpression(node.Syntax, constantValueOpt: null, node.Type);

            // operand.HasValue ? new Nullable(new Index(operand, fromEnd: true)) : default
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: node.Syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: node.Type,
                isRef: false);

            return(new BoundSequence(
                       syntax: node.Syntax,
                       locals: locals.ToImmutableAndFree(),
                       sideEffects: sideeffects.ToImmutableAndFree(),
                       value: conditionalExpression,
                       type: node.Type));
        }
예제 #5
0
 public override BoundNode VisitUnaryOperator(BoundUnaryOperator node)
 {
     CheckLiftedUnaryOp(node);
     return(base.VisitUnaryOperator(node));
 }