<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - false positive with exclusive_locks_required in the presence of templates"
   href="https://bugs.llvm.org/show_bug.cgi?id=51368">51368</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>false positive with exclusive_locks_required in the presence of templates
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Frontend
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>tamird@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Reproduces with all clang versions tested (10, 11, 12, trunk):

```
class Status {
public:
  static Status OK;
};
namespace absl {
inline namespace a {
class __attribute__((lockable)) Mutex {};
class MutexLock {
public:
  MutexLock(Mutex *);
};
} // namespace a
} // namespace absl
class ServerContext;
template <class, class> class ServerReaderWriter;
namespace envoy {
namespace api {
namespace v2 {
class DiscoveryRequest;
class DiscoveryResponse;
} // namespace v2
} // namespace api
namespace service {
namespace discovery {
namespace v2 {
class AggregatedDiscoveryService {
public:
  class Service {
    virtual Status
    StreamAggregatedResources(ServerContext *,
                              ServerReaderWriter<api::v2::DiscoveryResponse,
                                                 api::v2::DiscoveryRequest> *);
  };
};
} // namespace v2
} // namespace discovery
} // namespace service
} // namespace envoy

namespace grpc {
namespace testing {
namespace {

class AdsServiceImpl {
public:
  AdsServiceImpl() : v2_rpc_service_(this) {}

  template <class RpcApi, class DiscoveryRequest, class DiscoveryResponse>
  class RpcService : public RpcApi::Service {
  public:
    using Stream = ServerReaderWriter<DiscoveryResponse, DiscoveryRequest>;

    RpcService(AdsServiceImpl *parent) : parent_(parent) {}

    Status StreamAggregatedResources(ServerContext *context,
                                     Stream *stream) override {
      (void)context;
      (void)stream;
      absl::MutexLock lock(&parent_->ads_mu_);
      ProcessRequest();
      return Status::OK;
    }

  private:
    void ProcessRequest()
        __attribute__((exclusive_locks_required(parent_->ads_mu_))) {
      parent_->ads_done_ = false;
    }

    AdsServiceImpl *parent_;
  };

  RpcService<::envoy::service::discovery::v2::AggregatedDiscoveryService,
             ::envoy::api::v2::DiscoveryRequest,
             ::envoy::api::v2::DiscoveryResponse>
      v2_rpc_service_;

  absl::Mutex ads_mu_;
  bool ads_done_ __attribute__((guarded_by(ads_mu_))) = false;
};
} // namespace
} // namespace testing
} // namespace grpc
```

produces the warning:

```
$ clang -Werror -Wthread-safety -c minimal.cc -o /dev/null
minimal.cc:67:16: error: writing variable 'ads_done_' requires holding mutex
'parent_->ads_mu_' exclusively [-Werror,-Wthread-safety-analysis]
      parent_->ads_done_ = false;
               ^
minimal.cc:60:7: note: in instantiation of member function
'grpc::testing::(anonymous
namespace)::AdsServiceImpl::RpcService<envoy::service::discovery::v2::AggregatedDiscoveryService,
envoy::api::v2::DiscoveryRequest,
envoy::api::v2::DiscoveryResponse>::ProcessRequest' requested here
      ProcessRequest();
      ^
minimal.cc:53:5: note: in instantiation of member function
'grpc::testing::(anonymous
namespace)::AdsServiceImpl::RpcService<envoy::service::discovery::v2::AggregatedDiscoveryService,
envoy::api::v2::DiscoveryRequest,
envoy::api::v2::DiscoveryResponse>::StreamAggregatedResources' requested here
    RpcService(AdsServiceImpl *parent) : parent_(parent) {}
    ^
minimal.cc:46:22: note: in instantiation of member function
'grpc::testing::(anonymous
namespace)::AdsServiceImpl::RpcService<envoy::service::discovery::v2::AggregatedDiscoveryService,
envoy::api::v2::DiscoveryRequest,
envoy::api::v2::DiscoveryResponse>::RpcService' requested here
  AdsServiceImpl() : v2_rpc_service_(this) {}
                     ^
1 error generated.
```

godbolt: <a href="https://godbolt.org/z/hG4h4dePG">https://godbolt.org/z/hG4h4dePG</a></pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>