For a strict analysis, you can say "warn whenever a unique_ptr is dereferenced in any state other than unconsumed." A less strict version might say "only warn on dereference if it's in the consumed state." The less strict version will have a higher false negative rate, but a much lower false positive rate, especially for a widely-used type like unique_ptr.
These warnings seem like clear wins, and I’d definitely find them useful!
That's where things get tricky, because the C++ standard says that std::move must leave the object in a valid state. Some people rely on that behavior in their code, and routinely use null unique_ptrs, whereas some other people don't. So for a widely-used type, it's difficult to come up with a set of annotations that works for everyone. It's much easier if you're willing to create a strict_unique_ptr class (or something similar), that absolutely does not allow use-after-move.
A new class where everyone agrees on the allowed use-after-move behavior would be ideal, definitely. If we had annotations that people could use to mark their own custom classes as forbidding use-after-move, that would be enough to let people experiment with this in their own codebases, and if this approach got popular enough I imagine you’d find a class similar to strict_unique_ptr appearing in Boost or some other popular library soon enough.
So it sounds to me like so far, a refined proposal might have involve adding:
(1) Warnings about dereferencing a unique_ptr in any state other than unconsumed. (Or maybe the less strict version above, if this version has too high a false-positive rate.)
(2) A class annotation that tells the compiler to warn if objects of that class are touched at all in any state other than unconsumed.
Can we generalize (1) to an annotation that might be more broadly applicable? A straw-man annotation version of might be:
“(1) A class annotation that tells the compiler to warn if operator*, operator->, or operator is invoked on objects of that class in any state other than unconsumed.”
This seems applicable to e.g. shared_ptr as well.
I’d hope that the annotation version of (1) would be uncontroversial enough that it could be applied by default to smart pointer types in libc++. I’m not sure whether there are any types in the standard library that could get (2) by default without inconveniencing some users, but it doesn’t seem out of the question; std::unique_lock seems like a candidate.
Do these annotations sound like reasonable things to implement?