Strange "release_shared_capability" behavior in Clang thread safety analysis

While experimenting with Clang’s thread safety analysis (http://clang.llvm.org/docs/ThreadSafetyAnalysis.html) I ran into a compiler warning I didn’t understand. It seems that the release_shared_capability attribute is not doing what I expect. The code to reproduce is below:

// Begin file: getvalue.cc
// Fake mutex class.

class attribute((capability(“mutex”))) mutex {
public:
void SharedLock() attribute((acquire_shared_capability())) {
// Do nothing for this fake mutex.
}
void SharedUnlock() attribute((release_shared_capability())) {
// Do nothing for this fake mutex.
}
};

// Scoped lock class to do RAII locking for the fake mutex class above.
class attribute((scoped_lockable)) mutex_lock {
public:
mutex_lock(mutex *Mutex) attribute((acquire_shared_capability(Mutex)))
: Mutex(Mutex) {
Mutex->SharedLock();
}
~mutex_lock() attribute((release_shared_capability())) {
Mutex->SharedUnlock();
}

private:
mutex *Mutex;
};

// Global mutex and a corresponding value for it to protect.
mutex Mutex;
int Value attribute((guarded_by(Mutex))) = 42;

// Explicitly lock and unlock the mutex to read the value.
int getValueExplicitUnlock() {
Mutex.SharedLock();
int LocalValue = Value;
Mutex.SharedUnlock();
return LocalValue;
}

// Use the scoped lock class to lock and unlock the mutex.
// This is where the problem happens.
int getValueScopedLock() {
mutex_lock Lock(&Mutex);
return Value;
}

// End file: getvalue.cc

Compiling with tip-of-tree clang with the -Wthread-safety flag, I get the following warning:

Begin shell session

$ clang++ -Wthread-safety -c getvalue.cc
getvalue.cc:37:10: warning: releasing mutex ‘Lock’ using shared access, expected exclusive access
[-Wthread-safety-analysis]
return Value;
^
1 warning generated.

End shell session

So there is a problem with my scoped lock in the getValueScopedLock function, but there is no problem with the explicit locking and unlocking in my getValueExplicitUnlock function.

The warning goes away if I switch the annotation on the ~mutex_lock destructor to “release_capability” instead of “release_shared_capability”. Is this the expected behavior? It seems like an “acquire_shared_capability” should be paired with a “release_shared_capability”.

I also found a stack overflow question where someone else ran into this problem: http://stackoverflow.com/questions/33608378/clang-thread-safety-annotation-and-shared-capabilities

For reference, this is Thread Safety Analysis [-Wthread-safety-analysis] work wrong with shared lock · Issue #32851 · llvm/llvm-project · GitHub, which I closed as invalid because I think it was intended to work like this. This is also documented now.