You are making assumptions here about compilers
that are probably incorrect. If I implement a function
where type is some aggregate structure,
my GNU C (and C++) compiler will emit
virtually the same code as it would for
type* f(type*, ...)
I have actually implement functions
that return by value this way
in a separate translation unit.
The link editor resolves the reference without complaint
and the program executes as expected. Try it yourself.
If f(...) is used in an expression,
the compiler emits code to
1. allocate a temporary object of type type
from automatic storage (the program stack),
2. calls f with a pointer to the temporary object
prepended to the argument list and
3. deallocate storage for the temporary object
after the expression has executed.
In a C++ program, the constructor allocates
storage from the free store if necessary
and the destructor deallocates any such storage
when the temporary object is destroyed.
This is all done "behind the scenes"
as far as the application programmer is concerned.