0

I am trying to get Negative Capabilities working, as described in the link. I have the following code, which is based on the example in the link provided. (I changed their example mutex, Mutex, which they never define, to std::mutex, which has all the required annotations for the other threading safety checks to work.)

#include <mutex>

#define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))

#define EXCLUDES(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
#define REQUIRES(...) \
  THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))

class Foo {
  std::mutex mu;

  void foo() {
    mu.lock();
    bar();           
    baz();           
    mu.unlock();
  }

  void bar() {       
    mu.lock();
    // ...
    mu.unlock();
  }

  void baz() {
    bif();           
  }

  void bif() REQUIRES(!mu);
};

I expect this to warn me of not using REQUIRES(!mu) in all the places required. Instead, I get a syntax error:

<source>:30:23: error: invalid argument type 'std::mutex' to unary expression
   30 |   void bif() REQUIRES(!mu);
      |                       ^~~
1 error generated.
Compiler returned: 1

Which seems to suggest the compiler is not even able to parse this correctly. I have tried other (larger) examples, from a real project, and they correctly warn that I should use negative capabilities, but display the same syntax error as here when I actually try to write REQUIRES(!mu).

I have tried with multiple versions of clang, using the -Wthread-safety-negative flag as described in the documentation. (Notably, 20.1.0 and trunk, from compiler explorer.)

19
  • Check mutex.h. You need an annotated interface for mutexes too. Commented Jun 3 at 20:16
  • 1
    the code you posted is not the same as in the linked article. They use Mutex while you use std::mutex Commented Jun 3 at 20:23
  • @TedLyngmo, should have mentioned in the question, the header has the required annotations (at least for all the other threading annotations to work). If there are extra annotations I need for the negative capabilities specifically, maybe I'm missing those, but it wasn't mentioned in the docs. Commented Jun 3 at 20:23
  • 1
    @TedLyngmo I see, thank you. That answers my question then. I wish this was explicitly mentioned somewhere in the document though Commented Jun 3 at 20:30
  • 1
    @TedLyngmo If you want to write that in an answer, I'll accept it, otherwise I'll write it up myself for future reference Commented Jun 3 at 20:41

1 Answer 1

1

In order for REQUIRES(!mu) to work properly, you need to add an overload of operator!, for example this one from mutex.h :

  // For negative capabilities.
  const Mutex& operator!() const { return *this; }

The negative capabilities won't compile without this, and some lock implementations (such as std::mutex) do not provide this overload currently.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.