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

    <tr>
        <th>Summary</th>
        <td>
            Thread-safety analysis confused by range-based for loop
        </td>
    </tr>

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

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

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

<pre>
    This bug was found by Chrome committers @mthiesse. Here's a fairly short snippet that demonstrates this bug: https://godbolt.org/z/xW9nbsW55

```
#include <map>
#include <cstdio>

#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#define EXCLUSIVE_LOCK_FUNCTION(...) \
 THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
#define UNLOCK_FUNCTION(...) \
 THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
 THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))

class [[clang::capability("mutex")]] LockType {
  public:
 [[clang::acquire_capability()]] void Acquire();
 [[clang::release_capability()]] void Release();
};

class SCOPED_LOCKABLE BasicAutoLock {
 public:
  explicit BasicAutoLock(LockType& lock) EXCLUSIVE_LOCK_FUNCTION(lock)
      : lock_(lock) {
    lock_.Acquire();
  }

  BasicAutoLock(const BasicAutoLock&) = delete;
  BasicAutoLock& operator=(const BasicAutoLock&) = delete;

  ~BasicAutoLock() UNLOCK_FUNCTION() {
 lock_.Release();
  }

 public:
  LockType& lock_;
};

class FakeMap {
 public:
  typedef std::map<int, int> EntryMap;

  LockType& GetLock() const LOCK_RETURNED(lock_) { return lock_; }

  EntryMap::iterator begin() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
    return entries_.begin();
 }

  EntryMap::iterator end() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
 return entries_.end();
  }

  EntryMap::const_iterator begin() const EXCLUSIVE_LOCKS_REQUIRED(lock_) {
    return entries_.begin();
 }

  EntryMap::const_iterator end() const EXCLUSIVE_LOCKS_REQUIRED(lock_) {
    return entries_.end();
 }


 private:
  mutable LockType lock_;
  EntryMap entries_ GUARDED_BY(lock_);
};

int main() {
    FakeMap map;
 map.GetLock().Acquire();
    for (const auto& pair : map) {
 puts("aasdf");
    }
    map.GetLock().Release();
    return 0;
}
```

The error from clang is:
```
<source>:70:27: error: calling function 'end' requires holding mutex '__range1.lock_' exclusively [-Werror,-Wthread-safety-precise]
    for (const auto& pair : map) {
                          ^
<source>:70:27: note: found near match 'map.lock_'
<source>:70:27: error: calling function 'begin' requires holding mutex '__range1.lock_' exclusively [-Werror,-Wthread-safety-precise]
    for (const auto& pair : map) {
 ^
<source>:70:27: note: found near match 'map.lock_'
2 errors generated.
Compiler returned: 1
```

Per @pbos, it seems like clang doesn't understand that the internal range object `__range1` is aliased to `map`.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV1tz4jwS_TXipSuUI2MIDzyY20xqM8ksIZPdJ5csN6CNbHklORvmYX_7lmRzM7nMrWo_ijLYkk_3Od2tlpgxYl0gjkg0JtG0wyq7UXr0HS1bVQW3QhWdVGXb0XIjDKTVGv7DDKxUVWSQbmGy0SpH4CrPhbWoDZBekNuNQGOwC59RI6EDAwxWTGi5BbNR2oIpRFmiBbthFjLMVWGsZhYN2MYMCWPYWFsaEsaEzgmdr1WWKmm7Sq8JnX8ndP7yOCxS8xhFJJiSIG6u_aD51rc0FAWXVYZAwknOShLOXhvhxmZCHQZ3UzJciQJh-Xkxi6dJfHt7t4yX13e3SbxcLq7HD8tZkhB69ULoEJKEWatFWln0D5vn7tuCm_1jcvNwf_1tltzcTf6WzB9uJw6U0Ktut-ugSDSp3_nQMr5wWRnxjIlU_CnZBY3QqyT5Fifx4tO9m_eaFw-3v229Kn7a6v3k7uts6onH45vZhyYMVyVmnh1LJb6C6FksZsuHxe1sugvGR7Deb4220gVmPxqp-2Qx-_vD9cKb-c1QmUTjvyuhvfUPVfv0EC-ms2ky_uePElxXTGeYJen2jJ2_csmMAV_2Yy5Z4UqOhDFnJUuFFHbrM5jmlcUXQql7O5qSaAo3ij8ttyUCGYwb5lBWqRTcIdQPzmAZ91yTFvwO81mJDOJ6TjMQjt_C0iiRmfexFvWcFhYZTA__j1Ro5-SYGcHjyirH9YhnmybgSykFF_b0DUKvdiIR2gfpHw3fqfpmxg7VfdwC6HP0MHwsONSD3Tc0A8f0iCacOcjdmtt-2vdWwilkKNHiEV57IqgSNbNKk3D6s2g7zP-2fXLzzxelU-Y17dfDe077LGDtuCQf5sacPeEXVr6XBXZbYoYrMDarM9T3mYkoLKETcD_hDGaF1dsvbqAlw7FLn9AeaVGr2l7emqzwokC9gu2pnMf9YNY5JmwdNUhxLYrGzDtr3LGtQ-o1RrGwWqBJukdgR2X7g55gkf2SH20n9jjvVcGpD17f5FVNaun_L8q0vDro84d8ekWolke7PNfimbm63TuaV9b14EMLOC2hA5O9tdPGtXPwnaIThYWc7eNwwmRXivlRFbmb7knZvLkmAqyUhv1qxSqrXM2VTGi_3DrYE5NlZU3dBRkz2arpgseAe-Hczbknby1T-6AEJ0q8uoH11-UGAbVWGlZa5eCbIQizD037pXBiVKU5ug1tGA8CEsZ04Dh6EPeHMylFsYbd1g0IHfjMGECzLzGwUTJzc_wewE1IEs2KNV52m0AOYL-nkVvXqC8eawN0cvFoNxpZdmHYCu32otTIhUHXo381HG9-SDT7iHehfCI3J5cCmYacWb5xrFzcdoR-S7-m2v-6Cv5xoWgtiIE1Fm69wqxbD0xUXgqJGvZb7DCGy3cy_Ctqd3YsU2V807RgEHMDUjxhk--ZQuPktVAVGWpjWZHVR0i7QddmURdMghcYVPov5BZIP9hJTvoBCANMCmYwA6vcoJOoH3Q72SjMhuGQdXB02b8Kg6gXBr3OZkSjPjKe8qAXDQYDfomr4RVlYTrkYcQpX3XEiAY0DKKAXg6DKOh1-xjyy6jHgmjFB_10RXoB5kzIrpTPuTu9doQxFY76tDccdCRLUZrd6VuP3KSLtFob0gukMNYcXrPCShwtj3MCWMHk1gjjesOqcrTSbS3ARepZugSRSpWdSstR60At7KZKu1zlhM6dlebnotTKaUfo3HtqCJ17Z_8XAAD__2SevtI">