[CodeGenCXX] annotate a GEP to a derived class with 'inbounds' (PR35909)

The standard says:
[expr.static.cast] p11: "If the prvalue of type “pointer to cv1 B” points to a B 
that is actually a subobject of an object of type D, the resulting pointer points 
to the enclosing object of type D. Otherwise, the behavior is undefined."

Therefore, the GEP must be inbounds.

This should solve the failure to optimize away a null check shown in PR35909:
https://bugs.llvm.org/show_bug.cgi?id=35909 

Differential Revision: https://reviews.llvm.org/D42249

llvm-svn: 322950
This commit is contained in:
Sanjay Patel 2018-01-19 15:14:51 +00:00
parent eb74ab8633
commit 372c3f1f99
3 changed files with 31 additions and 4 deletions

View File

@ -406,8 +406,8 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
// Apply the offset.
llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy);
Value = Builder.CreateGEP(Value, Builder.CreateNeg(NonVirtualOffset),
"sub.ptr");
Value = Builder.CreateInBoundsGEP(Value, Builder.CreateNeg(NonVirtualOffset),
"sub.ptr");
// Just cast.
Value = Builder.CreateBitCast(Value, DerivedPtrTy);

View File

@ -371,7 +371,7 @@ class C : public A, public B // align=16
void downcast_pointer(B *b) {
(void) static_cast<C*>(b);
// Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...)
// CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8, i8* {{.*}}, i64 -16
// CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16
// CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C*
// null check goes here
// CHECK: [[FROM_PHI:%.+]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}}
@ -388,7 +388,7 @@ void downcast_pointer(B *b) {
void downcast_reference(B &b) {
(void) static_cast<C&>(b);
// Alignment check from EmitTypeCheck(TCK_DowncastReference, ...)
// CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8, i8* {{.*}}, i64 -16
// CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16
// CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C*
// Objectsize check goes here
// CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[C]] to i64

View File

@ -0,0 +1,27 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
class A {
int a;
};
class B {
int b;
public:
A *getAsA();
};
class X : public A, public B {
int x;
};
// PR35909 - https://bugs.llvm.org/show_bug.cgi?id=35909
A *B::getAsA() {
return static_cast<X*>(this);
// CHECK-LABEL: define %class.A* @_ZN1B6getAsAEv
// CHECK: %[[THIS:.*]] = load %class.B*, %class.B**
// CHECK-NEXT: %[[BC:.*]] = bitcast %class.B* %[[THIS]] to i8*
// CHECK-NEXT: getelementptr inbounds i8, i8* %[[BC]], i64 -4
}