<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Generating unnecessary null check when casting derived pointer to virtual base class pointer"
   href="http://llvm.org/bugs/show_bug.cgi?id=18243">18243</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Generating unnecessary null check when casting derived pointer to virtual base class pointer
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Macintosh
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>MacOS X
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>rian@alum.mit.edu
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>clang version 3.5 (trunk 197014)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

(clang was compiled from clean trunk)

When compiling with "clang++ -c -emit-llvm -S":

-----

class Base {
};

class Derived : public virtual Base {
};

Base *nice() {
  return new Derived();
}

-----

This generates the following LLVM bitcode for the function "nice()":

-----

; Function Attrs: ssp uwtable
define %class.Base* @_Z4nicev() #0 {
entry:
  %call = call noalias i8* @_Znwm(i64 8) #4
  %0 = bitcast i8* %call to %class.Derived*
  %1 = bitcast %class.Derived* %0 to i8*
  call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 8, i32 8, i1 false)
  call void @_ZN7DerivedC1Ev(%class.Derived* %0) #2
  %2 = icmp eq %class.Derived* %0, null
  br i1 %2, label %cast.end, label %cast.notnull

cast.notnull:                                     ; preds = %entry
  %3 = bitcast %class.Derived* %0 to i8**
  %vtable = load i8** %3
  %vbase.offset.ptr = getelementptr i8* %vtable, i64 -24
  %4 = bitcast i8* %vbase.offset.ptr to i64*
  %vbase.offset = load i64* %4
  %5 = bitcast %class.Derived* %0 to i8*
  %add.ptr = getelementptr inbounds i8* %5, i64 %vbase.offset
  %6 = bitcast i8* %add.ptr to %class.Base*
  br label %cast.end

cast.end:                                         ; preds = %cast.notnull,
%entry
  %cast.result = phi %class.Base* [ %6, %cast.notnull ], [ null, %entry ]
  ret %class.Base* %cast.result
}

-----

This generates an unnecessary check for null against "new Derived():" "%2 =
icmp eq %class.Derived* %0, null." I can see that in general it's necessary to
check for null before casting any arbitrary derived pointer to a virtual base
class but in this case it's unnecessary since "@_Znwm" can never return null
and the constructor for "Derived" has already been called by this point.

This potential bug was caught while statically checking code for errors using
the "Stack" (<a href="http://css.csail.mit.edu/stack/">http://css.csail.mit.edu/stack/</a>) static analyzer. You can see the
corresponding bug report there: <a href="https://github.com/xiw/stack/issues/25">https://github.com/xiw/stack/issues/25</a>.

When compiling on -O3 the bitcode is:

-----

; Function Attrs: ssp uwtable
define noalias %class.Base* @_Z4nicev() #0 {
entry:
  %call = tail call noalias i8* @_Znwm(i64 8) #2
  %0 = bitcast i8* %call to i32 (...)***
  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]*
@_ZTV7Derived, i64 1, i64 0) to i32 (...)**), i32 (...)*** %0, align 8, !tbaa
!1
  %vbase.offset = load i64* bitcast ([3 x i8*]* @_ZTV7Derived to i64*), align 8
  %add.ptr = getelementptr inbounds i8* %call, i64 %vbase.offset
  %1 = bitcast i8* %add.ptr to %class.Base*
  ret %class.Base* %1
}

-----

So the check is correctly optimized out here.

What exactly is the contract between Clang codegen and the LLVM optimization
passes? It seems like Clang is in the wrong here because it's generating code
that isn't assuming C++ defined behavior (checking for null pointer after
calling constructor with that pointer). There may be several other instances of
generating unnecessary code against undefined behavior in the codegen module so
that might just be how it works.

The relevant code in the codegen module lives at:
CodeGenFunction::GetAddressOfBaseClass() in lib/CodeGen/CGClass.cpp and
ShouldNullCheckClassCastValue() in lib/CodeGen/CGExprScalar.cpp.

Note: It would be nice to fix this in Clang codegen because it generates false
positives in the "Stack" static analyzer, a workaround has been committed for
this case but it seems like Clang is generating code that the user did not
write.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>