This kind of analysis is not quite possible to perform with all languages. With some languages doing this kind of data flow analysis basically requires you to run the code and as soon as you perform IO you're out of luck.
There are static analyzers that try their best getting this data, but with arbitrary references without clearly annotated lifetimes that can very often become a stack of "well, it depends" to the point the analysis has to give up.
Deduction of lifetimes in statically-typed languages without a borrow checker is very similar to deduction of types in dynamically-typed programs.