I wrote an app that sends two transactions which double spend the same output in a row. The second never generates a reject message, because we end up in the dead “replace tx” codepath which returns false and doesn’t even log anything, so the tx disappears silently. I think if that codepath is taken out or just #defined out so it’s clear where the fixed code should go once done, then it will fall through to the other checks below.
However then we have a second problem, which is that if all the tx outputs are spent already, it also won’t trigger a reject message because it will hit the block starting with
0 // do all inputs exist?
and end up failing to find the CCoins, so again, no reject message.