Introduce a new kind of derived-to-base cast which bypasses the need for

null checks, and make sure we elide null checks when accessing base class
members.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99963 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
John McCall 2010-03-30 23:58:03 +00:00
Родитель 658f679b63
Коммит 23cba801e1
7 изменённых файлов: 56 добавлений и 4 удалений

Просмотреть файл

@ -1552,6 +1552,10 @@ public:
/// CK_DerivedToBase - Derived to base class casts.
CK_DerivedToBase,
/// CK_UncheckedDerivedToBase - Derived to base class casts that
/// assume that the derived pointer is not null.
CK_UncheckedDerivedToBase,
/// CK_Dynamic - Dynamic cast.
CK_Dynamic,

Просмотреть файл

@ -552,6 +552,8 @@ const char *CastExpr::getCastKindName() const {
return "BaseToDerived";
case CastExpr::CK_DerivedToBase:
return "DerivedToBase";
case CastExpr::CK_UncheckedDerivedToBase:
return "UncheckedDerivedToBase";
case CastExpr::CK_Dynamic:
return "Dynamic";
case CastExpr::CK_ToUnion:

Просмотреть файл

@ -2306,6 +2306,7 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
case CastExpr::CK_DerivedToBase:
case CastExpr::CK_UncheckedDerivedToBase:
// Delegate to SValuator to process.
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I;

Просмотреть файл

@ -1637,6 +1637,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CastExpr::CK_AnyPointerToObjCPointerCast:
return EmitLValue(E->getSubExpr());
case CastExpr::CK_UncheckedDerivedToBase:
case CastExpr::CK_DerivedToBase: {
const RecordType *DerivedClassTy =
E->getSubExpr()->getType()->getAs<RecordType>();

Просмотреть файл

@ -769,6 +769,9 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
const Expr *E = CE->getSubExpr();
if (CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase)
return false;
if (isa<CXXThisExpr>(E)) {
// We always assume that 'this' is never null.
@ -826,6 +829,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
return CGF.GetAddressOfDerivedClass(Src, BaseClassDecl, DerivedClassDecl,
NullCheckValue);
}
case CastExpr::CK_UncheckedDerivedToBase:
case CastExpr::CK_DerivedToBase: {
const RecordType *DerivedClassTy =
E->getType()->getAs<PointerType>()->getPointeeType()->getAs<RecordType>();

Просмотреть файл

@ -1461,7 +1461,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
if (PointerConversions)
QType = Context.getPointerType(QType);
ImpCastExprToType(From, QType, CastExpr::CK_DerivedToBase,
ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase,
/*isLvalue*/ !PointerConversions);
FromType = QType;
@ -1497,7 +1497,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
QualType UType = URecordType;
if (PointerConversions)
UType = Context.getPointerType(UType);
ImpCastExprToType(From, UType, CastExpr::CK_DerivedToBase,
ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase,
/*isLvalue*/ !PointerConversions);
FromType = UType;
FromRecordType = URecordType;
@ -1517,8 +1517,8 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// FIXME: isLvalue should be !PointerConversions here, but codegen
// does very silly things.
ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
/*isLvalue=*/ true);
ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase,
/*isLvalue=*/ !PointerConversions);
return false;
}

Просмотреть файл

@ -44,3 +44,43 @@ int f() {
return A().foo();
}
}
namespace test4 {
struct A {
int x;
};
struct B {
int x;
void foo();
};
struct C : A, B {
};
extern C *c_ptr;
// CHECK: define i32 @_ZN5test44testEv()
int test() {
// CHECK: load {{.*}} @_ZN5test45c_ptrE
// CHECK-NEXT: bitcast
// CHECK-NEXT: getelementptr
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @_ZN5test41B3fooEv
c_ptr->B::foo();
// CHECK: load {{.*}} @_ZN5test45c_ptrE
// CHECK-NEXT: bitcast
// CHECK-NEXT: getelementptr
// CHECK-NEXT: bitcast
// CHECK-NEXT: getelementptr
// CHECK-NEXT: store i32 5
c_ptr->B::x = 5;
// CHECK: load {{.*}} @_ZN5test45c_ptrE
// CHECK-NEXT: bitcast
// CHECK-NEXT: getelementptr
// CHECK-NEXT: bitcast
// CHECK-NEXT: getelementptr
// CHECK-NEXT: load i32*
return c_ptr->B::x;
}
}