On Sat, Apr 25, 2020 at 7:12 AM Niall Douglas via SG12 <sg12@lists.isocpp.org> wrote:
I will apologise in advance Miguel if the following comes across as
patronising. However I think it would aid you in writing in the
appropriate terminology in the next revision of P1315. I'll also
apologise to Core now, for the likely many mistakes I am about to make
in describing the abstract machine.
Your friends in Core look forward to having you join us in mediating upon the wording in session **insert soundtrack here** :)

What 95% of C and C++ programmers write code for is the concrete
machine. In the concrete machine, all object representations have a well
defined bit layout. Zapping the bits of an object representation to zero
eliminates the value of that object. This is what you want in your
paper. This is what memset_s() does.
Hopefully that's what memset_s does for some version of the object. The wording for it is, as you said later in your note, rather handwavy.
This is very straightforward on 99%
of compilers out there to implement.
As long as the user is happy with clearing only some version of the object.

The problem is how to codify the same operation into the abstract
machine: in C++, there are two kinds of object, one is C-ish which is
treated as a bunch of bits, and the other is C++-ish, and is not treated
as a bunch of bits. Only the former has any notion of being "clearable",
because you cannot treat the latter as bits to be cleared without UB.
The paper does have is_trivially_copyable_v<T> in the constraints for the "C++" interface. Although, the paper should probably suggest why users either should not want to clear non-trivially-copyable types or suggest how (perhaps with an array that provides storage) to clear types that are not trivially copyable. The paper should probably also make some mention of whether there are meaningful semantics for the function in constant expression evaluation (such as causing the lifetime of all objects that are pointer interconvertible with the object designated by the argument to end).
[ ... ]
The idea behind my ensure_stores() proposal was a bit of a hack: it is
an intrinsic to tell the compiler "assume stores to this region have
escaped". All compilers already implement this intrinsic, it is better
known as "calling an extern function", so implementation is trivially
easy, and the reference implementation library for ensure_stores() is
literally calling an extern function which the compiler can never Link
Time Optimise. ensure_stores() is effectively a "fsync()" for the
compiler, forcing it to write out the current bit representation to the
escaped region now. The big advantage of this is that the compiler is
free to optimise maximally before ensure_stores(), so performance is
way, way better than volatile.
@Herring, Davis, I thought you had tried to do work in this area in relation to contracts. If I recall correctly, this was around the San Diego meeting.

[off-topic note] Someone recently said that our naming of Wikis by venue is unhelpful. Yet, I find that it tends to be easier to recall conversations from meetings based on the scenery outside the window, the weather, or the cuisine...
[ ... ]
There is no problem, in theory, with marking all clear-on-delete objects
as volatile. However, in a concrete machine, that leads to dire
performance. So what we really need here are "constrained volatile
object optimisation", specifically:

- Dead store elimination is permitted, except at certain "fsync moments"

- Write combining is permitted, except at certain "fsync moments"

- Write and read reordering is permitted, except at certain "fsync moments"

I have no idea how to phrase that in a wording acceptable to Core. But
that seems to be the only remaining path forwards which nobody has
attempted yet.
I'm not sure that nobody has attempt this yet, but I'm not sure where those attempts went.

I wish you good luck in your endeavours, and for the record, thank you
for investing your effort to date as this is a problem which is holding
up a ton of other stuff, far far wider than bit clearing (think shared
memory, object serialisation to mapped memory, etc).
... statement attributes for breakpoints and some interpretations of what contracts should do in the vicinity of the check or of the handler.