If the lifetime of the temporary ended with the function body, the assignment (which reads the temporary via the returned reference) happens afterwards and that's UB. Essentially,
int const &r = f(3);
and
int r = f(3);
would both be UB under that implementation-defined case.
The posted article, second row of "common mistakes", describes returning a const reference parameter, when called with a prvalue, as blanket UB.
"6.1 A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call."
So, while the parameter's (the reference "int const &a") lifetime is implementation-defined, the temporary to which that parameter refers to is the full expression of the call. Sanity is restored.
const int& f(int parameter) { return parameter; }
const int i = f(42);
Is strictly undefined behavior under the simpler C++03 rules/wording of 5.2.2/4: "The lifetime of a parameter ends when the function in which it is defined returns.")
P0135R0 would loosen the requirements on parameter's lifetime as a means of enabling guaranteed copy elision, in such a way that an implementation could technically decide to make this to have defined behavior (not that I suggest relying on it!)
The posted article, second row of "common mistakes", describes returning a const reference parameter, when called with a prvalue, as blanket UB.
Finally someone clarified: https://timsong-cpp.github.io/cppwp/class.temporary#6.1
"6.1 A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call."
So, while the parameter's (the reference "int const &a") lifetime is implementation-defined, the temporary to which that parameter refers to is the full expression of the call. Sanity is restored.