This issue is caused by a compiler optimization called "COMDAT folding".
On non-compiled builds, BIV_IsCompiled and BIV_TrayMenu have the same implementation: just return an empty string. This is because the BIV interface only supports strings, and all objects are treated as "" when used in that context. The actual implementation of A_TrayMenu is in the expression evaluator, and is dependent on
mBIV == &BIV_TrayMenu.
With COMDAT folding, identical functions (that is, functions with the exact same machine code implementation) are "folded", such that you're actually calling the same address. So in this case,
mBIV == &BIV_TrayMenu and
mBIV == &BIV_IsCompiled are both true.
An interesting side note is that since True, False, A_PtrSize and A_IsUnicode are optimized by comparing the address in mBIV and replacing them with the corresponding constant value at load time, any BIV functions identical with those will be optimized as well. So for instance, if v2 had an ANSI build, A_IsCompiled would automatically be resolved to "" at load time, because its compiled form would be identical to A_IsUnicode (but only in ANSI builds). I didn't optimize A_IsCompiled this way because it isn't used in (performance-critical) expressions much, and there is a small cost to code size.
There seems to be
some disagreement about whether the change in behaviour caused by this optimization complies with or violates the C++ standard.
Either way, I'll work around it (to fix the bug).
Edit: Fixed by v2.0-a084.