Regression for F2018 §16.9.81/§16.9.187/§16.9.92. Pre-fix the
module-level `parameter :: tol = epsilon(1.0_dp)` initializer
stored 0.0; the test would error-stop on the first comparison.
F2018 §16.9.81 / §16.9.187 / §16.9.92: EPSILON, TINY, and HUGE are
numeric inquiry intrinsics that fold at compile time when the
operand has a known kind. Pre-fix eval_const_scalar lacked these
in its FunctionCall fold list, so module-level
real(dp), parameter :: tol_dp = epsilon(1.0_dp)
stored 0.0 in the binary. Every dependent runtime check then
behaved as if the tolerance were zero — breaking convergence
loops like the modified-Lentz iteration in
stdlib_specialfunctions_gamma's gpx_*:
do
...
if (abs(y - one) < tol_dp) exit
end do
which spun forever on every gamma_p/gamma_q/ligamma/uigamma call.
gamma_pdf SEGV'd on a separate path (NaN propagation).
The fold reads the operand's kind from a real-literal suffix
(`1.0_dp` → kind 8 → f64) or integer-literal kind, falls back
on default real/integer kinds, and emits the corresponding
{f32,f64,i32,i64}::EPSILON / MIN_POSITIVE / MAX.
Regression for F2018 §11.2.3. Pre-fix every selector silently fell
through to the post-list statement; the test would have hit the
default branch every iteration.
F2018 §11.2.3: `GO TO (l1, l2, ..., ln) expr` evaluates the integer
expr; if 1 <= expr <= n, branches to label[expr]; otherwise falls
through to the next statement.
Pre-fix Stmt::ComputedGoto had NO lowering case, so every selector
silently fell through. This broke every LAPACK driver routine that
uses computed goto for parameter validation — most visibly
`stdlib_ilaenv`, the LAPACK environment-inquiry function called
to get optimal block sizes. ilaenv's first line is
`go to (10, 10, 10, 80, ...) ispec`; with computed goto silently
falling through, every query fell into the `stdlib_ilaenv = -1`
default path. Routines that pre-allocate workspaces from
`stdlib_ilaenv(...)` then computed lwork from -1, getri returned
info = -6 (lwork too small), inverse triggered the error path,
and the formatter SEGV'd dereferencing a malformed err state.
Lowering is a chain of (icmp eq sel, k) → cond_br to label[k-1]
or fall to next check. The final fall-through block is what the
next statement sees. Empty label list still evaluates the selector
expression for side effects.
Regression for F2018 §15.5.2.4(13). Pre-fix this fired
'index 1 outside [1, 0]' inside the callee body — the failure
mode that kept stdlib_linalg's LAPACK call chain (sgetrf2 →
strsm with a(1, n1+1)) silently broken.
F2018 §15.5.2.4(13) — argument storage association: when a dummy is
declared with explicit shape (e.g. `a(lda, *)`) and the actual
argument is, say, an array element designator like `a(1, n1+1)`,
the caller's descriptor may have rank 0 or other misshapen dim
metadata. The dummy must present its OWN declared shape — bounds
come from the formal's declaration, not the actual's descriptor.
Without the rebase, accesses to the explicit dim trip
`index k outside [1, 0]` because afs_array_lbound/ubound on a
rank-0 descriptor return the (1, 0) sentinel. This is exactly the
failure inside stdlib_linalg's solve / chol / svd: sgetrf2 calls
strsm with `a(1, n1+1)` for the `b(ldb, *)` parameter; pre-fix
strsm's first b(i, j) write fired the bounds check.
The new install_explicit_shape_dummy_rebase fires on entry for
descriptor_arg dummies whose spec is `Explicit{ ... } [, *]`. It
allocates a fresh local descriptor, memcpys the caller's so we
preserve base_addr + elem_size, then patches rank, each Explicit
dim's lower/upper from the formal expressions, and column-major
strides. AssumedSize last dim leaves upper untouched —
last_dim_assumed_size already suppresses bounds checks on it.
Regression test for F2018 §8.5.8.5: `a(lda, *)` dummy must accept
indexing past the actual's first-dim extent. Pre-fix this fired
'index 1 outside [1, 0]' and silently broke every LAPACK call
through stdlib_linalg.
F2018 §8.5.8.5: an explicit-shape dummy with `*` last dim
(e.g. `a(lda, *)`) carries no upper bound on the last dim — accesses
past the actual's nominal extent are legal as long as the underlying
storage permits. Previously the lowering emitted a bounds check
against the (1, 0) sentinel that extract_array_dims produces for
AssumedSize, so every legal index past 0 fired
`index k outside [1, 0]`.
This pattern shows up throughout LAPACK (gesv/getrf/getrs/laswp
all take `b(ldb, *)`) and is what kept example_solve1 silently
failing inside stdlib_linalg's solve_lu_one → gesv chain even after
the rank-remap pointer assignment fix landed.
LocalInfo gains a last_dim_assumed_size flag, populated at dummy
setup via arg_last_dim_assumed_size_from_decls.
compute_flat_elem_offset consults it on both the runtime-descriptor
and static-shape paths.