Abstract out everything having to do with member pointers into the ABI
class; they should just be completely opaque throughout IR gen now,
although I haven't really audited that.
Fix a bug apparently inherited from gcc-4.2 where we failed to null-check
member data pointers when performing derived-to-base or base-to-derived
conversions on them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 4d4ddd9..4487f17 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -414,11 +414,8 @@
return Builder.CreateFCmpUNE(Src, Zero, "tobool");
}
- if (SrcType->isMemberPointerType()) {
- // Compare against -1.
- llvm::Value *NegativeOne = llvm::Constant::getAllOnesValue(Src->getType());
- return Builder.CreateICmpNE(Src, NegativeOne, "tobool");
- }
+ if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType))
+ return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT);
assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) &&
"Unknown scalar type to convert");
@@ -567,14 +564,10 @@
}
Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
- const llvm::Type *LTy = ConvertType(Ty);
-
- if (!Ty->isMemberDataPointerType())
- return llvm::Constant::getNullValue(LTy);
-
- // Itanium C++ ABI 2.3:
- // A NULL pointer is represented as -1.
- return llvm::ConstantInt::get(LTy, -1ULL, /*isSigned=*/true);
+ if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
+ return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
+
+ return llvm::Constant::getNullValue(ConvertType(Ty));
}
//===----------------------------------------------------------------------===//
@@ -994,17 +987,15 @@
case CastExpr::CK_FunctionToPointerDecay:
return EmitLValue(E).getAddress();
- case CastExpr::CK_NullToMemberPointer:
+ case CastExpr::CK_NullToMemberPointer: {
// If the subexpression's type is the C++0x nullptr_t, emit the
// subexpression, which may have side effects.
if (E->getType()->isNullPtrType())
(void) Visit(E);
- if (CE->getType()->isMemberFunctionPointerType())
- return CGF.CGM.getCXXABI().EmitNullMemberFunctionPointer(
- CE->getType()->getAs<MemberPointerType>());
-
- return CGF.CGM.EmitNullConstant(DestTy);
+ const MemberPointerType *MPT = CE->getType()->getAs<MemberPointerType>();
+ return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ }
case CastExpr::CK_BaseToDerivedMemberPointer:
case CastExpr::CK_DerivedToBaseMemberPointer: {
@@ -1016,33 +1007,9 @@
// actual control flow may be required in order to perform the
// check, which it is for data member pointers (but not member
// function pointers on Itanium and ARM).
-
- if (CE->getType()->isMemberFunctionPointerType())
- return CGF.CGM.getCXXABI().EmitMemberFunctionPointerConversion(CGF, CE,
- Src);
-
- // See if we need to adjust the pointer.
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(E->getType()->getAs<MemberPointerType>()->
- getClass()->getAs<RecordType>()->getDecl());
- const CXXRecordDecl *DerivedDecl =
- cast<CXXRecordDecl>(CE->getType()->getAs<MemberPointerType>()->
- getClass()->getAs<RecordType>()->getDecl());
- if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
- std::swap(DerivedDecl, BaseDecl);
-
- if (llvm::Constant *Adj =
- CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
- CE->path_begin(),
- CE->path_end())) {
- if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
- Src = Builder.CreateNSWSub(Src, Adj, "adj");
- else
- Src = Builder.CreateNSWAdd(Src, Adj, "adj");
- }
-
- return Src;
+ return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src);
}
+
case CastExpr::CK_ConstructorConversion:
assert(0 && "Should be unreachable!");
@@ -1096,10 +1063,13 @@
case CastExpr::CK_FloatingCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy);
- case CastExpr::CK_MemberPointerToBoolean:
- return CGF.EvaluateExprAsBool(E);
+ case CastExpr::CK_MemberPointerToBoolean: {
+ llvm::Value *MemPtr = Visit(E);
+ const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);
}
-
+ }
+
// Handle cases where the source is an non-complex type.
if (!CGF.hasAggregateLLVMType(E->getType())) {
@@ -1821,14 +1791,13 @@
TestAndClearIgnoreResultAssign();
Value *Result;
QualType LHSTy = E->getLHS()->getType();
- if (LHSTy->isMemberFunctionPointerType()) {
+ if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) {
assert(E->getOpcode() == BinaryOperator::EQ ||
E->getOpcode() == BinaryOperator::NE);
Value *LHS = CGF.EmitScalarExpr(E->getLHS());
Value *RHS = CGF.EmitScalarExpr(E->getRHS());
- Result = CGF.CGM.getCXXABI().EmitMemberFunctionPointerComparison(
- CGF, LHS, RHS, LHSTy->getAs<MemberPointerType>(),
- E->getOpcode() == BinaryOperator::NE);
+ Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison(
+ CGF, LHS, RHS, MPT, E->getOpcode() == BinaryOperator::NE);
} else if (!LHSTy->isAnyComplexType()) {
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());