In C/C++, this can be done by just not using malloc() or new.
You can get an awfully long way in C with only stack variables (or even no variables, functional style). You can get a little bit further with variable length arrays, and alloca() added to the mix.
With C++, you have the choice of stack, or raw new/delete, or unique_ptr, or shared_ptr / reference counting. I think this "multi-paradigm" approach works pretty well, but of course its complicated, and lots of people mess it up.
I think, with well-designed C/C++, 90+% of things can be on the stack, and dynamic allocation can be very much the exception.
I've been switching back and forth across C/C++/Java for the past few months. The more I think about it, the more ridiculous/pathological the Java approach of every object dynamically allocated, impossible to create an object not on the heap seems.
I think the main problem is kind of a human one, that people see/learn about dynamic allocation/shared_ptr etc. and it becomes a hammer and everything looks like a nail, and they forget the prospect of just using stack variables, or more generally doing the simplest thing that will work.
Maybe some kind of language where doing dumb things is an error would be good. e.g., in C++ if you do new and delete in the same scope, it's an error because it could have been a stack variable, just like unreachable code is an error on Java.