aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-03 08:15:49 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-03 08:15:49 +0000
commit5808ce43f8d7e71f5acacc9ca320268c4f37565a (patch)
tree50a9b47a2ac607cfe51b3498125d8d4b07667e17 /lib/CodeGen/CGExprConstant.cpp
parent553304523bcce281aa3b1afe0f84ae34a90a3c86 (diff)
More capturing of 'this': implicit member expressions. Getting that
right for anonymous struct/union members led to me discovering some seemingly broken code in that area of Sema, which I fixed, partly by changing the representation of member pointer constants so that IndirectFieldDecls aren't expanded. This led to assorted cleanups with member pointers in CodeGen, and while I was doing that I saw some random other things to clean up. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprConstant.cpp')
-rw-r--r--lib/CodeGen/CGExprConstant.cpp51
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>());
}