Exemplo n.º 1
0
 internal static bool CanVOCast(this TypeSymbol source)
 {
     if (source.IsIntegralType())
     {
         return(true);
     }
     if (source.IsVoidPointer())
     {
         return(true);
     }
     if (source.IsPointerType())
     {
         return(true);
     }
     if (source.SpecialType == SpecialType.System_IntPtr)
     {
         return(true);
     }
     if (source.SpecialType == SpecialType.System_UIntPtr)
     {
         return(true);
     }
     if (source.IsValueType)     // PSZ for example
     {
         return(true);
     }
     if (source.IsReferenceType)
     {
         return(false);
     }
     return(false);
 }
Exemplo n.º 2
0
 BoundExpression XsHandleExplicitConversion(TypeSymbol targetType, BoundExpression expression, DiagnosticBag diagnostics, Conversion conversion)
 {
     if (conversion.IsExplicit && expression.Type != targetType)
     {
         // silently convert integral types
         if (CheckImplicitCast(expression.Type, targetType, expression.Syntax, diagnostics) || conversion.IsNullable)
         {
             BoundExpression result;
             if (targetType.IsIntegralType() && expression.Type.IsIntegralType())
             {
                 result = CreateConversion(expression.Syntax, expression, conversion, false, targetType, diagnostics);
             }
             else
             {
                 result = XsCreateConversionNonIntegralNumeric(targetType, expression, diagnostics, conversion);
             }
             result.WasCompilerGenerated = true;
             return(result);
         }
     }
     return(null);
 }
