Is there a compiler warning for breaking deep const?

Does clang have a compiler warning for when code could be breaking deep const-ness? I know this is legal in C++, but it is often undesirable, especially in light of const now implying thread safety in most libraries. We just chased a thread safety bug down to a problem like the following:

struct Foo
{
  void DoSomething();
};

class Bar
{
  Foo *foo;
  void DoConstSomething() const { foo->DoSomething(); }
};

If clang doesn't have this warning, it would be extremely useful to have as we migrate to a concurrent world. I would propose that to work around the warning the user could do one of the two following things:

class Bar
{
  mutable Foo *foo;
// OR the following const_cast
  void DoConstSomething() const { const_cast<Foo *>(foo)->DoSomething(); }
};

What makes this even trickier is that the std smart pointer classes allow you to do the same thing. I don't know if clang could also warn about these as well, but having the former would be a good first step in the right direction.

Thanks,
Brian

Does clang have a compiler warning for when code could be breaking deep
const-ness?

Nope.

I know this is legal in C++, but it is often undesirable, especially in
light of const now implying thread safety in most libraries.

Even in the latter case it's hard to know which parts of an object are part
of its identity. Unless there are some particularly accurate heuristics we
could use to guess whether an object is part of the object identity of some
other object I doubt we could add such a warning.

We just chased a thread safety bug down to a problem like the following:

struct Foo
{
  void DoSomething();
};

class Bar
{
  Foo *foo;
  void DoConstSomething() const { foo->DoSomething(); }
};

If clang doesn't have this warning, it would be extremely useful to have
as we migrate to a concurrent world. I would propose that to work around
the warning the user could do one of the two following things:

class Bar
{
  mutable Foo *foo;

Except this has another meaning - it means that 'foo' is changeable under
'const', not that the thing foo points to is/isn't.

// OR the following const_cast
  void DoConstSomething() const { const_cast<Foo *>(foo)->DoSomething(); }
};

What makes this even trickier is that the std smart pointer classes allow
you to do the same thing. I don't know if clang could also warn about these
as well, but having the former would be a good first step in the right
direction.

At least with std::unique_ptr you know the object isn't shared so the
chance that it forms part of the object identity of the enclosing object is
a bit higher, but probably still not good enough I'd wager.

I've seen people attempt to solve this with a library solution:

deep_const_ptr<T> x;

where op* and op-> return const/non-const references as appropriate.

This is probably more likely to be the way to solve your problem - along
with some kind of stylistic guideline in your codebase that members that
are pointers to portions of the value of an object should use this wrapper
(& that way you can see when you read the code which members are part of
the object identity and which ones are not)