From 16ba3203b9c470aa79f1ac198e319b07e480d1b7 Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Fri, 11 Nov 2022 12:38:44 -0600 Subject: [PATCH] Test functionality of automatic conversion in ccall This adds tests for the `cconvert` method used implicitly during `ccall`s. When designing the tests, though, it became obvious that real-world conversion to `Cint` arguments (such as calls to `mmap` in UnixMmap.jl) weren't covered by the existing method. Change the behavior to allow for conversion to any integer type which can be represented by the destination type. --- src/BitFlags.jl | 6 +++--- test/runtests.jl | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/BitFlags.jl b/src/BitFlags.jl index 2eec7f3..43533fb 100644 --- a/src/BitFlags.jl +++ b/src/BitFlags.jl @@ -16,9 +16,9 @@ abstract type BitFlag{T<:Integer} end basetype(::Type{<:BitFlag{T}}) where {T<:Integer} = T -(::Type{T})(x::BitFlag{T2}) where {T<:Integer,T2<:Unsigned} = T(bitcast(T2, x))::T -Base.cconvert(::Type{T}, x::BitFlag{T2}) where {T<:Unsigned,T2<:Unsigned} = T(x) -Base.write(io::IO, x::BitFlag{T}) where {T<:Unsigned} = write(io, T(x)) +(::Type{T})(x::BitFlag{T2}) where {T<:Integer, T2} = T(bitcast(T2, x))::T +Base.cconvert(::Type{T}, x::BitFlag{T2}) where {T<:Integer, T2} = T(T2(x)) +Base.write(io::IO, x::BitFlag{T}) where {T} = write(io, T(x)) Base.read(io::IO, ::Type{T}) where {T<:BitFlag} = T(read(io, basetype(T))) Base.isless(x::T, y::T) where {T<:BitFlag} = isless(basetype(T)(x), basetype(T)(y)) diff --git a/test/runtests.jl b/test/runtests.jl index 7fecfaa..14f8428 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -69,6 +69,22 @@ end # Broadcasting @test [flag1a, flag1b] .| flag1c == [flag1a | flag1c, flag1b | flag1c] + + # ccall conversion + @bitflag CFlag1::UInt64 begin + cflag1_small = 1 + cflag1_large = UInt64(1) << 63 + end + flag_nonzero(x::Integer) = Cint(!iszero(x)) + cflag_nonzero_u64 = @cfunction(flag_nonzero, Cint, (UInt64,)) + cflag_nonzero_u32 = @cfunction(flag_nonzero, Cint, (UInt32,)) + cflag_nonzero_i32 = @cfunction(flag_nonzero, Cint, (Int32,)) + @test ccall(cflag_nonzero_u64, Cint, (UInt64,), cflag1_small) == 1 + @test ccall(cflag_nonzero_u32, Cint, (UInt32,), cflag1_small) == 1 + @test ccall(cflag_nonzero_i32, Cint, (Int32,), cflag1_small) == 1 + @test ccall(cflag_nonzero_u64, Cint, (UInt64,), cflag1_large) == 1 + @test_throws InexactError ccall(cflag_nonzero_u32, Cint, (UInt32,), cflag1_large) + @test_throws InexactError ccall(cflag_nonzero_i32, Cint, (Int32,), cflag1_large) #end #@testset "Type properties" begin