In my experience, many people who embrace exceptions have previously worked with code that didn't have them, and had to deal with the if/else/error-code hell and people ignoring them (HRESULTS anyone?) and many of those who avoid them have used them in Java, experiencing all the problems Andy describes. (many more who object to them have never used them. That is a a different disucssion)
To me, the culprit is not exceptions (or error codes), but rather how they get used/misused. Bad code is bad code, and there is no language construct or usage rule that is going to turn those who write bad code into people who right good code. To me the more important question is: How easy is it for someone who can write good code to write good code? Having navigated the HRESULT error code hell of COM, I know what the answer is for me -- exceptions make it easier for me to write good code, so I prefer them.
On one project, we were called on to improve parts of a C++ system that had both COM and non-COM elements. Initially the project's mandate was: No exceptions. Deal in error codes, because ultimately that's what the system will produce. It was a mess -- not because of the error codes per se, but because the programmers who wrote the code, did not handle them properly. Later the rule was relaxed and exceptions were allowed, yet those same programmers proceeded to make a huge mess of the exception handling -- in both cases, they tended to ignore or eat errors -- both their own, and in code called.
The difference (and why I disagree with Joel) is that when we set about cleaning things up, it was much easier to do so with exceptions (and then translating those to HRESULTS at the system boundary) then it was to manage all of that if/else/error-code infrastructure that Joel is advocating. Because our goal was to design a robust system that handled its error conditions properly, and we had people who knew how to do so, we succeeded. Not because we used exceptions, but because used people who knew how to write good code.
Every exception-handling pitfall Joel and Andy point out can be avoided if you write clear, intention-revealing, well-tested code. For example: multiple return paths in a function are fine if that code satisfies those requirements. Homework assignment: think about all of their examples and see if you can find one where applying those three things would not make a positive difference.
So, my position on this religious war is that both sides of the debate are dealing with a symptom and not the real problem. The real problem is bad coders. If I agreed with Joel's implication that standards and prohibitions can turn bad coders into good ones, I might also agree with him in advocating error codes -- as exceptions have a steeper learning curve -- but I don't agree. I don't believe in wasting time, energy and money trying to mandate quality in others. Instead I focus on what helps me write better code, and for others I recommend they enable those who can write better code do so, and get those who can't out of their way.
Exceptions are just another poweful tool in the toolshed, no more to be avoided than a band saw. If you have people who can't use the band saw, don't remove it from the machine shop, remove them from the machine shop.
BTW, I wonder if Joel will go for vi/emacs as an encore?