I don't think so this can be done automatically - plpgsql does not check objects inside in registration time. You can use objects and functions that don't exist in CREATE FUNCTION time. And you need to know this info before optimization time. So if we implement this check automatically, then planning time can be increased a lot.
Regards
Pavel
The second question "It is v for “volatile” functions, whose results might change at any time. (Use v also for functions with side-effects, so that calls to them cannot get optimized away.)"
I think they are different semantics. One of the results is volatile functions can't be removed
by remove_unused_subquery_output even if it doesn't have side effects. for example:
select b from (select an_expensive_random(), b from t); Is it by design on purpose?