diff options
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/member-pointers-zero-init.cpp | 24 |
4 files changed, 56 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 047fecdc207..d8fc3146894 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/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<llvm::Constant *> Array(NumElements); + for (uint64_t i = 0; i != NumElements; ++i) + Array[i] = Element; + + const llvm::ArrayType *ATy = + cast<llvm::ArrayType>(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/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 44f4c27927b..e761e9f3c7d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/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<llvm::PointerType>(Src->getType())) && "Unknown scalar type to convert"); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0b012592e4f..6135f65513d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/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/clang/test/CodeGenCXX/member-pointers-zero-init.cpp b/clang/test/CodeGenCXX/member-pointers-zero-init.cpp new file mode 100644 index 00000000000..db7c71a0d4b --- /dev/null +++ b/clang/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) { } + +} + |