That's not terrible in and of itself, but one should really watch the nesting.
The acceptable use case is as such:
I am a low-ish component that may encounter a number of different errors however my consumer is only interested in a specific type of exception. Therefore I may do this:
catch(IOException ex)
{
throw new PlatformException("some additional context", ex);
}
Now this allows the consumer to do:
try
{
component.TryThing();
}
catch(PlatformException ex)
{
// handle error
}
Yes, I know some people will say but the consumer should catch the IOException but this depends on how abstract the consuming code actually is. What if the Impl is saving something to disk and the consumer has no valid reason to think their operation will touch the disk? In such a scenario it would make no sense to put this exception handling in the consuming code.
What we are generally trying to avoid by using this pattern is placing a "catch-all" exception handler in business logic code because we want to find out all the possible types of exceptions as they might lead to a more fundamental problem that needs to be investigated.
If we don't catch, it bubbles up, hits the "top top" level handler and should halt the app from going any further. This means the customer will report that exception and you will get a chance to look into it. This is important when you're trying to build robust software. You need to find all these error cases and write specific code to handle them.
What isn't very pretty is nesting these an excessive amount and that is the problem you should solve with this code.
As another poster stated exceptions are for reasonably exceptional behaviour but don't take this too far. Basically the code should express the "normal" operation and exceptions should handle potential problems you may come across.
In terms of performance exceptions are fine, you will get horrible results if you perf test with a debugger to an embedded device but in release without a debugger they're actually pretty quick.
The main thing people forget when discussing the performance of exceptions is that in error cases everything slows down anyway because the user has encountered a problem. Do we really care about speed when the network is down and the user can't save their work? I very much doubt getting the error report back to the user a few ms quicker is going to make a difference.
The main guideline to remember when discussing exceptions is that Exceptions should not occur within the normal application flow (normal meaning no errors). Everything else stems from that statement.
In the exact example you give I'm unsure though. It seems to me that no benefit is really gained from wrapping what seems to be a generic tcl exception in another generic sounding tcl exception. If anything I would suggest tracking down the original creator of the code and learning whether there is any particular logic behind his thinking. Chances are though that you could just kill the catch.