--dev --sanitize did not compile. Any program, at any optimisation
level: clang 20's AddressSanitizer module pass segfaults on the module,
and the message it leaves behind is its own crash backtrace rather than
anything about the program. Reduced here to five lines of IR, and the
trigger is narrow -- @llvm.global_ctors naming a function that the
module only *declares*. Both of ours are declarations, because both are
C in the runtime.
This predates the crash-handler lane and is not its doing: the one-entry
table, with flan_dev_reg_enable alone in it, crashes the same way, and
that entry has been emitted since the registry was armed from a
constructor. What the lane did was add a second declaration to a shape
that was already crashing, where nothing built the combination to
notice.
So the table names a local definition that calls the two, which is the
shape clang emits for its own constructors, and it costs a call once
before main. The ordering it fixes was unspecified before -- two entries
at one priority -- and arming the registry before installing the handler
is the order that was wanted.
What it unblocks is the reason to care. flan_dev_crash_enable yields to
ASan through a weak __asan_init so the two do not both own SIGSEGV, and
that line could not have run, because the build it guards would not
link. It does now: a dev build of dev-segv.flan at -O0 under ASan takes
the fault, ASan reports it with the frame, and the handler stays out of
the way instead of parking. No alias covers the combination, so that
check was made by hand.