ASan is an LLVM pass but instruments only functions carrying sanitize_address, which clang's C frontend adds and nothing adds to IR written by hand. Passing -fsanitize=address to the clang run over the .ll therefore instruments flan_rt.c and not one instruction of Flan: an out-of-bounds read of a defvar array, built --no-bounds-checks, printed its garbage and exited 0. With Emit naming an attribute group on every define, the same program reports global-buffer-overflow in flan.main. UBSan has no such lever. Its checks are branches the C frontend emits to __ubsan_handle_*, not a pass, so -fsanitize=undefined covers the runtime and nothing else; (<< 1 32) still goes unremarked. Recorded where it will be read rather than discovered again. The flag does not force -O0 the way --debug does -- the UB worth finding is what the optimiser does with it -- and it does pull in -g, since a report with no line costs more than the build. compile_c's cache key now digests the same cflags list the command line uses, because an unsanitized flan_rt.o served out of the cache links fine and reports nothing.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%