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

    <tr>
        <th>Summary</th>
        <td>
            Thread safety/capability analysis behavioral difference between member and free function
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang:frontend,
            clang:analysis
      </td>
    </tr>

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

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

<pre>
    The following code emits unexpected diagnostics about the capability expecting to be held or still being held within the `*_permission` functions:
```
#if __has_cpp_attribute(clang::capability)
#define CAPABILITY(Name) [[clang::capability(Name)]]
#define ACQUIRE(Cap) [[clang::acquire_capability(Cap)]]
#define RELEASE(Cap) [[clang::release_capability(Cap)]]
#define REQUIRE(Cap) [[clang::requires_capability(Cap)]]
#else
#define CAPABILITY(Name)
#define ACQUIRE(Cap)
#define RELEASE(Cap)
#define REQUIRE(Cap)
#endif

struct CAPABILITY("special permission") SpecialPerms {
} SpecialPermissions;

ACQUIRE(SpecialPermissions) void give_me_permission() {}
RELEASE(SpecialPermissions) void revoke_my_permission() {}

REQUIRE(SpecialPermissions) void func() {}

void good_call() {
 give_me_permission();
  func();
 revoke_my_permission();
}
```
https://godbolt.org/z/d8Ezhsn88

But with a tweak to using member functions instead, no diagnostics are issued:
```
#if __has_cpp_attribute(clang::capability)
#define CAPABILITY(Name) [[clang::capability(Name)]]
#define ACQUIRE(Cap) [[clang::acquire_capability(Cap)]]
#define RELEASE(Cap) [[clang::release_capability(Cap)]]
#define REQUIRE(Cap) [[clang::requires_capability(Cap)]]
#else
#define CAPABILITY(Name)
#define ACQUIRE(Cap)
#define RELEASE(Cap)
#define REQUIRE(Cap)
#endif

struct CAPABILITY("special permission") SpecialPerms {
  ACQUIRE() void give_me_permission() {}
  RELEASE() void revoke_my_permission() {}
} SpecialPermissions;

REQUIRE(SpecialPermissions) void func() {}

void good_call() {
  SpecialPermissions.give_me_permission();
  func();
 SpecialPermissions.revoke_my_permission();
}
```
https://godbolt.org/z/Eoh8xKnje

Am I holding it wrong in the free function example or is this an issue with the analysis?
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzslkGPozgThn-NcylNBAYSOHAg6URqfaNPszO9hz0hg4vgGWOztkm659evDOkJvUqnp6Wd20hIQbjq9VsV-1Exa8VBIeYk2ZDkbsEG12qTF8xotWFSdkwtKs2f8ocWodFS6pNQB6g1R8BOOAuDwscea4ccuGAHpa0TtQVW6cGBaxFq1rNKSOGeYIr0Ak5DhdCi5KANWCekhAr9yvjtJFwr1JhOVgGhRdmj6YS1QiuyCqAZVO2EVpZEBQkKHzM9QUFoJBooy5bZsu77kjlnRDU4JDStJVMHnxIVF1eEZlMax0YohG3xqdjcf7x_-IvQ9P-sQ0IzGNuzeSX_OYokd_6ZixXbP_68_7wjNN2y_qoQq_8ehMHyheAUfEXv8-7jrvhyS8-gRGZ_Xu8tfwZHf_YtQZQW3-zjzd7cLPSm67MDxUXjX4PCOjPU7qUFQqntsRZMwuwwUeqr_jItfELTWSDrjVdZ380_T-GWRJtph4v5K0E0g6MWHA7iiGWH88PrfWTjFmvfuEuZN2QMHvU3LLunG0Kj1k9Y8jfnSu5kV2te1kzKWUBQvFrF1AuYSZ6_vO733L5p19mlbZ3rx7tM94TuD5pXWrqlNgdC998J3fN09721Kk0nt5vBjYgABu6E7JvHyWA9PTrsKjQXPoBQ1iHjhG5B6ZeEMgjC2gH5b4j8hsivgQjM_L2DCjBz_j4K3IbWryLElT2X76bGFY3_HiQ73aaP_1Nf8UzxDu6h1ZJ7dggHJ6P9yzR5NAbxB0kAH1nXS_TjirDgWmGBqQkgE4t8ClNMPllhSbRf8DziWZSxBebhOl7TmGZxtmjzJsjCJI7TJG3CFWZhtlqnPEjipAlrVq_pQuQ0oEmQhHG4DpM4W6YYhZQlKY1WNK4xInGAHRNyKeWx88UtRht5GGVZFC0kq1DacaKj9PkSNkYrh4qPZ3U7W_hhmVI_AJrci36ohoMlcSCFdfayjRNOYv7QGmQcLGvQX-P9bMB7FoMKW3YU2jAJXDQNGlQ1QoXuhKieKc0Uf9nkxWBk_q-_ULh2qJa17gjdeyPnnw-90V-xdoTux-Itoftz_cec_hMAAP__raRcVQ">