Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Sorry, I was referring to the program as a whole. I get why it did the optimization for that one function in particular, but in this case, it can be proven that the function call will result in undefined behavior and (in my opinion, not necessarily the way the C standard works) it should be flagged or not compiled.


> it should be flagged or not compiled.

It will be, if you use clang-tidy (or clang's static analyzer):

    $ clang-tidy main.cpp -- -std=c++14
    1 warning generated.
    main.cpp:10:5: warning: Forming reference to null pointer [clang-analyzer-core.NonNullParamChecker]
        f_unused_parameter(*i);
        ^
    main.cpp:19:7: note: Passing null pointer value via 1st parameter 'i'
        f(nullptr);
        ^
    main.cpp:19:5: note: Calling 'f'
        f(nullptr);
        ^
    main.cpp:10:5: note: Forming reference to null pointer
        f_unused_parameter(*i);
        ^


Do not put your faith in whole program optimization. If it can be proven that the function call will result in undefined behavior, the compiler will assume that the function will never be called. If it can be proven that it will always be called, the compiler is free to assume that the program will never be run, and optimize the whole program down to nothing.

That is, undefined behavior propagates not only forwards (if you dereference a pointer, from them on you can be sure that it's not null), but also backwards (if you dereference a null pointer, that's a contradiction since null pointers can't be dereferenced, and the contradiction can only be resolved if the statement is unreachable).


> If it can be proven that it will always be called, the compiler is free to assume that the program will never be run, and optimize the whole program down to nothing.

Does that happen when the compiler assumes you'll never take branches that lead to UB, and then finds a path through your branches that more or less does nothing? Or can it happen even if you're not branching at all?

Also, say my program is

    int main() {
        printf("hello world\n");
        do_some_UB();
    }
Is the compiler really allowed to produce a program that doesn't print?


> Does that happen when the compiler assumes you'll never take branches that lead to UB, and then finds a path through your branches that more or less does nothing? Or can it happen even if you're not branching at all?

Yes and yes. How far it will propagate these backwards depends on the compiler.

> Is the compiler really allowed to produce a program that doesn't print?

Yes. A program which contains UB is illegal, there are no guarantees about any of its behaviour, including behaviour which precedes any possible actual invocation of UB, this is pointed rather clearly by the standard:

> However, if any such execution contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).


Good heavens! :)


Yes the compiler can remove the printf.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: