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); } }
/// <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)); }
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))); }
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)); }
public override BoundNode VisitUnaryOperator(BoundUnaryOperator node) { CheckLiftedUnaryOp(node); return(base.VisitUnaryOperator(node)); }