<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">