Example #1
0
        public CSharpTypePrinterResult VisitArrayType(ArrayType array,
                                                      TypeQualifiers quals)
        {
            if (ContextKind == CSharpTypePrinterContextKind.Native &&
                array.SizeType == ArrayType.ArraySize.Constant)
            {
                Type arrayType = array.Type.Desugar();

                PrimitiveType primitiveType;
                if ((arrayType.IsPointerToPrimitiveType(out primitiveType) &&
                     !(arrayType is FunctionType)) ||
                    (arrayType.IsPrimitiveType() && MarshalKind != CSharpMarshalKind.NativeField))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void*");
                    }
                    return(string.Format("{0}", array.Type.Visit(this, quals)));
                }

                if (TypePrinterContext.Parameter != null)
                {
                    return(string.Format("global::System.IntPtr"));
                }

                Enumeration @enum;
                if (arrayType.TryGetEnum(out @enum))
                {
                    return(new CSharpTypePrinterResult
                    {
                        Type = string.Format("fixed {0}", @enum.BuiltinType),
                        NameSuffix = string.Format("[{0}]", array.Size)
                    });
                }

                Class @class;
                if (arrayType.TryGetClass(out @class))
                {
                    return(new CSharpTypePrinterResult
                    {
                        Type = "fixed byte",
                        NameSuffix = string.Format("[{0}]", array.Size * @class.Layout.Size)
                    });
                }

                var arrayElemType = array.Type.Visit(this, quals).ToString();

                // C# does not support fixed arrays of machine pointer type (void* or IntPtr).
                // In that case, replace it by a pointer to an integer type of the same size.
                if (arrayElemType == IntPtrType)
                {
                    arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int";
                }

                // Do not write the fixed keyword multiple times for nested array types
                var fixedKeyword = array.Type is ArrayType ? string.Empty : "fixed ";
                return(new CSharpTypePrinterResult
                {
                    Type = string.Format("{0}{1}", fixedKeyword, arrayElemType),
                    NameSuffix = string.Format("[{0}]", array.Size)
                });
            }

            // const char* and const char[] are the same so we can use a string
            if (array.SizeType == ArrayType.ArraySize.Incomplete &&
                array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) &&
                array.QualifiedType.Qualifiers.IsConst)
            {
                return("string");
            }

            return(string.Format("{0}{1}", array.Type.Visit(this),
                                 array.SizeType == ArrayType.ArraySize.Constant ? "[]" :
                                 (ContextKind == CSharpTypePrinterContextKind.Managed ? "*" : string.Empty)));

            // C# only supports fixed arrays in unsafe sections
            // and they are constrained to a set of built-in types.
        }
Example #2
0
        public override TypePrinterResult VisitArrayType(ArrayType array,
                                                         TypeQualifiers quals)
        {
            Type arrayType = array.Type.Desugar();

            if ((MarshalKind == MarshalKind.NativeField ||
                 (ContextKind == TypePrinterContextKind.Native &&
                  MarshalKind == MarshalKind.ReturnVariableArray)) &&
                array.SizeType == ArrayType.ArraySize.Constant)
            {
                if (array.Size == 0)
                {
                    var pointer = new PointerType(array.QualifiedType);
                    return(pointer.Visit(this));
                }

                PrimitiveType primitiveType;
                if ((arrayType.IsPointerToPrimitiveType(out primitiveType) &&
                     !(arrayType is FunctionType)) ||
                    (arrayType.IsPrimitiveType() && MarshalKind != MarshalKind.NativeField))
                {
                    if (primitiveType == PrimitiveType.Void)
                    {
                        return("void*");
                    }

                    return(array.QualifiedType.Visit(this));
                }

                if (Parameter != null)
                {
                    return(IntPtrType);
                }

                Enumeration @enum;
                if (arrayType.TryGetEnum(out @enum))
                {
                    return(new TypePrinterResult
                    {
                        Type = $"fixed {@enum.BuiltinType}",
                        NameSuffix = $"[{array.Size}]"
                    });
                }

                Class @class;
                if (arrayType.TryGetClass(out @class))
                {
                    return(new TypePrinterResult
                    {
                        Type = "fixed byte",
                        NameSuffix = $"[{array.Size * @class.Layout.Size}]"
                    });
                }

                var arrayElemType = array.QualifiedType.Visit(this).ToString();

                // C# does not support fixed arrays of machine pointer type (void* or IntPtr).
                // In that case, replace it by a pointer to an integer type of the same size.
                if (arrayElemType == IntPtrType)
                {
                    arrayElemType = Context.TargetInfo.PointerWidth == 64 ? "long" : "int";
                }

                // Do not write the fixed keyword multiple times for nested array types
                var fixedKeyword = arrayType is ArrayType ? string.Empty : "fixed ";
                return(new TypePrinterResult
                {
                    Type = $"{fixedKeyword}{arrayElemType}",
                    NameSuffix = $"[{array.Size}]"
                });
            }

            // const char* and const char[] are the same so we can use a string
            if (array.SizeType == ArrayType.ArraySize.Incomplete &&
                arrayType.IsPrimitiveType(PrimitiveType.Char) &&
                array.QualifiedType.Qualifiers.IsConst)
            {
                return("string");
            }

            if (arrayType.IsPointerToPrimitiveType(PrimitiveType.Char))
            {
                var prefix = ContextKind == TypePrinterContextKind.Managed ? string.Empty :
                             "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] ";
                return($"{prefix}string[]");
            }

            var arraySuffix = array.SizeType != ArrayType.ArraySize.Constant &&
                              MarshalKind == MarshalKind.ReturnVariableArray ?
                              (ContextKind == TypePrinterContextKind.Managed &&
                               arrayType.IsPrimitiveType() ? "*" : string.Empty) : "[]";

            return($"{arrayType.Visit(this)}{arraySuffix}");
        }