Exemplo n.º 3
0
        private void TestBinaryIntrinsicSymbol(
            BinaryOperatorKind op,
            TypeSymbol leftType,
            TypeSymbol rightType,
            CSharpCompilation compilation,
            SemanticModel semanticModel,
            ExpressionSyntax node1,
            ExpressionSyntax node2,
            ExpressionSyntax node3,
            ExpressionSyntax node4,
            ExpressionSyntax node5,
            ExpressionSyntax node6,
            ExpressionSyntax node7,
            ExpressionSyntax node8
        )
        {
            SymbolInfo info1 = semanticModel.GetSymbolInfo(node1);
            HashSet<DiagnosticInfo> useSiteDiagnostics = null;

            if (info1.Symbol == null)
            {
                if (info1.CandidateSymbols.Length == 0)
                {
                    if (leftType.IsDynamic() || rightType.IsDynamic())
                    {
                        Assert.True(CandidateReason.LateBound == info1.CandidateReason || CandidateReason.None == info1.CandidateReason);
                    }
                    else
                    {
                        Assert.Equal(CandidateReason.None, info1.CandidateReason);
                    }
                }
                else
                {
                    Assert.Equal(CandidateReason.OverloadResolutionFailure, info1.CandidateReason);
                    foreach (MethodSymbol s in info1.CandidateSymbols)
                    {
                        Assert.Equal(MethodKind.UserDefinedOperator, s.MethodKind);
                    }
                }
            }
            else
            {
                Assert.Equal(leftType.IsDynamic() || rightType.IsDynamic() ? CandidateReason.LateBound : CandidateReason.None, info1.CandidateReason);
                Assert.Equal(0, info1.CandidateSymbols.Length);
            }

            var symbol1 = (MethodSymbol)info1.Symbol;
            var symbol2 = semanticModel.GetSymbolInfo(node2).Symbol;
            var symbol3 = semanticModel.GetSymbolInfo(node3).Symbol;
            var symbol4 = semanticModel.GetSymbolInfo(node4).Symbol;
            var symbol5 = (MethodSymbol)semanticModel.GetSymbolInfo(node5).Symbol;
            var symbol6 = semanticModel.GetSymbolInfo(node6).Symbol;
            var symbol7 = semanticModel.GetSymbolInfo(node7).Symbol;
            var symbol8 = semanticModel.GetSymbolInfo(node8).Symbol;

            Assert.Equal(symbol1, symbol5);
            Assert.Equal(symbol2, symbol6);
            Assert.Equal(symbol3, symbol7);
            Assert.Equal(symbol4, symbol8);

            if ((object)symbol1 != null && symbol1.IsImplicitlyDeclared)
            {
                Assert.NotSame(symbol1, symbol5);
                Assert.Equal(symbol1.GetHashCode(), symbol5.GetHashCode());

                for (int i = 0; i < 2; i++)
                {
                    Assert.Equal(symbol1.Parameters[i], symbol5.Parameters[i]);
                    Assert.Equal(symbol1.Parameters[i].GetHashCode(), symbol5.Parameters[i].GetHashCode());
                }

                Assert.NotEqual(symbol1.Parameters[0], symbol5.Parameters[1]);
            }

            switch (op)
            {
                case BinaryOperatorKind.LogicalAnd:
                case BinaryOperatorKind.LogicalOr:
                    Assert.Null(symbol1);
                    Assert.Null(symbol2);
                    Assert.Null(symbol3);
                    Assert.Null(symbol4);
                    return;
            }


            BinaryOperatorKind result = OverloadResolution.BinopEasyOut.OpKind(op, leftType, rightType);
            BinaryOperatorSignature signature;
            bool isDynamic = (leftType.IsDynamic() || rightType.IsDynamic());

            if (result == BinaryOperatorKind.Error)
            {
                if (leftType.IsDynamic() && !rightType.IsPointerType() && !rightType.IsRestrictedType())
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Dynamic, leftType, rightType, leftType);
                }
                else if (rightType.IsDynamic() && !leftType.IsPointerType() && !leftType.IsRestrictedType())
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Dynamic, leftType, rightType, rightType);
                }
                else if ((op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual) &&
                    leftType.IsReferenceType && rightType.IsReferenceType &&
                    (leftType == rightType || compilation.Conversions.ClassifyConversion(leftType, rightType, ref useSiteDiagnostics).IsReference))
                {
                    if (leftType.IsDelegateType() && rightType.IsDelegateType())
                    {
                        Assert.Equal(leftType, rightType);
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Delegate,
                            leftType, // TODO: this feels like a spec violation
                            leftType, // TODO: this feels like a spec violation
                            compilation.GetSpecialType(SpecialType.System_Boolean));
                    }
                    else if (leftType.SpecialType == SpecialType.System_Delegate && rightType.SpecialType == SpecialType.System_Delegate)
                    {
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Delegate,
                            compilation.GetSpecialType(SpecialType.System_Delegate), compilation.GetSpecialType(SpecialType.System_Delegate),
                            compilation.GetSpecialType(SpecialType.System_Boolean));
                    }
                    else
                    {
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Object, compilation.ObjectType, compilation.ObjectType,
                            compilation.GetSpecialType(SpecialType.System_Boolean));
                    }
                }
                else if (op == BinaryOperatorKind.Addition &&
                    ((leftType.IsStringType() && !rightType.IsPointerType()) || (!leftType.IsPointerType() && rightType.IsStringType())))
                {
                    Assert.False(leftType.IsStringType() && rightType.IsStringType());

                    if (leftType.IsStringType())
                    {
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.String, leftType, compilation.ObjectType, leftType);
                    }
                    else
                    {
                        Assert.True(rightType.IsStringType());
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.String, compilation.ObjectType, rightType, rightType);
                    }
                }
                else if (op == BinaryOperatorKind.Addition &&
                    (((leftType.IsIntegralType() || leftType.IsCharType()) && rightType.IsPointerType()) ||
                    (leftType.IsPointerType() && (rightType.IsIntegralType() || rightType.IsCharType()))))
                {
                    if (leftType.IsPointerType())
                    {
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, leftType, symbol1.Parameters[1].Type, leftType);
                        Assert.True(symbol1.Parameters[1].Type.IsIntegralType());
                    }
                    else
                    {
                        signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, symbol1.Parameters[0].Type, rightType, rightType);
                        Assert.True(symbol1.Parameters[0].Type.IsIntegralType());
                    }
                }
                else if (op == BinaryOperatorKind.Subtraction &&
                    (leftType.IsPointerType() && (rightType.IsIntegralType() || rightType.IsCharType())))
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.String, leftType, symbol1.Parameters[1].Type, leftType);
                    Assert.True(symbol1.Parameters[1].Type.IsIntegralType());
                }
                else if (op == BinaryOperatorKind.Subtraction && leftType.IsPointerType() && leftType == rightType)
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, leftType, rightType, compilation.GetSpecialType(SpecialType.System_Int64));
                }
                else if ((op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) &&
                    leftType.IsEnumType() && (rightType.IsIntegralType() || rightType.IsCharType()) &&
                    (result = OverloadResolution.BinopEasyOut.OpKind(op, leftType.EnumUnderlyingType(), rightType)) != BinaryOperatorKind.Error &&
                    (signature = compilation.builtInOperators.GetSignature(result)).RightType == leftType.EnumUnderlyingType())
                {
                    signature = new BinaryOperatorSignature(signature.Kind | BinaryOperatorKind.EnumAndUnderlying, leftType, signature.RightType, leftType);
                }
                else if ((op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) &&
                    rightType.IsEnumType() && (leftType.IsIntegralType() || leftType.IsCharType()) &&
                    (result = OverloadResolution.BinopEasyOut.OpKind(op, leftType, rightType.EnumUnderlyingType())) != BinaryOperatorKind.Error &&
                    (signature = compilation.builtInOperators.GetSignature(result)).LeftType == rightType.EnumUnderlyingType())
                {
                    signature = new BinaryOperatorSignature(signature.Kind | BinaryOperatorKind.EnumAndUnderlying, signature.LeftType, rightType, rightType);
                }
                else if (op == BinaryOperatorKind.Subtraction &&
                    leftType.IsEnumType() && leftType == rightType)
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Enum, leftType, rightType, leftType.EnumUnderlyingType());
                }
                else if ((op == BinaryOperatorKind.Equal ||
                          op == BinaryOperatorKind.NotEqual ||
                          op == BinaryOperatorKind.LessThan ||
                          op == BinaryOperatorKind.LessThanOrEqual ||
                          op == BinaryOperatorKind.GreaterThan ||
                          op == BinaryOperatorKind.GreaterThanOrEqual) &&
                    leftType.IsEnumType() && leftType == rightType)
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Enum, leftType, rightType, compilation.GetSpecialType(SpecialType.System_Boolean));
                }
                else if ((op == BinaryOperatorKind.Xor ||
                          op == BinaryOperatorKind.And ||
                          op == BinaryOperatorKind.Or) &&
                    leftType.IsEnumType() && leftType == rightType)
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Enum, leftType, rightType, leftType);
                }
                else if ((op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) &&
                    leftType.IsDelegateType() && leftType == rightType)
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Delegate, leftType, leftType, leftType);
                }
                else if ((op == BinaryOperatorKind.Equal ||
                          op == BinaryOperatorKind.NotEqual ||
                          op == BinaryOperatorKind.LessThan ||
                          op == BinaryOperatorKind.LessThanOrEqual ||
                          op == BinaryOperatorKind.GreaterThan ||
                          op == BinaryOperatorKind.GreaterThanOrEqual) &&
                    leftType.IsPointerType() && rightType.IsPointerType())
                {
                    signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer,
                        compilation.CreatePointerTypeSymbol(compilation.GetSpecialType(SpecialType.System_Void)),
                        compilation.CreatePointerTypeSymbol(compilation.GetSpecialType(SpecialType.System_Void)),
                        compilation.GetSpecialType(SpecialType.System_Boolean));
                }
                else
                {
                    if ((object)symbol1 != null)
                    {
                        Assert.False(symbol1.IsImplicitlyDeclared);
                        Assert.Equal(MethodKind.UserDefinedOperator, symbol1.MethodKind);

                        if (leftType.IsValueType && !leftType.IsPointerType())
                        {
                            if (rightType.IsValueType && !rightType.IsPointerType())
                            {
                                Assert.Same(symbol1, symbol2);
                                Assert.Same(symbol1, symbol3);
                                Assert.Same(symbol1, symbol4);
                                return;
                            }
                            else
                            {
                                Assert.Null(symbol2);
                                Assert.Same(symbol1, symbol3);
                                Assert.Null(symbol4);
                                return;
                            }
                        }
                        else if (rightType.IsValueType && !rightType.IsPointerType())
                        {
                            Assert.Null(symbol2);
                            Assert.Null(symbol3);
                            Assert.Same(symbol1, symbol4);
                            return;
                        }
                        else
                        {
                            Assert.Null(symbol2);
                            Assert.Null(symbol3);
                            Assert.Null(symbol4);
                            return;
                        }
                    }

                    Assert.Null(symbol1);
                    Assert.Null(symbol2);

                    if (!rightType.IsDynamic())
                    {
                        Assert.Null(symbol3);
                    }

                    if (!leftType.IsDynamic())
                    {
                        Assert.Null(symbol4);
                    }
                    return;
                }
            }
            else if ((op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual) &&
                leftType != rightType &&
                (!leftType.IsValueType || !rightType.IsValueType ||
                 leftType.SpecialType == SpecialType.System_Boolean || rightType.SpecialType == SpecialType.System_Boolean ||
                 (leftType.SpecialType == SpecialType.System_Decimal && (rightType.SpecialType == SpecialType.System_Double || rightType.SpecialType == SpecialType.System_Single)) ||
                 (rightType.SpecialType == SpecialType.System_Decimal && (leftType.SpecialType == SpecialType.System_Double || leftType.SpecialType == SpecialType.System_Single))) &&
                (!leftType.IsReferenceType || !rightType.IsReferenceType ||
                 !compilation.Conversions.ClassifyConversion(leftType, rightType, ref useSiteDiagnostics).IsReference))
            {
                Assert.Null(symbol1);
                Assert.Null(symbol2);
                Assert.Null(symbol3);
                Assert.Null(symbol4);
                return;
            }
            else
            {
                signature = compilation.builtInOperators.GetSignature(result);
            }

            Assert.NotNull(symbol1);

            string containerName = signature.LeftType.ToTestDisplayString();
            string leftName = containerName;
            string rightName = signature.RightType.ToTestDisplayString();
            string returnName = signature.ReturnType.ToTestDisplayString();

            if (isDynamic)
            {
                containerName = compilation.DynamicType.ToTestDisplayString();
            }
            else if (op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction)
            {
                if (signature.LeftType.IsObjectType() && signature.RightType.IsStringType())
                {
                    containerName = rightName;
                }
                else if ((leftType.IsEnumType() || leftType.IsPointerType()) && (rightType.IsIntegralType() || rightType.IsCharType()))
                {
                    containerName = leftType.ToTestDisplayString();
                    leftName = containerName;
                    returnName = containerName;
                }
                else if ((rightType.IsEnumType() || rightType.IsPointerType()) && (leftType.IsIntegralType() || leftType.IsCharType()))
                {
                    containerName = rightType.ToTestDisplayString();
                    rightName = containerName;
                    returnName = containerName;
                }
            }

            Assert.Equal(isDynamic, signature.ReturnType.IsDynamic());

            string expectedSymbol = String.Format("{4} {0}.{2}({1} left, {3} right)",
                                       containerName,
                                       leftName,
                                       OperatorFacts.BinaryOperatorNameFromOperatorKind(op),
                                       rightName,
                                       returnName);
            string actualSymbol = symbol1.ToTestDisplayString();

            Assert.Equal(expectedSymbol, actualSymbol);

            Assert.Equal(MethodKind.BuiltinOperator, symbol1.MethodKind);
            Assert.True(symbol1.IsImplicitlyDeclared);

            bool isChecked;

            switch (op)
            {
                case BinaryOperatorKind.Multiplication:
                case BinaryOperatorKind.Addition:
                case BinaryOperatorKind.Subtraction:
                case BinaryOperatorKind.Division:
                    isChecked = isDynamic || symbol1.ContainingSymbol.Kind == SymbolKind.PointerType || symbol1.ContainingType.EnumUnderlyingType().SpecialType.IsIntegralType();
                    break;

                default:
                    isChecked = isDynamic;
                    break;
            }

            Assert.Equal(isChecked, symbol1.IsCheckedBuiltin);

            Assert.False(symbol1.IsGenericMethod);
            Assert.False(symbol1.IsExtensionMethod);
            Assert.False(symbol1.IsExtern);
            Assert.False(symbol1.CanBeReferencedByName);
            Assert.Null(symbol1.DeclaringCompilation);
            Assert.Equal(symbol1.Name, symbol1.MetadataName);

            Assert.True(symbol1.ContainingSymbol == symbol1.Parameters[0].Type || symbol1.ContainingSymbol == symbol1.Parameters[1].Type);

            int match = 0;
            if (symbol1.ContainingSymbol == symbol1.ReturnType)
            {
                match++;
            }

            if (symbol1.ContainingSymbol == symbol1.Parameters[0].Type)
            {
                match++;
            }

            if (symbol1.ContainingSymbol == symbol1.Parameters[1].Type)
            {
                match++;
            }

            Assert.True(match >= 2);

            Assert.Equal(0, symbol1.Locations.Length);
            Assert.Null(symbol1.GetDocumentationCommentId());
            Assert.Equal("", symbol1.GetDocumentationCommentXml());

            Assert.True(symbol1.HasSpecialName);
            Assert.True(symbol1.IsStatic);
            Assert.Equal(Accessibility.Public, symbol1.DeclaredAccessibility);
            Assert.False(symbol1.HidesBaseMethodsByName);
            Assert.False(symbol1.IsOverride);
            Assert.False(symbol1.IsVirtual);
            Assert.False(symbol1.IsAbstract);
            Assert.False(symbol1.IsSealed);
            Assert.Equal(2, symbol1.ParameterCount);
            Assert.Equal(0, symbol1.Parameters[0].Ordinal);
            Assert.Equal(1, symbol1.Parameters[1].Ordinal);

            var otherSymbol = (MethodSymbol)semanticModel.GetSymbolInfo(node1).Symbol;
            Assert.Equal(symbol1, otherSymbol);

            if (leftType.IsValueType && !leftType.IsPointerType())
            {
                if (rightType.IsValueType && !rightType.IsPointerType())
                {
                    Assert.Equal(symbol1, symbol2);
                    Assert.Equal(symbol1, symbol3);
                    Assert.Equal(symbol1, symbol4);
                    return;
                }
                else
                {
                    Assert.Null(symbol2);

                    if (rightType.IsDynamic())
                    {
                        Assert.NotEqual(symbol1, symbol3);
                    }
                    else
                    {
                        Assert.Equal(rightType.IsPointerType() ? null : symbol1, symbol3);
                    }

                    Assert.Null(symbol4);
                    return;
                }
            }
            else if (rightType.IsValueType && !rightType.IsPointerType())
            {
                Assert.Null(symbol2);
                Assert.Null(symbol3);

                if (leftType.IsDynamic())
                {
                    Assert.NotEqual(symbol1, symbol4);
                }
                else
                {
                    Assert.Equal(leftType.IsPointerType() ? null : symbol1, symbol4);
                }

                return;
            }

            Assert.Null(symbol2);

            if (rightType.IsDynamic())
            {
                Assert.NotEqual(symbol1, symbol3);
            }
            else
            {
                Assert.Null(symbol3);
            }

            if (leftType.IsDynamic())
            {
                Assert.NotEqual(symbol1, symbol4);
            }
            else
            {
                Assert.Null(symbol4);
            }
        }
