• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37997

29 Jan 2025 02:08AM UTC coverage: 17.283% (-68.7%) from 85.981%
#37997

push

local

web-flow
bpart: Start enforcing min_world for global variable definitions (#57150)

This is the analog of #57102 for global variables. Unlike for consants,
there is no automatic global backdate mechanism. The reasoning for this
is that global variables can be declared at any time, unlike constants
which can only be decalared once their value is available. As a result
code patterns using `Core.eval` to declare globals are rarer and likely
incorrect.

1 of 22 new or added lines in 3 files covered. (4.55%)

31430 existing lines in 188 files now uncovered.

7903 of 45728 relevant lines covered (17.28%)

98663.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.3
/base/pointer.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    Ptr{T}
5

6
A memory address referring to data of type `T`.  However, there is no guarantee that the
7
memory is actually valid, or that it actually represents data of the specified type.
8
"""
9
Ptr
10

11
## converting pointers to an appropriate unsigned ##
12

13
"""
14
    C_NULL
15

16
The C null pointer constant, sometimes used when calling external code.
17
"""
18
const C_NULL = bitcast(Ptr{Cvoid}, 0)
19

20
# TODO: deprecate these conversions. C doesn't even allow them.
21

22
# pointer to integer
UNCOV
23
convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x))::T
×
24

25
# integer to pointer
26
convert(::Type{Ptr{T}}, x::Union{Int,UInt}) where {T} = Ptr{T}(x)
1✔
27

28
# pointer to pointer
29
convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p
11✔
30
convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p)::Ptr{T}
1,662,705✔
31

32
# object to pointer (when used with ccall)
33

34
"""
35
    unsafe_convert(T, x)
36

37
Convert `x` to a C argument of type `T`
38
where the input `x` must be the return value of `cconvert(T, ...)`.
39

40
In cases where [`convert`](@ref) would need to take a Julia object
41
and turn it into a `Ptr`, this function should be used to define and perform
42
that conversion.
43

44
Be careful to ensure that a Julia reference to `x` exists as long as the result of this
45
function will be used. Accordingly, the argument `x` to this function should never be an
46
expression, only a variable name or field reference. For example, `x=a.b.c` is acceptable,
47
but `x=[a,b,c]` is not.
48

49
The `unsafe` prefix on this function indicates that using the result of this function after
50
the `x` argument to this function is no longer accessible to the program may cause undefined
51
behavior, including program corruption or segfaults, at any later time.
52

53
See also [`cconvert`](@ref)
54
"""
55
function unsafe_convert end
56

57
# convert strings to String etc. to pass as pointers
UNCOV
58
cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s)
×
UNCOV
59
cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s)
×
60
unsafe_convert(::Type{Ptr{UInt8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{UInt8}, (Any,), x)
570✔
61
unsafe_convert(::Type{Ptr{Int8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{Int8}, (Any,), x)
181✔
62
unsafe_convert(::Type{Ptr{UInt8}}, s::String) = ccall(:jl_string_ptr, Ptr{UInt8}, (Any,), s)
6,248,420✔
63
unsafe_convert(::Type{Ptr{Int8}}, s::String) = ccall(:jl_string_ptr, Ptr{Int8}, (Any,), s)
717✔
64

65
cconvert(::Type{<:Ptr}, a::Array) = getfield(a, :ref)
611,808✔
66
unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a))
×
UNCOV
67
unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = unsafe_convert(Ptr{T}, a.ref)
×
UNCOV
68
unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))")
×
69
# TODO: add this deprecation to give a better error:
70
# cconvert(::Type{<:Ptr}, a::AbstractArray) = error("conversion to pointer not defined for $(typeof(a))")
71
# unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("missing call to cconvert for call to unsafe_convert for AbstractArray")
72

UNCOV
73
cconvert(::Type{<:Ptr}, a::GenericMemory) = a
×
74
unsafe_convert(::Type{Ptr{Cvoid}}, a::GenericMemory{T}) where {T} = getfield(a, :ptr)
64,287✔
75
unsafe_convert(::Type{Ptr{T}}, a::GenericMemory) where {T} = convert(Ptr{T}, getfield(a, :ptr))
226,217✔
76

77
function unsafe_convert(::Type{Ptr{Cvoid}}, a::GenericMemoryRef{<:Any,T,Core.CPU}) where {T}
78
    mem = getfield(a, :mem)
128✔
79
    offset = getfield(a, :ptr_or_offset)
1,437,561✔
80
    MemT = typeof(mem)
92✔
81
    arrayelem = datatype_arrayelem(MemT)
92✔
82
    elsz = datatype_layoutsize(MemT)
92✔
83
    isboxed = 1; isunion = 2
92✔
84
    if arrayelem == isunion || elsz == 0
92✔
85
        offset = UInt(offset) * elsz
36✔
86
        offset += unsafe_convert(Ptr{Cvoid}, mem)
36✔
87
    end
88
    return offset
92✔
89
end
90
unsafe_convert(::Type{Ptr{T}}, a::GenericMemoryRef) where {T} = convert(Ptr{T}, unsafe_convert(Ptr{Cvoid}, a))
613,290✔
91

92
# unsafe pointer to array conversions
93
"""
94
    unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)
