C++ Logo

sg12

Advanced search

Re: [ub] Proposal: make self-initialized references ill-formed (C++17?)

From: David Krauss <david_work_at_[hidden]>
Date: Fri, 26 Sep 2014 11:45:10 +0800
On 2014–09–25, at 4:52 AM, Richard Smith <richardsmith_at_[hidden]> wrote:

> Then I'm strongly opposed. It does not seem acceptable to silently change existing valid and well-defined code into having undefined behavior. I'm sure I'm not the only one who'll feel this way.

True, nobody gains anything from the possibility of non-diagnosis and a crash-on-run executable. But that’s not in practice going to happen except as a result, as you put it, of the compiler doing nothing special in particular. If the implementation notices the out-of-thin-air result at all, that suggests the existence of some exception handling which provides an opportunity for diagnosis.

Perhaps there should be some specification like static UB diagnosis, where a particular expression is ill-formed/NDR but behavior is well-defined if it is neither diagnosed nor evaluated. The current wording of [dcl.init.ref] 8.5.3/1 actually comes pretty close:

> A variable declared to be a T& or T&&, that is, “reference to type T” (8.3.2), shall be initialized by an object, or function, of type T or by an object that can be converted into a T.


This is a “shall be” requirement applied to a runtime occurrence. Although, it perhaps intends only to constrain the type of an initializer expression.

Does portability suffer from NDR? Sure. But the main suggestion here is to weed out nonsense with a new diagnosis. If some customer can’t live with a hard error, issuing a warning and producing an executable also satisfies NDR.

Non-diagnosis and UB right at static initialization is the status quo for Clang and GCC, given this declaration sequence which portably specifies a defective product:

extern int & a;
int & b = a;
int & a = b;

The only other way I know to get circular reference initialization is in a constructor, between two member references, which Clang does diagnose by default as use of an uninitialized variable. GCC’s -Wuninitialized is also an area of active development.

On the other hand, there are ways to use a reference in its own initializer which are not unreasonable:

std::function< void( int ) > && f
    = [&] ( int cnt ) { if ( cnt ) f( -- cnt ); };

Stronger analysis might be better when it comes to checking initialization.


Received on 2014-09-26 05:45:22