================
@@ -2260,8 +2260,69 @@ mlir::Value 
CIRGenModule::emitMemberPointerConstant(const UnaryOperator *e) {
   // Otherwise, a member data pointer.
   auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
   const auto *fieldDecl = cast<FieldDecl>(decl);
-  return cir::ConstantOp::create(
-      builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
+  const auto *mpt = e->getType()->castAs<MemberPointerType>();
+  const auto *destClass = mpt->getMostRecentCXXRecordDecl();
+  std::optional<llvm::SmallVector<int32_t>> path =
+      buildMemberPath(destClass, fieldDecl);
+  if (!path)
+    return {};
+  return cir::ConstantOp::create(builder, loc,
+                                 builder.getDataMemberAttr(ty, *path));
+}
+
+std::optional<llvm::SmallVector<int32_t>>
+CIRGenModule::buildMemberPath(const CXXRecordDecl *destClass,
+                              const FieldDecl *field) {
+  llvm::SmallVector<int32_t> path;
+  if (!findFieldMemberPath(destClass, field, path))
+    return std::nullopt;
+  return path;
+}
+
+bool CIRGenModule::findFieldMemberPath(const CXXRecordDecl *currentClass,
+                                       const FieldDecl *field,
+                                       llvm::SmallVectorImpl<int32_t> &path) {
+  const CIRGenRecordLayout &layout =
+      getTypes().getCIRGenRecordLayout(currentClass);
+
+  for (const FieldDecl *fd : currentClass->fields()) {
+    if (fd != field)
+      continue;
+
+    int32_t fieldIdx;
+    if (currentClass->isUnion()) {
+      // For unions, getCIRFieldNo always returns 0 for every union member (all
+      // members share offset 0 in the CIR record).  Use the declaration-order
+      // index to distinguish members with the same type at the same offset.
+      if (!layout.isZeroInitializable()) {
+        errorNYI(field->getLocation(),
+                 "data member pointer for non-zero-initializable union");
+        return false;
+      }
+      fieldIdx = static_cast<int32_t>(field->getFieldIndex());
+    } else {
+      fieldIdx = static_cast<int32_t>(layout.getCIRFieldNo(field));
+    }
+    path.push_back(fieldIdx);
+    return true;
+  }
+
+  for (const CXXBaseSpecifier &base : currentClass->bases()) {
+    if (base.isVirtual()) {
+      errorNYI(base.getBeginLoc(), "data member pointer through virtual base");
----------------
erichkeane wrote:

Will this end up severely regressing our build?  Since now any member pointer 
where there is virtual inheritence (even if the pointer is not to a base?) will 
cause this NYI. Is there anything we can do to avoid this? 

https://github.com/llvm/llvm-project/pull/200854
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to