<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/123512>123512</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            clang thread safety analysis does not take into account assert_exclusive_lock attribute
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          krinkinmu
      </td>
    </tr>
</table>

<pre>
    It seems like clang version 18 (specifically I tested it on 18.1.8) fails to take into account `assert_exclusive_lock`/`assert_capability` annotations.

Here is a minimal example I came up with that reproduces the issue for me:

```c++
#define GUARDED_BY(x) __attribute__((guarded_by(x)))
#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
#define LOCKABLE __attribute__((lockable))
#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))

struct LOCKABLE Lock {
  void lock() EXCLUSIVE_LOCK_FUNCTION() {}
  void unlock() UNLOCK_FUNCTION() {}
  void assert() ASSERT_EXCLUSIVE_LOCK(this) {}
};

struct ComplexValue {
};

struct Parent {
  Lock lock;
};

struct Child {
  Child(Parent& p) : p(p) {}
  const ComplexValue& value() ASSERT_EXCLUSIVE_LOCK(p.lock) {
    p.lock.assert();
 return data;
  }

  Parent &p;
  ComplexValue data GUARDED_BY(p.lock);
};
```

When compiling this code with the following command:

```shell
clang++-18 -c -Wthread-safety -Wthread-safety-reference-return -Werror -std=c++20 test.cc
```

I get an error:

```
test.cc:25:12: error: returning variable 'data' by reference requires holding mutex 'p.lock' [-Werror,-Wthread-safety-reference-return]
 25 |     return data;
      |            ^
1 error generated.
```

I understand that returning a reference to a protected variable in general might be incorrect, but in this case before returning the reference I call a function with `assert_exclusive_lock` annotation, so by the time we get to the return statement, clang should be able to figure out that the lock is being held.

Naturally, replacing `assert_exclusive_lock` with `exclusive_locks_required` attribute eliminates the warning. However, in more complex cases it might be hard for clang to figure out what locks are held in what contexts, so I want to help clang with putting asserts like this to let clang know that the lock is actually held, but it does not seem that clang takes those into account or derives anything from `exclusive_locks_required`, which seems wrong.

Is my understanding of the purpose of `exclusive_locks_required` annotation somehow incorrect?
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyUVs1y6joSfhqx6YIycszPgoVD4F5qUrkzyc05MyuXLLexBlnySDKEt5-SbEhISHIORSXG6r_v61Z3M2vFViEuSHJLkrsBa12lzWJnhNoJVbeDXBfHxcaBRawtSLFD4JKpLezRWKEVjGdA6Mw2yEUpOJPyCBtwaB0WIBwEidF4NCN0DiUT0oLT4NgOQSingXGuW-WATCJmLRqX4QuXrRV7zKTmOzKJCF2_nnLWsFxI4Y5kEgFTSjvmhFZ2RKKUROmfaBCEBQa1UKJmEvCF1Y1E2ABnNULbwEG4ClzFHBhsjC5ajhZc5fVsi1BqAzWSOO0s-gjClxN6679RSmhcYCkUwh_P6ePd6i67_Q-hsxePMcuYc0bkrcMsI3RG6GzbMlNgkeXHXqj_vjW0-vfy_vlp82OV3f-1_MdT9rj61_PmcXVH6Gw0Gn1i-JIqmxn8XysMFoTOsuxHmqWPfzx52WsOvZv09n51za63xnKJ38aZrZ8fln9v_nr4jTCzslXcp-xXonx--HU3rfpt8-nT0-rx7-wS1JdOrhfp566i1DrTcvfK973mOyBTX0cAey0K6E14j5_T60-91vTuVbFD3B9-pOqaShd_f_gZfFcJe6Hs_8a3F3iW2t-qlx9MttjDuSL1T2bQ3-4ebsAeYo4_UVhWQhZn-fCL0FlnhtAJNCGuOPUPs-YdQq6VvYzMq-y7hy8RN6OOyfnZNUD3bvSWsS5aMOhao6BgjvVvoOfJP54w00lzOr0gy6tdNo6z9_e0nFpPZ_pnhQq4rhshhdqCzxJwXeCpofnWJaU--EOu65qp4mMXsxVKSaI0dPGuow3HMxhyGP50lUFWDC0r0R3f_x4aLNGg4jjs8Q9_ojHawNC6gsR3fX-kUWj_I84_ItjAFh0wBUHxY3AkSk-6cUoTEqdj6pN9Eu-Z9wD3zAjfo4DQaUgEnUJ-hHOQ0DdDC5WWhdeoW4cvXvxE9xRIctuDIHT5HV6ShCqjCZDp0hfItTrwn9Nx_yHJikTpuAMBW1RomMNidI2eVhVorGOqOA2oE172Bpqfm9AY7ZD7MXumQqjevIRabCsHuX_HtTHIHaFLyFvnhbrKYRYhx1IbfOPGV9GrIz8zpQQGp6baldoXw_rNSPYOrfZJ8UadqBEOGArAbwDVyStYxxzW4X4v--XCVrqVhQ8_4HIaSrFtDYJuXUeM1_cu_azP0UdeoSz6JeCBudb4VcRbNNhIxr3EV2GfcH06Uj200zAAlKIWirl-bziwQN4I_tQH3KMvJk9z7anl3dUPdFu_EZ0zUzFThGWjw3wJ8uBBhhCAGQzgvMnwmmvl8MXZnuANHJgKpFYom95awNO0zoXaCaj79S0k32mQ6HrZndKHj6wy7tqwznnf5-JxUGi0oHS3EnZqPQC2C3xo-2630wYKNGKPFpg6usqHVBpdf8O393moBK_65fNgtNr2Gd5YqI9vbos3qcsQf9Oaxoegy2_zeS5VsLrGSh_e3JZ4PSgWcTGP52yAi_E0ntJ5MqHxoFqweRknvJxPkpsJi_Mymc8nN3GZzOZ0nOdYDsSCRjSJxuP5-CaaRvFoNmMFljOWjPEmSZCRmwhrJuRIyn090mY7CKvnYkzjZEwHkuUo7WknNwsvNczbrSU3kRTW2Vc9J5zERZ-A0L6gb99MMXm0wr4m7OPWffU6vNb5oDVyUTnXWN-q6ZrQ9Va4qs1HXNeErn0U_b9hY_R_Q5dZByiW0HWPZr-g_w8AAP__KBICSw">