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
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 7fb1ffd..8373b66 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -105,10 +105,9 @@
MD->getParent()->getTypeForDecl()));
}
-llvm::Constant *CGCXXABI::EmitMemberPointer(const FieldDecl *FD) {
- return GetBogusMemberPointer(CGM,
- CGM.getContext().getMemberPointerType(FD->getType(),
- FD->getParent()->getTypeForDecl()));
+llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
+ return GetBogusMemberPointer(CGM, QualType(MPT, 0));
}
bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 547f98a..de4df3d 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -122,7 +122,8 @@
virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
/// Create a member pointer for the given field.
- virtual llvm::Constant *EmitMemberPointer(const FieldDecl *FD);
+ virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset);
/// Emit a comparison between two member pointers. Returns an i1.
virtual llvm::Value *
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 8bac4c0..2108e21 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1178,24 +1178,10 @@
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
-
- // If we're emitting an instance method as an independent lvalue,
- // we're actually emitting a member pointer.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- if (MD->isInstance()) {
- llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(MD);
- return MakeAddrLValue(V, MD->getType(), Alignment);
- }
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
- return EmitFunctionDeclLValue(*this, E, FD);
-
- // If we're emitting a field as an independent lvalue, we're
- // actually emitting a member pointer.
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND)) {
- llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(FD);
- return MakeAddrLValue(V, FD->getType(), Alignment);
- }
-
+
+ if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND))
+ return EmitFunctionDeclLValue(*this, E, fn);
+
assert(false && "Unhandled DeclRefExpr");
// an invalid LValue, but the assert will
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 51b1de3..4d8a60e 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -450,17 +450,10 @@
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 @@
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 @@
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 @@
// 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>());
}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 096430e..57627be 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -307,9 +307,9 @@
Value *VisitUnaryAddrOf(const UnaryOperator *E) {
- // If the sub-expression is an instance member reference,
- // EmitDeclRefLValue will magically emit it with the appropriate
- // value as the "address".
+ if (isa<MemberPointerType>(E->getType())) // never sugared
+ return CGF.CGM.getMemberPointerConstant(E);
+
return EmitLValue(E->getSubExpr()).getAddress();
}
Value *VisitUnaryDeref(const UnaryOperator *E) {
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 30c872a..7f77d55 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -254,7 +254,7 @@
static LValue MakeAddr(llvm::Value *V, QualType T, unsigned Alignment,
ASTContext &Context,
llvm::MDNode *TBAAInfo = 0) {
- Qualifiers Quals = Context.getCanonicalType(T).getQualifiers();
+ Qualifiers Quals = T.getQualifiers();
Quals.setObjCGCAttr(Context.getObjCGCAttrKind(T));
LValue R;
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 7652b88..39117c2 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -438,6 +438,8 @@
Types.UpdateCompletedType(TD);
}
+ llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
+
/// EmitConstantExpr - Try to emit the given expression as a
/// constant; returns 0 if the expression cannot be emitted as a
/// constant.
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 8a7ac0a..2068c29 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -79,7 +79,8 @@
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
- llvm::Constant *EmitMemberPointer(const FieldDecl *FD);
+ llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset);
llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
llvm::Value *L,
@@ -493,43 +494,13 @@
/*Packed=*/false);
}
-static uint64_t getFieldOffset(const FieldDecl *FD, CodeGenModule &CGM) {
- const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(FD->getParent());
- const llvm::StructType *ClassLTy = RL.getLLVMType();
-
- unsigned FieldNo = RL.getLLVMFieldNo(FD);
- return
- CGM.getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo);
-}
-
-llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const FieldDecl *FD) {
+llvm::Constant *
+ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
// Itanium C++ ABI 2.3:
// A pointer to data member is an offset from the base address of
// the class object containing it, represented as a ptrdiff_t
-
- const RecordDecl *parent = FD->getParent();
- if (!parent->isAnonymousStructOrUnion())
- return llvm::ConstantInt::get(getPtrDiffTy(), getFieldOffset(FD, CGM));
-
- // Handle a field injected from an anonymous struct or union.
-
- assert(FD->getDeclName() && "Requested pointer to member with no name!");
-
- // Find the record which the field was injected into.
- while (parent->isAnonymousStructOrUnion())
- parent = cast<RecordDecl>(parent->getParent());
-
- RecordDecl::lookup_const_result lookup = parent->lookup(FD->getDeclName());
- assert(lookup.first != lookup.second && "Didn't find the field!");
- const IndirectFieldDecl *indirectFD = cast<IndirectFieldDecl>(*lookup.first);
-
- uint64_t Offset = 0;
- for (IndirectFieldDecl::chain_iterator
- I= indirectFD->chain_begin(), E= indirectFD->chain_end(); I!=E; ++I) {
- Offset += getFieldOffset(cast<FieldDecl>(*I), CGM);
- }
-
- return llvm::ConstantInt::get(getPtrDiffTy(), Offset);
+ return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
}
llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {