From: Anders Carlsson Date: Sun, 9 Aug 2009 18:26:27 +0000 (+0000) Subject: Improve handling of member pointers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=237957c45774713f81fbd5394b3db4317fef0938;p=clang Improve handling of member pointers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78536 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 047fecdc20..d8fc314689 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -773,7 +773,27 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - // Always return an LLVM null constant for now; this will change when we - // get support for IRGen of member pointers. + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { + + QualType ElementTy = CAT->getElementType(); + + // FIXME: Handle arrays of structs that contain member pointers. + if (Context.getBaseElementType(ElementTy)->isMemberPointerType()) { + llvm::Constant *Element = EmitNullConstant(ElementTy); + uint64_t NumElements = CAT->getSize().getZExtValue(); + std::vector Array(NumElements); + for (uint64_t i = 0; i != NumElements; ++i) + Array[i] = Element; + + const llvm::ArrayType *ATy = + cast(getTypes().ConvertTypeForMem(T)); + return llvm::ConstantArray::get(ATy, Array); + } + } + + // FIXME: Handle structs that contain member pointers. + if (T->isMemberPointerType()) + return llvm::Constant::getAllOnesValue(getTypes().ConvertTypeForMem(T)); + return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 44f4c27927..e761e9f3c7 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -391,6 +391,14 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { return Builder.CreateFCmpUNE(Src, Zero, "tobool"); } + if (SrcType->isMemberPointerType()) { + // FIXME: This is ABI specific. + + // Compare against -1. + llvm::Value *NegativeOne = llvm::Constant::getAllOnesValue(Src->getType()); + return Builder.CreateICmpNE(Src, NegativeOne, "tobool"); + } + assert((SrcType->isIntegerType() || isa(Src->getType())) && "Unknown scalar type to convert"); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 0b012592e4..6135f65513 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -68,9 +68,9 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T) { bool CodeGenFunction::hasAggregateLLVMType(QualType T) { // FIXME: Use positive checks instead of negative ones to be more robust in // the face of extension. - return !T->hasPointerRepresentation() &&!T->isRealType() && + return !T->hasPointerRepresentation() && !T->isRealType() && !T->isVoidType() && !T->isVectorType() && !T->isFunctionType() && - !T->isBlockPointerType(); + !T->isBlockPointerType() && !T->isMemberPointerType(); } void CodeGenFunction::EmitReturnBlock() { diff --git a/test/CodeGenCXX/member-pointers-zero-init.cpp b/test/CodeGenCXX/member-pointers-zero-init.cpp new file mode 100644 index 0000000000..db7c71a0d4 --- /dev/null +++ b/test/CodeGenCXX/member-pointers-zero-init.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 && + +struct A { + int i; +}; + +// RUN: grep "@a = global i64 -1" %t && +int A::* a; + +// RUN: grep "@aa = global \[2 x i64\] \[i64 -1, i64 -1\], align 8" %t && +int A::* aa[2]; + +// RUN: grep "@aaa = global \[2 x \[2 x i64\]\] \[\[2 x i64\] \[i64 -1, i64 -1\], \[2 x i64\] \[i64 -1, i64 -1\]\]" %t && +int A::* aaa[2][2]; + +void f() { + // RUN: grep "%.obool = icmp ne i64 %.mp, -1" %t + if (a) { } + + // FIXME: This doesn't yet work +// if (a != 0) { } + +} +