F2018 §10.2.2.3: rank-remap pointer assignment
real(sp), pointer :: tau(:)
real(sp), target :: q(5, 5)
tau(1:k) => q(1:k, 1)
lower_rank_remap_pointer_assignment used to require RHS = bare Name
and bail on any FunctionCall (section/element) — the pointer
descriptor never got its base_addr, rank, or extents populated.
Subsequent 'geqrf(..., tau, ...)' (assumed-size dummy 'tau(*)') then
received tau.base_addr = NULL, and slarfg's '*tau = ...' SEGV'd at
depth. Surfaced as SEGVs across stdlib's qr/eig/schur cluster:
example_qr, example_qr_space, example_pivoting_qr*, example_eig*,
example_schur*.
Extend the source-shape match to handle FunctionCall (section
designator on a Name): convert each Range(start:..) into Element(start),
compute the address of the FIRST included element via
lower_array_element_addr, and use that as the descriptor's base_addr
with the target's bounds.
F2018 §7.8: a typed array constructor '[T :: ...]' has element type T
regardless of the element expressions' types. The reshape lowering at
lower_reshape_array_expr_descriptor inferred elem_ty solely via
first_array_constructor_type_info, which examines the first value
expression. For 'reshape([real(dp) :: 1, 2, 3, 4], [2, 2])' the values
are integer literals (4 bytes), so the materialised descriptor was
elem_size=4 instead of 8.
The malformed elem_size propagated through the reshape result; when
passed to an assumed-shape dummy 'a(:,:)' and used as SOURCE= in an
ALLOCATE, afs_prepare_array_copy saw 'dest.elem_size != source.elem_size'
(8 != 4), freed the freshly-allocated dest buffer, zeroed base_addr,
and the next read of 'amat(1,1)' SEGV'd. Surfaced across stdlib's det /
determinant / eig / qr clusters whose examples invoke
'det(reshape([real(dp)::1,2,3,4], [2,2]))'.
Consult type_spec first; fall back to first-element inference only when
no type_spec is present.
F2018 §9.7.1.2: SOURCE-expr in ALLOCATE need only be a value of the
right type/kind/shape — it doesn't have to itself be an ALLOCATABLE.
The common stdlib pattern is
pure module function det(a) result(d)
real(dp), intent(in) :: a(:,:) ! assumed-shape dummy
real(dp), allocatable :: amat(:,:)
allocate(amat(size(a,1), size(a,2)), source=a)
afs_prepare_array_copy required both dest.is_allocated() AND
source.is_allocated(). Assumed-shape dummies carry flags=CONTIGUOUS
only — they're bound to the caller's data, not owned — so
source.is_allocated() returned false, the routine freed the
fresh dest buffer, zeroed dest.base_addr, and the next read of
amat(1,1) faulted. Surfaced as SEGV across stdlib's det / determinant
/ eig / qr / lstsq / solve_chol / solve_custom clusters.
Replace source.is_allocated() with !source.base_addr.is_null():
the source is valid as long as it points to data, regardless of
whether it owns it.