getBar() doesn't leak because the backing variable bar is not a pointer. It will be allocated and deallocated with its parent Foo object. Nine times out of ten, this is probably the best thing to do.
But if you DO need bar to be pointer to Bar, and you need to return a reference to &bar as Bar*, then that is where the PIMPL design really shines. The wrapper object (of type, say, "PBar", for example) can passed and returned by value 90% of the time with no performance penalty, thanks to copy elision and RVO. This brings you a step closer to writing code just as expressive as Java and C# without littering your code with std::unique, std::forward, std::swap, et al. If the PIMPL is backed with std::unique, you have the added advantage of single-ownership being strictly enforced at compile time. You wouldn't ever pass around Bar, at that point, just PBar. If you need perform mutative operations on the backing Bar object, you would integrate that functionality into PBar.
For me, though, hiding smart pointer boilerplate is only the second-best thing about PIMPL. The best thing is having a place to put custom allocation: std::allocator performs very poorly in applications with a lot of memory churn.