GCC 6 `std::sort` sometimes compares an element to itself. For a normal
implementation of comparison, this is useless, but not harmful. The
render comparison predicate relies on accessing A[B[a][b]] when
comparing `a` and `b`. Array `B` has `-1` in positions where `a == b`,
which causes an access to `A[-1]`, which is undefined behavior. This
crashes when using _GLIBCXX_DEBUG:
Error: attempt to subscript container with out-of-bounds index -1, but
container only holds 8 elements.
Objects involved in the operation:
sequence "this" @ 0x0x335adf0 {
type = std::__debug::array<int, 8ul>::_Array_check_subscript<8ul>;
}
Since this is undefined behavior, non-debug builds might also misbehave.
Current data layouts make it likely that the failure would not have
externally observable consequences.
Prevent the invalid access by short-circuiting the result if `a == b`.
When using `gcc -fsanitize=undefined`, the compiler proves trivial
results, so `DXX_CONSTANT_TRUE` is defined. It then fails to prove that
`DXX_CONSTANT_TRUE(m_state == checked)` is false, causing a compile-time
error. Relax the check to occur only when it can prove `m_state` equal
to a disallowed value, rather than when it cannot prove `m_state` equal
to an allowed value.
Move the preprocessor guard so that the runtime check is always visible.
Optimizing compilers can still eliminate that check at compile-time when
it provably never fails.
Rebirth built with `gcc -fsanitize=undefined` warns when binding a
reference to nullptr, even if that reference is never followed. This
could be reproduced using a guided missile against the first PIG in
Descent 2: Counterstrike level 1.
This object pointer is used only to test for address equality, so
nullptr is safe here. Switch to pass it as a pointer to prevent the
warning.
Macro LINE_SPACING previously used global grd_curcanv implicitly.
Change it to take a canvas argument. Change all callers to pass
grd_curcanv, so that usage is explicit.
As a macro, it always refers to the global grd_curcanv. This interferes
with converting canvas handling to be an argument. Expand GHEIGHT so
that uses of grd_curcanv can be changed individually.
As a macro, it always refers to the global grd_curcanv. This interferes
with converting canvas handling to be an argument. Expand GWIDTH so
that uses of grd_curcanv can be changed individually.