Example #1
0
        public override BoundNode VisitIsOperator(BoundIsOperator node)
        {
            BoundSpillSequenceBuilder builder = null;
            var operand = VisitExpression(ref builder, node.Operand);

            return(UpdateExpression(builder, node.Update(operand, node.TargetType, node.Conversion, node.Type)));
        }
Example #2
0
        private BoundExpression MakeIsOperator(
            BoundIsOperator oldNode,
            SyntaxNode syntax,
            BoundExpression rewrittenOperand,
            BoundTypeExpression rewrittenTargetType,
            Conversion conversion,
            TypeSymbol rewrittenType
            )
        {
            if (rewrittenOperand.Kind == BoundKind.MethodGroup)
            {
                var             methodGroup = (BoundMethodGroup)rewrittenOperand;
                BoundExpression?receiver    = methodGroup.ReceiverOpt;
                if (receiver != null && receiver.Kind != BoundKind.ThisReference)
                {
                    // possible side-effect
                    return(RewriteConstantIsOperator(
                               receiver.Syntax,
                               receiver,
                               ConstantValue.False,
                               rewrittenType
                               ));
                }
                else
                {
                    return(MakeLiteral(syntax, ConstantValue.False, rewrittenType));
                }
            }

            var operandType = rewrittenOperand.Type;
            var targetType  = rewrittenTargetType.Type;

            Debug.Assert(operandType is { } || rewrittenOperand.ConstantValue !.IsNull);
Example #3
0
 internal void Parse(BoundIsOperator boundIsOperator)
 {
     base.Parse(boundIsOperator);
     this.ConversionKind = boundIsOperator.Conversion.Kind;
     this.TargetType     = Deserialize(boundIsOperator.TargetType) as TypeExpression;
     this.Operand        = Deserialize(boundIsOperator.Operand) as Expression;
 }
        public override BoundNode VisitIsOperator(BoundIsOperator node)
        {
            BoundExpression rewrittenOperand    = VisitExpression(node.Operand);
            var             rewrittenTargetType = (BoundTypeExpression)VisitTypeExpression(node.TargetType);
            TypeSymbol      rewrittenType       = VisitType(node.Type);

            return(MakeIsOperator(node, node.Syntax, rewrittenOperand, rewrittenTargetType, node.Conversion, rewrittenType));
        }
        private BoundExpression VisitIsOperator(BoundIsOperator node)
        {
            var operand = node.Operand;

            if ((object)operand.Type == null && operand.ConstantValue != null && operand.ConstantValue.IsNull)
            {
                operand = _bound.Null(_objectType);
            }

            return(ExprFactory("TypeIs", Visit(operand), _bound.Typeof(node.TargetType.Type)));
        }
        private BoundExpression MakeIsOperator(
            BoundIsOperator oldNode,
            SyntaxNode syntax,
            BoundExpression rewrittenOperand,
            BoundTypeExpression rewrittenTargetType,
            Conversion conversion,
            TypeSymbol rewrittenType)
        {
            if (rewrittenOperand.Kind == BoundKind.MethodGroup)
            {
                var             methodGroup = (BoundMethodGroup)rewrittenOperand;
                BoundExpression receiver    = methodGroup.ReceiverOpt;
                if (receiver != null && receiver.Kind != BoundKind.ThisReference)
                {
                    // possible side-effect
                    return(RewriteConstantIsOperator(receiver.Syntax, receiver, ConstantValue.False, rewrittenType));
                }
                else
                {
                    return(MakeLiteral(syntax, ConstantValue.False, rewrittenType));
                }
            }

            var operandType = rewrittenOperand.Type;
            var targetType  = rewrittenTargetType.Type;

            Debug.Assert((object)operandType != null || rewrittenOperand.ConstantValue.IsNull);
            Debug.Assert((object)targetType != null);

            // TODO: Handle dynamic operand type and target type

            if (!_inExpressionLambda)
            {
                ConstantValue constantValue = Binder.GetIsOperatorConstantResult(operandType, targetType, conversion.Kind, rewrittenOperand.ConstantValue);

                if (constantValue != null)
                {
                    return(RewriteConstantIsOperator(syntax, rewrittenOperand, constantValue, rewrittenType));
                }
                else if (conversion.IsImplicit)
                {
                    // operand is a reference type with bound identity or implicit conversion
                    // We can replace the "is" instruction with a null check
                    return(MakeNullCheck(syntax, rewrittenOperand, BinaryOperatorKind.NotEqual));
                }
            }

            return(oldNode.Update(rewrittenOperand, rewrittenTargetType, conversion, rewrittenType));
        }
        public override BoundNode VisitIsOperator(BoundIsOperator node)
        {
            BoundExpression     operand    = (BoundExpression)this.Visit(node.Operand);
            BoundTypeExpression targetType = (BoundTypeExpression)this.Visit(node.TargetType);
            TypeSymbol          type       = this.VisitType(node.Type);

            if (operand.Kind != BoundKind.SpillSequence)
            {
                return(node.Update(operand, targetType, node.Conversion, type));
            }

            var spill         = (BoundSpillSequence)operand;
            var newIsOperator = node.Update(spill.Value, targetType, node.Conversion, type);

            return(RewriteSpillSequence(spill, newIsOperator));
        }
Example #8
0
        public override BoundNode VisitIsOperator(BoundIsOperator node)
        {
            // rewrite is needed only for cases where there are no errors and
            // no warnings (i.e. non-constant result) generated during binding
            if (!node.HasErrors && node.ConstantValue == null)
            {
                BoundExpression operand     = node.Operand;
                var             targetType  = node.TargetType.Type;
                var             operandType = operand.Type;

                Debug.Assert(operandType != null);
                if (operandType.IsNullableType())
                {
                    //TODO: handle nullable types once nullable conversions are implemented
                }
                else if (!operandType.IsValueType)
                {
                    if (operandType.IsSameType(targetType))
                    {
                        // operand with bound identity or implicit conversion
                        // We can replace the "is" instruction with a null check
                        Visit(operand);
                        if (operandType.TypeKind == TypeKind.TypeParameter)
                        {
                            // We need to box the type parameter even if it is a known
                            // reference type to ensure there are no verifier errors
                            operand = new BoundConversion(operand.Syntax, operand.SyntaxTree, operand,
                                                          ConversionKind.Boxing, this.containingSymbol, false, false, null,
                                                          compilation.GetSpecialType(SpecialType.System_Object));
                        }
                        return(new BoundBinaryOperator(node.Syntax, node.SyntaxTree, BinaryOperatorKind.NotEqual,
                                                       operand, new BoundLiteral(null, null, ConstantValue.Null, null), null, node.Type));
                    }
                }
            }
            return(base.VisitIsOperator(node));
        }
        public override BoundNode VisitIsOperator(BoundIsOperator node)
        {
            // rewrite is needed only for cases where there are no errors and 
            // no warnings (i.e. non-constant result) generated during binding
            if (!node.HasErrors && node.ConstantValue == null)
            {
                BoundExpression operand = node.Operand;
                var targetType = node.TargetType.Type;
                var operandType = operand.Type;

                Debug.Assert(operandType != null);
                if (operandType.IsNullableType())
                {
                    //TODO: handle nullable types once nullable conversions are implemented
                }
                else if (!operandType.IsValueType)
                {
                    if (operandType.IsSameType(targetType))
                    {
                        // operand with bound identity or implicit conversion
                        // We can replace the "is" instruction with a null check
                        Visit(operand);
                        if(operandType.TypeKind == TypeKind.TypeParameter)
                        {
                            // We need to box the type parameter even if it is a known
                            // reference type to ensure there are no verifier errors
                            operand = new BoundConversion(operand.Syntax, operand.SyntaxTree, operand, 
                                ConversionKind.Boxing, this.containingSymbol, false, false, null, 
                                compilation.GetSpecialType(SpecialType.System_Object));
                        }
                        return new BoundBinaryOperator(node.Syntax, node.SyntaxTree, BinaryOperatorKind.NotEqual,
                            operand, new BoundLiteral(null, null, ConstantValue.Null, null), null, node.Type);
                    }
                }
            }
            return base.VisitIsOperator(node);
        }
Example #10
0
 private void EmitIsExpression(BoundIsOperator isOp, bool used)
 {
     var operand = isOp.Operand;
     EmitExpression(operand, used);
     if (used)
     {
         Debug.Assert((object)operand.Type != null);
         if (!operand.Type.IsVerifierReference())
         {
             // box the operand for isinst if it is not a verifier reference
             EmitBox(operand.Type, operand.Syntax);
         }
         _builder.EmitOpCode(ILOpCode.Isinst);
         EmitSymbolToken(isOp.TargetType.Type, isOp.Syntax);
         _builder.EmitOpCode(ILOpCode.Ldnull);
         _builder.EmitOpCode(ILOpCode.Cgt_un);
     }
 }
Example #11
0
        private BoundExpression MakeIsOperator(
            BoundIsOperator oldNode,
            SyntaxNode syntax,
            BoundExpression rewrittenOperand,
            BoundTypeExpression rewrittenTargetType,
            Conversion conversion,
            TypeSymbol rewrittenType)
        {
            if (rewrittenOperand.Kind == BoundKind.MethodGroup)
            {
                var             methodGroup = (BoundMethodGroup)rewrittenOperand;
                BoundExpression receiver    = methodGroup.ReceiverOpt;
                if (receiver != null && receiver.Kind != BoundKind.ThisReference)
                {
                    // possible side-effect
                    return(RewriteConstantIsOperator(receiver.Syntax, receiver, ConstantValue.False, rewrittenType));
                }
                else
                {
                    return(MakeLiteral(syntax, ConstantValue.False, rewrittenType));
                }
            }

            var operandType = rewrittenOperand.Type;
            var targetType  = rewrittenTargetType.Type;

            Debug.Assert((object)operandType != null || rewrittenOperand.ConstantValue.IsNull);
            Debug.Assert((object)targetType != null);

            // TODO: Handle dynamic operand type and target type

            if (!_inExpressionLambda)
            {
                ConstantValue constantValue = Binder.GetIsOperatorConstantResult(operandType, targetType, conversion.Kind, rewrittenOperand.ConstantValue);

                if (constantValue != null)
                {
                    return(RewriteConstantIsOperator(syntax, rewrittenOperand, constantValue, rewrittenType));
                }
                else if (conversion.IsImplicit)
                {
                    // operand is a reference type with bound identity or implicit conversion
                    // We can replace the "is" instruction with a null check

                    Debug.Assert((object)operandType != null);
                    if (operandType.TypeKind == TypeKind.TypeParameter)
                    {
                        // We need to box the type parameter even if it is a known
                        // reference type to ensure there are no verifier errors
                        rewrittenOperand = MakeConversionNode(
                            syntax: rewrittenOperand.Syntax,
                            rewrittenOperand: rewrittenOperand,
                            conversion: Conversion.Boxing,
                            rewrittenType: _compilation.GetSpecialType(SpecialType.System_Object),
                            @checked: false);
                    }

                    return(MakeNullCheck(syntax, rewrittenOperand, BinaryOperatorKind.NotEqual));
                }
            }

            return(oldNode.Update(rewrittenOperand, rewrittenTargetType, conversion, rewrittenType));
        }
Example #12
0
 public override object VisitIsOperator(BoundIsOperator node, object arg)
 {
     VisitExpression(node.Operand);
     return(null);
 }