Yeah, it wouldn’t be trivial. But FWIW, we’re currently vulnerable to the pattern you described, we just don’t have any checks for it.
Many of our “global” locks are actually contained to a single compilation unit. As you mentioned, those can safely be easily fixed by hiding them in a class and instantiating a static instance of the class instead.
Also, the negative warnings don’t apply to mutexes marked as re-entrant, so the nastiest ones (looking at you, cs_main) would still be exempt.
I have a patch for clang that adds an ASSUMES annotation for capabilities that means “assume I was unlocked at this point (trust me, bro), but enforce checks from here down”. The intended use-case was helping with migration away from nasty recursive mutexes (ala cs_main), but I’m realizing it’d be helpful in this case too. I should really get that upstreamed.
Several of the globals get in the way and are part of my todo list for my net refactor anyway. I didn’t mean to imply that we could turn on -Wthread-safety-negative any time soon, only that it would be a nice-to-have in the future.