[dmd-internals] Errors emitted by the optimizer and the as-if rule
k.hara.pg at gmail.com
Sat Aug 18 11:38:53 PDT 2012
2012/8/19 David Nadlinger <code at klickverbot.at>:
> Kenji's fix for issue 8339 introduces code which accesses a
> void-initialized variable without setting it first:
> I'm aware that it is contained inside an is(typeof()) check, and it
> seems like a clever solution to work around the underlying issue.
> However, DMD, with the optimizer enabled, would actually refuse to
> compile the code (even if a __traits(compiles, …) check returned
> true!), because access of uninitialized data is detected during data
> flow analysis somewhere in the optimizer, producing a "variable used
> before set"-type error.
> My point, which is only tangentially related to the bug fix in
> question, is that the optimizer in DMD grossly violates the "as-if"
> rule by changing the definition of what is legal D code. For example,
> the spec  says that accessing an uninitialized value results in
> undefined behavior. To me, this implies that code like this is fine if
> it is never executed. Yet, DMD for example refuses to compile a
> function which contains such an access of uninitialized data (or a
> null pointer dereference, …), even if that function is never invoked.
> In my opinion, this is clearly a bug. We can chose to either make
> accessing uninitialized data illegal – but the semantics of this are
> difficult to define in the general case due to the requirement of
> elaborate data flow analysis, somewhat defeating the point of having
> VoidInitializer in the first place –, _or_ to make it undefined
> behavior. Right now, we are doing a little of both, which is arguable
> the worst solution. It causes unexpected behavior of is(typeof()) and
> friends, and, much worse, leads to problems with cross-compiler
> compatibility: If a program includes piece of code which uses
> uninitialized data is never executed at runtime, it works fine when
> compiled GDC and LDC, in perfect agreement with the spec, yet DMD
> refuses to accept it.
> Yes, emitting a warning if use of uninitialized data is detected is
> most likely a good idea, but changing the language semantics depending
> on whether the optimizer is enabled is not.
> What do you think?
My answer is: optimizer doesn't affect the result of semantic analysis.
In other words, flow analysis by the optimizer also doesn't affect to
With the current DMD implementation, there is two *flow analysis*, the
former is checked by the front-end, the latter is checked by the
back-end. See the example code.
void foo() nothrow
throw new Exception("");
// "function test.foo 'foo' is nothrow yet may throw"
int bar(int n)
if (n != 0)
n = 1;
// "function test.bar no return exp; or assert(0); at end of function"
int n = void;
// "Error: variable n used before set" with -O switch
nothrow and no return analysis, which occurs with and without -o-
switch, are checked by the front-end, and that is a part of language
The "used before set" error disappears if you don't specify -O.
Therefore it is backend optimizer's work, and is not a part of the
Today, the flow analysis for uninitialized variable is not needed in
semantic analysis, so it doesn't become matter.
More information about the dmd-internals