Yes, it is legal for a function to return references to input parameters, in the sense that it will compile and there are many uses where it will work without problems. The lifetime of any temporaries created in an expression is the lifetime of the full expression or statement, so as long as the reference is not used beyond the expression, the usage should work fine. It is somewhat risky, though, because the caller may not be aware of the reference propagation the function does, and the special rules for extension of temporary lifetimes don't generally apply when the reference is passed through an intermediary function.
Your examples involve modifying and returning a reference to non-const
lvalue instance. These types of uses, in general, will be harder to run into the pitfalls than references to const
or references to rvalues. A reference to non-const
lvalue can't be bound to a temporary (at least not without going through some hoops to trick the compiler), so you will generally have to pass an actual l-value (non-temporary) named variable (or other long-lived object) into them. When that reference is then passed out of the function as a return value, it will refer to whatever long-lived object was passed in. (You can still get into trouble if you don't properly manage lifetimes, of course, but at least the lifetimes we're talking about in this case are generally more than a single statement/expression.)
If you pass rvalue references through your function, and especially if they get translated to a non-const
lvalue somewhere down the expression tree (which is somewhat easy to do since the language, as a safety feature, decays rvalues into lvalues whenever they're bound to a name), the temporary nature of the reference can be lost and it is easier to accidentally bind the reference to a long-lived reference, which would outlive the temporary that it is bound to (which generally won't live beyond the statement/full-expression in which it is created). This is why I generally favor returning (and usually passing) r-values by value rather than by reference. Then, the compiler is more aware of the lifetime issues and the usages are generally more foolproof. In many cases, the compiler can elide the move constructions anyway, and when it can't, moves are generally cheap.