[LLVMbugs] [Bug 18243] New: Generating unnecessary null check when casting derived pointer to virtual base class pointer
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Fri Dec 13 10:57:21 PST 2013
http://llvm.org/bugs/show_bug.cgi?id=18243
Bug ID: 18243
Summary: Generating unnecessary null check when casting derived
pointer to virtual base class pointer
Product: clang
Version: trunk
Hardware: Macintosh
OS: MacOS X
Status: NEW
Severity: enhancement
Priority: P
Component: LLVM Codegen
Assignee: unassignedclangbugs at nondot.org
Reporter: rian at alum.mit.edu
CC: llvmbugs at cs.uiuc.edu
Classification: Unclassified
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" (http://css.csail.mit.edu/stack/) static analyzer. You can see the
corresponding bug report there: https://github.com/xiw/stack/issues/25.
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.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20131213/60f1f63e/attachment.html>
More information about the llvm-bugs
mailing list