Exemplo n.º 4
0
        protected override Conversion ClassifyVOImplicitBuiltInConversionFromExpression(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            // Parameters checks have been done in the calling code
            var  srcType   = source.SpecialType;
            var  dstType   = destination.SpecialType;
            bool voCast    = false;
            bool voConvert = false;
            bool typeCast  = false;
            bool vo7       = Compilation.Options.HasOption(CompilerOption.ImplicitCastsAndConversions, sourceExpression.Syntax);

            if (sourceExpression.Syntax != null)
            {
                var xNode = sourceExpression.Syntax.XNode;
                while (xNode != null)
                {
                    voCast = xNode is XP.VoCastExpressionContext;
                    if (voCast)
                    {
                        break;
                    }
                    voConvert = xNode is XP.VoConversionExpressionContext;
                    if (voConvert)
                    {
                        break;
                    }
                    typeCast = xNode is XP.TypeCastContext;
                    if (typeCast)
                    {
                        break;
                    }
                    xNode = xNode.Parent as IXParseTree;
                    if (xNode is XP.StatementContext)
                    {
                        break;
                    }
                }
            }
            if (vo7 && (typeCast || voCast || voConvert))
            {
                // Allow cast -> BOOLEAN
                if (dstType == SpecialType.System_Boolean && srcType.IsIntegralType())
                {
                    if (sourceExpression is BoundExpression be && be.Type.SpecialType == SpecialType.System_Boolean)
                    {
                        return(Conversion.Identity);
                    }
                }
            }
            // TYPE(_CAST, expr) allows almost everything
            // source must be PTR, Integral, IntPtr, UIntPtr
            // this is handled in CanVOCast
            if (voCast && source.CanVOCast() && destination.CanVOCast())
            {
                // No _CAST on USUAL
                if (source == Compilation.UsualType())
                {
                    return(Conversion.NoConversion);
                }
                // Allow LOGIC(_CAST
                if (dstType == SpecialType.System_Boolean)
                {
                    return(Conversion.Identity);
                }
                // Allow cast -> INTEGRAL
                // except from NullableTypes and Reference Types
                if (dstType.IsIntegralType() && !source.IsNullableType() && !source.IsReferenceType)
                {
                    if (srcType.IsNumericType())
                    {
                        // always implicit numeric conversion
                        return(Conversion.ImplicitNumeric);
                    }
                    if (source.SpecialType == SpecialType.System_Boolean)
                    {
                        return(Conversion.Identity);
                    }

                    // Allow PTR -> Integral when size matches
                    if (source.IsVoidPointer())
                    {
                        if (dstType.SizeInBytes() == 4 && Compilation.Options.Platform == Platform.X86)
                        {
                            return(Conversion.Identity);
                        }
                        if (dstType.SizeInBytes() == 8 && Compilation.Options.Platform == Platform.X64)
                        {
                            return(Conversion.Identity);
                        }
                    }
                }


                // Allow cast -> PTR when
                // source is integral and source size matches the Integral size
                // source is Ptr, IntPtr, UintPtr
                // source is PSZ
                if (destination is PointerTypeSymbol)
                {
                    if (source.IsIntegralType())
                    {
                        if (Compilation.Options.Platform == Platform.X86 && srcType.SizeInBytes() == 4)
                        {
                            return(Conversion.Identity);
                        }
                        if (Compilation.Options.Platform == Platform.X64 && srcType.SizeInBytes() == 8)
                        {
                            return(Conversion.Identity);
                        }
                        return(Conversion.IntegerToPointer);
                    }
                    if (source.IsPointerType() || source.IsVoidPointer() ||
                        source.SpecialType == SpecialType.System_IntPtr || source.SpecialType == SpecialType.System_UIntPtr)
                    {
                        return(Conversion.Identity);
                    }
                    if (source == Compilation.PszType())
                    {
                        return(Conversion.Identity);
                    }
                }
                // Allow cast -> PSZ
                if (destination == Compilation.PszType())
                {
                    return(Conversion.Identity);
                }
            }
            if (voConvert)
            {
                // we need to convert BYTE(<p>) to dereferencing the <p>
                // This is done else where in Binder.BindVulcanPointerDereference()
                // Integer conversions
                if (srcType.IsNumericType() && dstType.IsNumericType() &&
                    srcType.IsIntegralType() == dstType.IsIntegralType())
                {
                    // always implicit numeric conversion
                    return(Conversion.ImplicitNumeric);
                }
            }
            if (source == Compilation.UsualType())
            {
                // Usual -> Decimal. Get the object out of the Usual and let the rest be done by Roslyn
                if (destination == Compilation.UsualType())
                {
                    return(Conversion.NoConversion);
                }
                if (dstType == SpecialType.System_Decimal)
                {
                    return(Conversion.Boxing);
                }
                // Usual -> OBJECT. Get the object out of the Usual
                // Our special call will call in LocalWriter.UnBoxVOType will
                // convert the Unbox operation to a call to __Usual.ToObject()
                // This method will return the Contents of the usual as an object
                // and not the usual itself as an object
                else if (dstType == SpecialType.System_Object)
                {
                    // All Objects are boxed in a usual
                    return(Conversion.Boxing);
                }
                else if (destination.IsReferenceType && !IsClipperArgsType(destination) && !destination.IsStringType() && !destination.IsIFormatProvider())
                {
                    // all user reference types are boxed. But not the Usual[] args and not string
                    return(Conversion.Boxing);
                }
                else if (destination.IsPointerType())
                {
                    // Not really boxed, but we handle this in LocalRewriter.UnBoxXSharpType
                    return(Conversion.Boxing);
                }
            }

            if (Compilation.Options.LateBindingOrFox(sourceExpression.Syntax) || vo7)                // lb or vo7
            {
                if (srcType == SpecialType.System_Object)
                {
                    if (destination.IsReferenceType && !IsClipperArgsType(destination))
                    {
                        // Convert Object -> Reference allowed with /lb and with /vo7
                        // except when converting to array of usuals
                        return(Conversion.ImplicitReference);
                    }
                    if (destination.IsPointerType() || destination.SpecialType == SpecialType.System_IntPtr)
                    {
                        return(Conversion.Identity);
                    }
                }
                if (dstType == SpecialType.System_Object)
                {
                    if (source.IsReferenceType)
                    {
                        return(Conversion.ImplicitReference);
                    }
                    if (source.IsPointerType() || source.SpecialType == SpecialType.System_IntPtr)
                    {
                        return(Conversion.Identity);
                    }
                }
            }
            if (vo7)
            {
                // Convert Any Ptr -> Any Ptr
                if (source.IsPointerType() && destination.IsPointerType())
                {
                    return(Conversion.Identity);
                }
            }
            // Convert Integral type -> Ptr Type
            if (source.IsIntegralType() && destination.IsPointerType())
            {
                if (Compilation.Options.Platform == Platform.X86 && srcType.SizeInBytes() <= 4)
                {
                    return(Conversion.Identity);
                }
                if (Compilation.Options.Platform == Platform.X64 && srcType.SizeInBytes() <= 8)
                {
                    return(Conversion.Identity);
                }
                return(Conversion.IntegerToPointer);
            }
            // When unsafe we always allow to cast void * to typed *
            // Is this OK ?
            // See ticket C425
            if (source.IsVoidPointer() && destination.IsPointerType() && Compilation.Options.AllowUnsafe)
            {
                return(Conversion.Identity);
            }
            if (srcType.IsIntegralType() && dstType.IsIntegralType())
            {
                if (srcType.SizeInBytes() < dstType.SizeInBytes() ||
                    sourceExpression is BoundConditionalOperator)
                // IIF expressions with literals are always seen as Int, even when the values are asmall
                {
                    return(Conversion.ImplicitNumeric);
                }
            }
            if (destination == Compilation.PszType() ||
                destination.IsVoidPointer())
            {
                if (source.SpecialType == SpecialType.System_String)
                {
                    return(Conversion.ImplicitReference);
                }
            }
            // when nothing else, then use the Core rules
            return(ClassifyCoreImplicitConversionFromExpression(sourceExpression, source, destination, ref useSiteDiagnostics));
        }
