IMO, the problem is not so much the inlining, but the sad state of the optimization passes losing track of many things and producing useless debug info.
IMO, the problem is not so much the inlining, but the sad state of the optimization passes losing track of many things and producing useless debug info.
Adding such debugging aids in your program may need some extra work, but it also functions in all cases when using the debugger is hopeless, e.g. for concurrent programs or other programs that depend on real-time interactions which prevent the use of breakpoints.
Of course I can always go back and add some logging, but it's not a given that I'll want to keep it around after the problem is fixed. For example if it's in a performance-critical section of code, even the cost of checking to see whether logging is enabled may be too great. And in any case every log statement does add visual noise to the code.
Bug reports have been filed, especially against MSVC, but they have been largely ignored over the years. AFAIK, MSVC is not open-source so improvements cannot be contributed either.
Yes, the debugger might have "forgot" the value of that function argument. So check a few other levels of the call stack that it was passed through. Or a local variable might be unavailable in a given line. So have breakpoints a bit before, or trace it into the next function call.
And when all else fails, you can go and look at the disassembly. Yes, calling conventions are stupid, instruction mnemonics are a hassle and register aliases are terrible, but even with rudimentary understanding you can generally figure out what's going on. If your code does a multiplication, look for the `mult`. If your code calls some external function, look for a `call`. Compilers can do cool things with your code, but computers are not magic - you can actually just look at what your CPU does, and it will strongly correlate with your code. As an added bonus, this helps you actually understand what code your compiler produces, which (if you reach for C++!) you probably should care about to some degree.
The only reason I have to care about debug builds is code coverage and/or iterator-checked runs, but that's something that can run overnight if it has to.
/rant
That said, under assumption you have a good code coverage with tests, and your code uses a lot of asserts to check pre- and post-conditions, debug builds can be useful for early detection of broken invariants.
I get that the development cycle is shortened through shorter compile times but that is simply the artifact of all optimizing compilers and not something which is exclusive to C++. And luckily this can be easily alleviated.
Expecting to have comparable runtime performance (which one is it?) in languages backed with optimizing compilers seem a bit delusional to me and even more so if you're in the realm of soft real-time systems.
I have spent, over the years, an amazing amount of time on trying to improve optimized-code debug info.
You could and should improve the optimization passes, but at various points in life they were actually very good. It is always a dance between advancing optimization and debug info, and i certainly will not claim that debug info is thought about as much as it should be - it is often fixed later, as i'm sure you expect.
But at the same time, what the author amounts to ends up reducing to the following:
1. The output executable is pretty well optimized
2. The output debug info is a recreation of the program as-written that can be executed by a debugger
3. The mapping between #2 and #1 has no holes.
IE #2 is basically "you've output the entire program using dwarf5 as a target processor".
This is never going to be a thing that regular users strive for, for lots of reasons. So if the game companies or whoever want this to be the case, they will actually have to contribute more than just bug reports - because it's not something that drives compiler usage for any language, whether it's C++ or anything else (IE it's hubris to believe that other languages won't end up the same way as they get better at optimizing. C++ just has a long head start)
At the same time I am sure that just one good compiler person paid for a year working on any of the compilers to improve optimized debug info would get to a really good place. I know - i was once paid to do it, and when i stopped, it was, back then, in a pretty darn good place compared to where we started[1].
Rather than throwing away every abstraction, it's hard to believe this entire industry can't afford this. Yet I have not seen them try before (perhaps they did after my time, but my time covered 20 years, and it didn't really happen during then)
So it is 100% reasonable to blame game developers or whoever as a group - because as a group, they aren't (again, AFAIK) doing anything about it other than writing blog posts about how the language is mean to them, and filing bugs that compilers are mean to them.
[1] I'll note, in practice, the most effective route over time is likely actually to just store enough info to do deoptimize during debugging as-needed, which is the path various VM based languages take and works well. The traditional path to doing this is to JIT the language along the way (which is totally possible for C++), but it's not strictly necessary to do it that way.
The harder part is the debugger/compiler cooperation, not the runtime mechanism.
If someone is interested in what's being done to improve LLVMs debuginfo, here's a talk by Djordje Todorovic from two years ago: https://www.youtube.com/watch?v=GpMLt1oecOk. It's about tracking dwarf locations for variables by keeping around information from the parent frame. According to that presentation, at least that work has been progressing.
There are people from that industry or adjacent industries writing other languages. Most obviously Jai (Jonathan Blow's language, Jonathan did "Braid" and "The Witness") but you could also argue for Ginger Bill's Odin. I suppose in this context it will be interesting to see whether the debug story is any better in these languages (neither is yet finished).
Person slightly doing things to LLVM checking in -- the three points you list are compelling, because it's always going to be difficult to describe one program (source) in terms of a vastly different (optimised) program. Do you think there's mileage in showing the developer a partially optimised program [0] instead of trying to perfectly describe the source? It'd be easier to describe in debug-info, and possibly easier for developers to identify unexpected changes to the code they wrote.
[0] "Non-Transparent Debugging of Optimized Code", 1999
This is apparent in C++ when you look at the optimized output on Compiler Explorer: it attempts to color assembly based on the source lines, and some source lines get strewn about the resulting assembly.
JVMs move heaven and Earth to make optimization not observable and support the JVMTI, upon which debuggers are built. They are required to materialize a bytecode-level view of execution state upon demand, just as CPUs are required to materialize a machine-level view of execution state. As a result, any source debugger written against what is available at the bytecode level will work without needing to see through the abstractions.