diff options
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 51b1de37a9..4d8a60e1e8 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -450,17 +450,10 @@ public: llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return Visit(E->getInitializer()); } - + llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) { - if (const MemberPointerType *MPT = - E->getType()->getAs<MemberPointerType>()) { - DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr()); - NamedDecl *ND = DRE->getDecl(); - if (MPT->isMemberFunctionPointer()) - return CGM.getCXXABI().EmitMemberPointer(cast<CXXMethodDecl>(ND)); - else - return CGM.getCXXABI().EmitMemberPointer(cast<FieldDecl>(ND)); - } + if (E->getType()->isMemberPointerType()) + return CGM.getMemberPointerConstant(E); return 0; } @@ -934,6 +927,38 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, return C; } +static uint64_t getFieldOffset(ASTContext &C, const FieldDecl *field) { + const ASTRecordLayout &layout = C.getASTRecordLayout(field->getParent()); + return layout.getFieldOffset(field->getFieldIndex()); +} + +llvm::Constant * +CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) { + // Member pointer constants always have a very particular form. + const MemberPointerType *type = cast<MemberPointerType>(uo->getType()); + const ValueDecl *decl = cast<DeclRefExpr>(uo->getSubExpr())->getDecl(); + + // A member function pointer. + if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl)) + return getCXXABI().EmitMemberPointer(method); + + // Otherwise, a member data pointer. + uint64_t fieldOffset; + if (const FieldDecl *field = dyn_cast<FieldDecl>(decl)) + fieldOffset = getFieldOffset(getContext(), field); + else { + const IndirectFieldDecl *ifield = cast<IndirectFieldDecl>(decl); + + fieldOffset = 0; + for (IndirectFieldDecl::chain_iterator ci = ifield->chain_begin(), + ce = ifield->chain_end(); ci != ce; ++ci) + fieldOffset += getFieldOffset(getContext(), cast<FieldDecl>(*ci)); + } + + CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset); + return getCXXABI().EmitMemberDataPointer(type, chars); +} + static void FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, std::vector<llvm::Constant *> &Elements, @@ -1000,9 +1025,10 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, uint64_t StartIndex = StartOffset / 8; uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8; + // FIXME: hardcodes Itanium member pointer representation! llvm::Constant *NegativeOne = llvm::ConstantInt::get(llvm::Type::getInt8Ty(CGM.getLLVMContext()), - -1ULL, /*isSigned=*/true); + -1ULL, /*isSigned*/true); // Fill in the null data member pointer. for (uint64_t I = StartIndex; I != EndIndex; ++I) @@ -1123,6 +1149,5 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { // Itanium C++ ABI 2.3: // A NULL pointer is represented as -1. - return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1ULL, - /*isSigned=*/true); + return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>()); } |