I use 2 and 4 where applicable (i.e. when I know the content's height or if overflowing doesn't harm). Anywhere else, I go with solution 3. By the way, your first solution has no advantage over 3 (that I can spot) because it isn't any more semantic since it uses the same dummy element.
By the way, I wouldn't be concerned about the fourth solution being a hack. Hacks in CSS would only be harmful if their underlying behaviour is subject to reinterpretation or other change. This way, your hack wouldn't be guaranteed to work. However in this case, your hack relies on the exact behaviour that overflow: auto
is meant to have. No harm in hitching a free ride.