> Well implemented exception systems allow you to transparently handle exceptions up in the stack
If by "transparently" you mean that the code can automatically unwind the stack frames of several unsuspecting functions, you're right. _All_ exceptions systems I know of do this. This is also usually pointed out as one of the weakness in exceptions, because an implicit flow of control is introduced, and you have to always be aware of it. Much like what happens when you write multi-threaded applications.
> if you want to pass up error codes, you will have to manually make sure that every error code is passed as the error code of the current routine and the flow is stopped as soon as an error is detected.
No you don't have to. You can have a global error object (à la errno) and pass up the error _condition_ (that is, that there has been an error). This can even been in the error object, you don't even need to return an special value. What you have to do is check explicitly after each call if there has been an error or not. This is a bug or a feature, depending who you ask. I personally find both useful sometimes, but I have been seen cursing both from time to time. Exceptions are tempting, for the same reason that garbage collection is: it helps you being lazy. But you have to be aware of the price you pay, and that it may come back to bite you later. My personal opinion is that anybody saying one or the other is The Right Thing(TM) is just a moron.
> Using error codes also makes it difficult to generate clear and details backtraces
This is simply not true. There's nothing preventing you from generating backtraces and what not if the language and/or the libraries provide you with the tools (I have done this in Python and Delphi, for instance).
> If you have such facilities then you have implemented an exception systems.
No, because the implicit flow of control that characterizes exceptions is missing.