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

    <tr>
        <th>Summary</th>
        <td>
            Thread safety analysis treats non-const method calls as reads
        </td>
    </tr>

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

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

    <tr>
      <th>Reporter</th>
      <td>
          ilya-biryukov
      </td>
    </tr>
</table>

<pre>
    The thread safety analysis can distinguish between reads and writes to variables of simple types, but falls short when the write happens through a method call (see https://gcc.godbolt.org/z/8dffM6j1e and the code below).
It seems to treat all method calls as reads and never as writes. This is a conservative approach that avoids false positives.
However, it would be useful to have a mode that treat all non-const method calls as writes and const method calls as reads (similarly, passing an object through a const reference is a read and through a reference as a write?). E.g. this would allow to catch things like `vector.push_back()` made under a read lock.

Has this been discussed before?
Should we consider adding a new warning flag to enable this class of warnings? (basically treats capture-by-reference as a write and capture-by-const-reference as a read)

```cpp
struct __attribute__((lockable)) mutex {};

struct __attribute__((scoped_lockable)) lock_guard {
    lock_guard(mutex& mu) __attribute__((exclusive_lock_function(mu)));
    ~lock_guard() __attribute__((unlock_function));
};

struct __attribute__((scoped_lockable)) shared_lock_guard {
 shared_lock_guard(mutex& mu) __attribute__((shared_lock_function(mu)));
 ~shared_lock_guard() __attribute__((unlock_function));
};

// Wraps an int.
struct value {
    int get() const;
    void set(int);
};


struct Test {
    mutable mutex mu;
 value val __attribute__((guarded_by(mu)));
    int num __attribute__((guarded_by(mu)));

    void accidental_write_under_shared_lock() {
        shared_lock_guard l(mu);
        num = 10; // ok, warning.
        val.set(10); // no warning, but it would be nice to have one.
    }
};

```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysVk9v47YS_zT0ZRBBphL_OfiweXnGe4eeGqBHg6LGEjcUKXBIed3DfvZiKGcjJ063aBsYCCwPf_9mRFIRmdYh7sTDo3h4WqgUOx92xp7VXW3COb34cVH75rx77hBiF1A1QOqI8QzKKXsmQ6CVg8ZQNK5NhjqoMZ4QHXAxgXINnIKJSBA9jCoYVVsk8Ecg0w8WIZ4HJCH_A3WKcFTWElDnQ4RThw5ih9N66NQwoCOW4VPbgYIeY-cb0MpaEHJDiNDFOJCovgi5F3Lfal20vqm9jYUPrZD734Xcb5rj8ZfV1yVmcUygfYNQo_UnIbeFKJ9E-eX_EQixz7JjQBWBaWaUBIpmJh2OGPjR5LaA584QGAIF2jvCMKpoRgQ1DMEr3UHsGHP0piG2TQiDJ8M1dJHwP39iUM7GRDj5ZBuoERLhMVnW1SkGhJ7lZ7g3oc67O-aNHyRfusGabxdMnjhQ0xurgj2zgoGHxbWgHPj6K-o4a8SEE_CIAZ3GyXUelinh17q3CsUVWYmo9hw6_LdoC4ic2WRUWetPbFKrmNMyriWw5gVBrMoRdfShGBJ1h1rpFyE3Qm7FqoReNQjJNdyMSYP1-uWS6CVXRRNTzXPaGNKJCDnbow9ZUC77tctCTpj9mYzYNDkDcHiCkwqOvx2talkoOh7tCVlbRXnIL0Ukqj1HWisyHPR5ahW_PUNMAe_q892tdKY2vdXkpN9Xskt2P7MoVuX00cMwPaEYko5wOKgYg6lTxMMhp7bhfFg5Q8gt9CniNxDrR7F-EtXjHPVzDNJ-wObwDoq_HtqkQpPxMgYAzJ4Lucl8Qq6gT7zmBjh-0zaRGTHjH47J6Wi8y2snJv5UM4LvVwyfwCb3Du4K5p-7p06Fy9MPIXz47S8FMV_1sxS-36L4l5KYdlf4LaiBNxIwLhZXGY3KJrzuuXERWowXEXmOr1rGGyFQLjAu_oR_zvWMFK-p-hTzmzhNcp_eeCZdo7K3UsghYXOoz38yWWzDpf5vrX9nVmltGnRR2UN-1w951zrM-nYJ68oc_32cLPuDsnpXy2JF9QTLUlSPcOmcf-Et_bI3FdcLRmWLqQ_LcgJ8XeX865LX43p-LDmj8ceh5B3OYLmDn7XydaNaNLuq2VZbtcDdci3LslxWq2rR7bb3m6aqq4dqVddS6lWpV2WzPi5LVa82a9wuzE6W8r5cl9WyLLeyKlabeyW3NT5U6riuZCnuS-yVsYW1Y88XgYUhSrjbrh8eyoVVNVrKVyAptVXsTvJtKOy4_q5OLYn70hqK9IYQTbS4e759Jbrs7Z-fwfmIXaRgd-8uLCZ2qS6074XcM9fl390QPJ-5Qu6zdBJyP6kfd_KPAAAA__9tuiQS">