95

96
Wrap a Julia `Array` object around the data at the address given by `pointer`,
97
without making a copy.  The pointer element type `T` determines the array
98
element type. `dims` is either an integer (for a 1d array) or a tuple of the array dimensions.
99
`own` optionally specifies whether Julia should take ownership of the memory,
100
calling `free` on the pointer when the array is no longer referenced.
101

102
This function is labeled "unsafe" because it will crash if `pointer` is not
103
a valid memory address to data of the requested length. Unlike [`unsafe_load`](@ref)
104
and [`unsafe_store!`](@ref), the programmer is responsible also for ensuring that the
105
underlying data is not accessed through two arrays of different element type, similar
106
to the strict aliasing rule in C.
107
"""
UNCOV
108
function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}},
×
109
                     p::Ptr{T}, dims::NTuple{N,Int}; own::Bool = false) where {T,N}
UNCOV
110
    ccall(:jl_ptr_to_array, Array{T,N}, (Any, Ptr{Cvoid}, Any, Int32),
×
111
          Array{T,N}, p, dims, own)
112
end
113
function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,1}}},
319✔
114
                     p::Ptr{T}, d::Integer; own::Bool = false) where {T}
115
    ccall(:jl_ptr_to_array_1d, Array{T,1},
319✔
116
          (Any, Ptr{Cvoid}, Csize_t, Cint), Array{T,1}, p, d, own)
117
end
UNCOV
118
function unsafe_wrap(::Union{Type{GenericMemory{kind,<:Any,Core.CPU}},Type{GenericMemory{kind,T,Core.CPU}}},
×
119
                     p::Ptr{T}, dims::Tuple{Int}; own::Bool = false) where {kind,T}
UNCOV
120
    ccall(:jl_ptr_to_genericmemory, Ref{GenericMemory{kind,T,Core.CPU}},
×
121
          (Any, Ptr{Cvoid}, Csize_t, Cint), GenericMemory{kind,T,Core.CPU}, p, dims[1], own)
122
end
123
function unsafe_wrap(::Union{Type{GenericMemory{kind,<:Any,Core.CPU}},Type{GenericMemory{kind,T,Core.CPU}}},
×
124
                     p::Ptr{T}, d::Integer; own::Bool = false) where {kind,T}
125
    ccall(:jl_ptr_to_genericmemory, Ref{GenericMemory{kind,T,Core.CPU}},
×
126
          (Any, Ptr{Cvoid}, Csize_t, Cint), GenericMemory{kind,T,Core.CPU}, p, d, own)
127
end
128
unsafe_wrap(Atype::Union{Type{Array},Type{Array{T}},Type{Array{T,N}},Type{GenericMemory{kind,<:Any,Core.CPU}},Type{GenericMemory{kind,T,Core.CPU}}} where {kind},
×
129
            p::Ptr{T}, dims::NTuple{N,<:Integer}; own::Bool = false) where {T,N} =
130
    unsafe_wrap(Atype, p, convert(Tuple{Vararg{Int}}, dims), own = own)
131

132

133
"""
134
    unsafe_load(p::Ptr{T}, i::Integer=1)
135
    unsafe_load(p::Ptr{T}, order::Symbol)
136
    unsafe_load(p::Ptr{T}, i::Integer, order::Symbol)
137

138
Load a value of type `T` from the address of the `i`th element (1-indexed) starting at `p`.
139
This is equivalent to the C expression `p[i-1]`. Optionally, an atomic memory ordering can
140
be provided.
141

