Example #1
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($"fixed {@enum.BuiltinType}",
                                                 $"[{array.Size}]"));
                }

                if (arrayType.IsClass())
                {
                    return(new TypePrinterResult($"fixed byte", $"[{array.GetSizeInBytes()}]"));
                }

                TypePrinterResult arrayElemType = array.QualifiedType.Visit(this);

                // 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(fixedKeyword + arrayElemType.Type,
                                             $"[{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)] ";
                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}");
        }