This patch fixes three groups of failures I've come across with C++ exception handling.
- Under some circumstances a cleanup handler will call terminate and go to an unreachable instruction rather than returning. This caused an assertion in the code that tries to insert a stub landing pad. There are a couple of problems here that I didn't attempt to address. I don't think the front end should be inserting a landing pad with a terminate call, since the runtime takes care of that on Windows. Also, the IR is generated as a landing pad with a catch-all clause but no begin/end catch. As a result we are interpreting it as cleanup code. In any event, it seems useful, at least in the short term, to handle the case of an outlined handler that flows to an unreachable instruction but not a return instruction.
- Under some circumstances the front end will chain together a series of catch dispatch blocks wherein some selectors are repeated and do not correspond to clauses in the parent landing pad. This happens when similar block sequences are combined. It should work because the earlier dispatch will logically catch the exception and make the later dispatch unreachable for that code path. However, our handler block mapping wasn't paying attention to which selector comparisons were being done and so it thinks it is done mapping blocks before it actually is. The "fix" I have for that is intended as a stop-gap measure to get some tests passing until we can decide how this should be redesigned.
- When blocks are combined for multiple landing pads the selector values can reach the dispatch comparison through a PHI node and thus confuse the cloning code. The cloning code tries to do constant folding to avoid cloning blocks it doesn't need, but in this case the PHI resolution doesn't happen until all blocks have been cloned and so we hit an assertion when a second begincatch call is reached. I worked around this by treating all compare instructions which have an llvm.eh.typeid.for result as an operand as if the other operand is the selector value (which I believe will always be true). This effectively emulates the suggestion I made of combining the llvm.eh.typeid.for+icmp instructions into a single intrinsic. I still think adding that intrinsic is a better solution but, again, this gets some things working in the meantime.
I don't really think that any of the changes in this patch are the right long term solution, but I think they are worth committing to establish a baseline of correct results.