diff options
author | Anders Carlsson <andersca@mac.com> | 2010-02-02 05:17:25 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-02-02 05:17:25 +0000 |
commit | 2c12d0319a267b844cb7d569d84426cd344b90f7 (patch) | |
tree | 89a5b200b5e51978044861d63e354c0cbb2e27bf /lib/CodeGen/CGExprConstant.cpp | |
parent | c29f4c396019f51e09511e385d6c07c4ea2a1464 (diff) |
Improve handling of emitting 'null' pointers to data members.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95066 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index fba70cb88f..d843d023f7 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -911,7 +911,24 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, return C; } -static inline bool isDataMemberPointerType(QualType T) { +static bool containsPointerToDataMember(CodeGenTypes &Types, QualType T) { + // No need to check for member pointers when not compiling C++. + if (!Types.getContext().getLangOptions().CPlusPlus) + return false; + + T = Types.getContext().getBaseElementType(T); + + if (const RecordType *RT = T->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + // FIXME: It would be better if there was a way to explicitly compute the + // record layout instead of converting to a type. + Types.ConvertTagDeclType(RD); + + const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); + return Layout.containsPointerToDataMember(); + } + if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) return !MPT->getPointeeType()->isFunctionType(); @@ -919,45 +936,58 @@ static inline bool isDataMemberPointerType(QualType T) { } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - // No need to check for member pointers when not compiling C++. - if (!getContext().getLangOptions().CPlusPlus) + if (!containsPointerToDataMember(getTypes(), T)) return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); - + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { QualType ElementTy = CAT->getElementType(); - // FIXME: Handle arrays of structs that contain member pointers. - if (isDataMemberPointerType(Context.getBaseElementType(ElementTy))) { - 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; + llvm::Constant *Element = EmitNullConstant(ElementTy); + unsigned NumElements = CAT->getSize().getZExtValue(); + std::vector<llvm::Constant *> Array(NumElements); + for (unsigned i = 0; i != NumElements; ++i) + Array[i] = Element; - const llvm::ArrayType *ATy = - cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T)); - return llvm::ConstantArray::get(ATy, Array); - } + const llvm::ArrayType *ATy = + cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T)); + return llvm::ConstantArray::get(ATy, Array); } if (const RecordType *RT = T->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); - // FIXME: It would be better if there was a way to explicitly compute the - // record layout instead of converting to a type. - Types.ConvertTagDeclType(RD); - - const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); - if (Layout.containsMemberPointer()) { - assert(0 && "FIXME: No support for structs with member pointers yet!"); + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + assert(!RD->getNumBases() && + "FIXME: Handle zero-initializing structs with bases and " + "pointers to data members."); + const llvm::StructType *STy = + cast<llvm::StructType>(getTypes().ConvertTypeForMem(T)); + unsigned NumElements = STy->getNumElements(); + std::vector<llvm::Constant *> Elements(NumElements); + + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); I != E; ++I) { + const FieldDecl *FD = *I; + + unsigned FieldNo = getTypes().getLLVMFieldNo(FD); + Elements[FieldNo] = EmitNullConstant(FD->getType()); + } + + // Now go through all other fields and zero them out. + for (unsigned i = 0; i != NumElements; ++i) { + if (!Elements[i]) + Elements[i] = llvm::Constant::getNullValue(STy->getElementType(i)); } + + return llvm::ConstantStruct::get(STy, Elements); } - // FIXME: Handle structs that contain member pointers. - if (isDataMemberPointerType(T)) - return llvm::Constant::getAllOnesValue(getTypes().ConvertTypeForMem(T)); - - return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); + assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() && + "Should only see pointers to data members here!"); + + // Itanium C++ ABI 2.3: + // A NULL pointer is represented as -1. + return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1, + /*isSigned=*/true); } llvm::Constant * |