Exemplo n.º 5
0
        protected override Conversion ClassifyCoreImplicitConversionFromExpression(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            // Parameters checks have been done in the calling code
            // The following conversion Rules are for all dialects
            var srcType = source.SpecialType;
            var dstType = destination.SpecialType;

            // From and to CHAR
            if (srcType == SpecialType.System_Char)
            {
                if (dstType == SpecialType.System_UInt16)
                {
                    return(Conversion.Identity);
                }
                if (Compilation.Options.HasOption(CompilerOption.SignedUnsignedConversion, sourceExpression.Syntax)) // vo4
                {
                    if (dstType == SpecialType.System_Byte)
                    {
                        return(Conversion.ImplicitNumeric);
                    }
                }
            }

            if (dstType == SpecialType.System_Char)
            {
                if (srcType == SpecialType.System_UInt16)
                {
                    return(Conversion.Identity);
                }
                if (srcType == SpecialType.System_Byte)
                {
                    return(Conversion.ImplicitNumeric);
                }
            }
            // From IntPtr -> Anything
            if (srcType == SpecialType.System_IntPtr || srcType == SpecialType.System_UIntPtr)
            {
                if (destination.IsPointerType())
                {
                    return(Conversion.IntPtr);
                }
                if (destination.IsVoStructOrUnion() || destination.IsIntegralType())
                {
                    return(Conversion.Identity);
                }
            }
            // From Anything -> IntPtr
            if (dstType == SpecialType.System_IntPtr || dstType == SpecialType.System_UIntPtr)
            {
                if (source.IsVoStructOrUnion() || source.IsIntegralType())
                {
                    return(Conversion.Identity);
                }
                else if (source.IsPointerType())
                {
                    return(Conversion.Identity);
                }
            }
            if (Compilation.Options.HasOption(CompilerOption.SignedUnsignedConversion, sourceExpression.Syntax)) // vo4
            {
                // This compiler option only applies to numeric types
                if (srcType.IsNumericType() && dstType.IsNumericType())
                {
                    if (srcType.IsIntegralType() && dstType.IsIntegralType())
                    {
                        // when both same # of bits and integral, use Identity conversion
                        if (srcType.SizeInBytes() == dstType.SizeInBytes())
                        {
                            return(Conversion.Identity);
                        }
                        else
                        {
                            // otherwise implicit conversion
                            return(Conversion.ImplicitNumeric);
                        }
                    }
                    // Vulcan also allows to convert floating point types <-> integral types
                    else if (srcType.IsIntegralType() || dstType.IsIntegralType())
                    {
                        return(Conversion.ImplicitNumeric);
                    }
                }
            }

            return(Conversion.NoConversion);
        }