Boost logo

Boost :

Subject: Re: [boost] [outcome] To variant, or not to variant?
From: Peter Dimov (lists_at_[hidden])
Date: 2017-06-03 09:42:39


Vicente J. Botet Escriba wrote:

> Peter, I not be against an implementation that returns nullptr of
> operator-> as far as this is not documented and something the user could
> use.
> If returning a nulptr is the best thing that we can do today in order to
> help the current tools to catch UB, why not.
> I don't agree on documenting it, because this could make some user code
> more complex.
> When you have a narrow contract you know that the check must be done
> before. If you document that it the user can be tempted to check it.

The expression `r->x` still has a narrow contract under my formulation. You
(and the static analyzer) still know that a check needs to be done. It's
just specified differently because the real world consequences of this
specification are more in line with the semantics I want to express.

> Well operator-> is particular in some way as the user doesn't use to use
> it as x.operator->().

Yes, `r.operator->()` is now defined, which some consider desirable.
Presumably, if one writes `auto* p = r.operator->();`, one is aware of what
one's doing. I wouldn't presume that this code is a logic error without a
check, and neither should a static analyzer.

> Consider for a moment that some compiler manage better UB when we do a
> check and assert for unreachable code (as other are suggesting). Requiring
> a nullptr as result will forbid this implementation, isn't it?

No, it doesn't. This formulation just lifts the undefined behavior in `r->x`
from the library into user code, and what happens there depends on the
compiler. g++ takes care to trap on null pointer access, clang++ optimizes
out the checks under the assumption that null pointer accesses don't occur.
The balance here is hard to strike, because there are security implications
of just allowing `p->m = ...` to write over the error; at the same time,
there's an argument to be made to optimize correct programs more at the
expense of incorrect programs. The main feature of my formulation here is
that `r->x` and `p->x` (where p is a raw pointer) elicit a consistent
response from the compiler when they invoke UB, and are therefore covered by
the same optimization decisions or command line switches.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk