I've used many static checkers in the past, and the rate of false positives was high enough to dissuade me from using them. This is why D uses DFA to catch 100% of the positives with 0% negatives. I knew this could be done because the compilers were using DFA in the optimization pass.
In order to get the tracking to work, one cannot just track things for a function named "free". After all, a common thing to do is write one's own custom storage allocators, and the compiler won't know what they are. Hence, there has to be some mechanism to tell the compiler when a pointer parameter to a function is getting "consumed" by the caller, and when it is just "loaned" to the caller (hence the nomenclature of an Ownership/Borrowing system).
One of the difficulties to overcome with D in doing this is there are several complex semantic constructs that needed to be deconstructed into their component pointer operations. I noticed that Rust simplified this problem by simplifying the language :-)
But once done, it works, and works satisfyingly well.
Note that none of this is a criticism of what GCC 10 does, because the article gives insufficient detail to draw any informed conclusions. But I do see this as part of a general trend that people are sick and tired of memory safety bugs in programming languages, and it's good to see progress on all fronts here.