https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71892

            Bug ID: 71892
           Summary: Recent optimization changes introduce bugs
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kern at sibbald dot com
  Target Milestone: ---

The optimizations that you made to g++ 6.0 are not reasonable since they create
programming bugs.  This applies to two optimizations you have made.  One
disallowing this to be tested against NULL and the second elimination of what
you determine to be unnecessary memory clearing with memset. 

In both case, the assumptions you make are not valid and thus these
optimizations should not be made at low levels such as -O2 and below.

First the case of testing this == NULL.  You state: "When optimizing, GCC now
assumes the this pointer can never be null, which is guaranteed by the language
rules."

This seems to be incorrect to me.  "this" is nothing but a pointer to the class
structure and at least in the case of non-virtual methods this can be zero, and
it is often useful for it to be zero, and it is even more useful for a class
implementer to be able to know if his method is being called with an
uninitialized class.  For example, if one has an optional list implemented as a
class(as is the case in Bacula), rather than testing everywhere in the code
whether or not the list pointer is NULL, it is more efficient to do so in the
class.  In our case, we return a zero in the size() method and thus there is no
need in perhaps hundreds of places to test for a NULL pointer because it is
done in the class.  Another more important use of testing for this == NULL is
for a class author to be able to know if the class has been initialized.  If
so, the method can continue, and if not the class writer can take appropriate
action and avoid a seg fault.  With your optimization, you explicitly remove
this feature from the C++ language.

The second case is you do not generate code in a overridden new operator when
memset() is used to zero the memory.  You are assuming that memory has already
been zeroed, but we are overridding new specifically to use our own memory
allocator that guarantees that the memory is non-zero.  While your optimization
may be appropriate at higher levels of optimization, it is not appropriate at
-O2 which is used by many programs.

I maintain that it is irresponsible to implement the above two unsafe
optimizations at levels -O2 and below.  I am fully aware that we could test for
the compiler level and add new command line options, but that is a lot of
unnecessary work, and in the mean time, g++ is not generating the code that
corresponds to what we wrote (i.e. it is generating incorrect code and
introducing seg faults in many programs).  Please implement these
"optimizations" if you must at higher optimization levels and leave levels -O2
and -O1 with only optimizations that are safe and do not modify the behavior of
the program as written.

Reply via email to