142
The `unsafe` prefix on this function indicates that no validation is performed on the
143
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
144
that referenced memory is not freed or garbage collected while invoking this function.
145
Incorrect usage may segfault your program or return garbage answers. Unlike C, dereferencing
146
memory region allocated as different type may be valid provided that the types are compatible.
147

148
!!! compat "Julia 1.10"
149
     The `order` argument is available as of Julia 1.10.
150

151
See also: [`atomic`](@ref)
152
"""
153
unsafe_load(p::Ptr, i::Integer=1) = pointerref(p, Int(i), 1)
9,363,085✔
UNCOV
154
unsafe_load(p::Ptr, order::Symbol) = atomic_pointerref(p, order)
×
155
function unsafe_load(p::Ptr, i::Integer, order::Symbol)
×
156
    unsafe_load(p + (elsize(typeof(p)) * (Int(i) - 1)), order)
×
157
end
158

159
"""
160
    unsafe_store!(p::Ptr{T}, x, i::Integer=1)
161
    unsafe_store!(p::Ptr{T}, x, order::Symbol)
162
    unsafe_store!(p::Ptr{T}, x, i::Integer, order::Symbol)
163

164
Store a value of type `T` to the address of the `i`th element (1-indexed) starting at `p`.
165
This is equivalent to the C expression `p[i-1] = x`. Optionally, an atomic memory ordering
166
can be provided.
167

168
The `unsafe` prefix on this function indicates that no validation is performed on the
169
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
170
that referenced memory is not freed or garbage collected while invoking this function.
171
Incorrect usage may segfault your program. Unlike C, storing memory region allocated as
172
different type may be valid provided that the types are compatible.
173

174
!!! compat "Julia 1.10"
175
     The `order` argument is available as of Julia 1.10.
176

177
See also: [`atomic`](@ref)
178
"""
UNCOV
179
unsafe_store!(p::Ptr{Any}, @nospecialize(x), i::Integer=1) = pointerset(p, x, Int(i), 1)
×
180
unsafe_store!(p::Ptr{T}, x, i::Integer=1) where {T} = pointerset(p, convert(T,x), Int(i), 1)
37,336✔
UNCOV
181
unsafe_store!(p::Ptr{T}, x, order::Symbol) where {T} = atomic_pointerset(p, x isa T ? x : convert(T,x), order)
×
182
function unsafe_store!(p::Ptr, x, i::Integer, order::Symbol)
×
183
    unsafe_store!(p + (elsize(typeof(p)) * (Int(i) - 1)), x, order)
×
184
end
185

186
"""
187
    unsafe_modify!(p::Ptr{T}, op, x, [order::Symbol]) -> Pair
188

189
These atomically perform the operations to get and set a memory address after applying
190
the function `op`. If supported by the hardware (for example, atomic increment), this may be
191
optimized to the appropriate hardware instruction, otherwise its execution will be
192
similar to:
193

194
    y = unsafe_load(p)
195
    z = op(y, x)
196
    unsafe_store!(p, z)
197
    return y => z
198

199
The `unsafe` prefix on this function indicates that no validation is performed on the
200
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
201
that referenced memory is not freed or garbage collected while invoking this function.
202
Incorrect usage may segfault your program.
203

204
!!! compat "Julia 1.10"
205
     This function requires at least Julia 1.10.
206

207
See also: [`modifyproperty!`](@ref Base.modifyproperty!), [`atomic`](@ref)
208
"""
UNCOV
209
function unsafe_modify!(p::Ptr, op, x, order::Symbol=:not_atomic)
×
UNCOV
210
    return atomic_pointermodify(p, op, x, order)
×
211
end
212

213
"""
214
    unsafe_replace!(p::Ptr{T}, expected, desired,
215
                   [success_order::Symbol[, fail_order::Symbol=success_order]]) -> (; old, success::Bool)
216

217
These atomically perform the operations to get and conditionally set a memory address to
218
a given value. If supported by the hardware, this may be optimized to the appropriate
219
hardware instruction, otherwise its execution will be similar to:
220

221
    y = unsafe_load(p, fail_order)
222
    ok = y === expected
223
    if ok
224
        unsafe_store!(p, desired, success_order)
225
    end
226
    return (; old = y, success = ok)
227

228
The `unsafe` prefix on this function indicates that no validation is performed on the
229
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
230
that referenced memory is not freed or garbage collected while invoking this function.
231
Incorrect usage may segfault your program.
232

233
!!! compat "Julia 1.10"
234
     This function requires at least Julia 1.10.
235

236
See also: [`replaceproperty!`](@ref Base.replaceproperty!), [`atomic`](@ref)
237
"""
UNCOV
238
function unsafe_replace!(p::Ptr{T}, expected, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order) where {T}
×
UNCOV
239
    @inline
×
UNCOV
240
    xT = desired isa T ? desired : convert(T, desired)
×
UNCOV
241
    return atomic_pointerreplace(p, expected, xT, success_order, fail_order)
×
242
end
UNCOV
243
function unsafe_replace!(p::Ptr{Any}, @nospecialize(expected), @nospecialize(desired), success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
×
UNCOV
244
    return atomic_pointerreplace(p, expected, desired, success_order, fail_order)
×
245
end
246

247
"""
248
    unsafe_swap!(p::Ptr{T}, x, [order::Symbol])
249

250
These atomically perform the operations to simultaneously get and set a memory address.
251
If supported by the hardware, this may be optimized to the appropriate hardware
252
instruction, otherwise its execution will be similar to:
253

254
    y = unsafe_load(p)
255
    unsafe_store!(p, x)
256
    return y
257

258
The `unsafe` prefix on this function indicates that no validation is performed on the
259
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
260
that referenced memory is not freed or garbage collected while invoking this function.
261
Incorrect usage may segfault your program.
262

263
!!! compat "Julia 1.10"
264
     This function requires at least Julia 1.10.
265

266
See also: [`swapproperty!`](@ref Base.swapproperty!), [`atomic`](@ref)
267
"""
UNCOV
268
function unsafe_swap!(p::Ptr{Any}, x, order::Symbol=:not_atomic)
×
UNCOV
269
    return atomic_pointerswap(p, x, order)
×
270
end
UNCOV
271
function unsafe_swap!(p::Ptr{T}, x, order::Symbol=:not_atomic) where {T}
×
UNCOV
272
    @inline
×
UNCOV
273
    xT = x isa T ? x : convert(T, x)
×
UNCOV
274
    return atomic_pointerswap(p, xT, order)
×
275
end
276

277
# convert a raw Ptr to an object reference, and vice-versa
278
"""
279
    unsafe_pointer_to_objref(p::Ptr)
280

281
Convert a `Ptr` to an object reference. Assumes the pointer refers to a valid heap-allocated
282
Julia object. If this is not the case, undefined behavior results, hence this function is
283
considered "unsafe" and should be used with care.
284

285
See also [`pointer_from_objref`](@ref).
286
"""
287
unsafe_pointer_to_objref(x::Ptr) = ccall(:jl_value_ptr, Any, (Ptr{Cvoid},), x)
148,321✔
288

289
"""
290
    pointer_from_objref(x)
291

292
Get the memory address of a Julia object as a `Ptr`. The existence of the resulting `Ptr`
293
will not protect the object from garbage collection, so you must ensure that the object
294
remains referenced for the whole time that the `Ptr` will be used.
295

296
This function may not be called on immutable objects, since they do not have
297
stable memory addresses.
298

299
See also [`unsafe_pointer_to_objref`](@ref).
300
"""
301
function pointer_from_objref(@nospecialize(x))
302
    @inline
439✔
303
    ismutable(x) || error("pointer_from_objref cannot be used on immutable objects")
439✔
304
    ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x)
24,189✔
305
end
306

307
## limited pointer arithmetic & comparison ##
308

UNCOV
309
isequal(x::Ptr, y::Ptr) = (x === y)
×
UNCOV
310
isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y
×
311

312
==(x::Ptr, y::Ptr) = UInt(x) == UInt(y)
846,167✔
313
<(x::Ptr,  y::Ptr) = UInt(x) < UInt(y)
6✔
314
-(x::Ptr,  y::Ptr) = UInt(x) - UInt(y)
1,748✔
315

316
+(x::Ptr, y::Integer) = add_ptr(x, (y % UInt) % UInt)
6,099,192✔
317
-(x::Ptr, y::Integer) = sub_ptr(x, (y % UInt) % UInt)
4,964,612✔
318
+(x::Integer, y::Ptr) = y + x
36✔
319

320
unsigned(x::Ptr) = UInt(x)
×
321
signed(x::Ptr) = Int(x)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc