llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This change upstreams the code to generate CIR for bool casts and reinterpret 
casts involving member pointer types and the code to lower these casts for the 
Itanium C++ ABI.

---
Full diff: https://github.com/llvm/llvm-project/pull/175996.diff


9 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+5) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+9-2) 
- (modified) clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp (+40-2) 
- (modified) clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h (+18) 
- (modified) 
clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp (+61) 
- (modified) clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp (+55) 
- (added) clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp (+71) 
- (added) clang/test/CIR/IR/invalid-cast.cir (+27) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index ceb9899a00ac4..8352f99380845 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -241,6 +241,7 @@ def CIR_CastOp : CIR_Op<"cast", [
   // The input and output types should match the cast kind.
   let hasVerifier = 1;
   let hasFolder = 1;
+  let hasCXXABILowering = 1;
 
   let extraLLVMLoweringPatternDecl = [{
     mlir::Type convertTy(mlir::Type ty) const;
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 2a4e6d9b89ee4..8a3af1ffcdbdf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2243,6 +2243,11 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr 
*ce) {
     return builder.getNullDataMemberPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
   }
 
+  case CK_ReinterpretMemberPointer: {
+    mlir::Value src = Visit(subExpr);
+    return builder.createBitcast(cgf.getLoc(subExpr->getExprLoc()), src,
+                                 cgf.convertType(destTy));
+  }
   case CK_BaseToDerivedMemberPointer:
   case CK_DerivedToBaseMemberPointer: {
     mlir::Value src = Visit(subExpr);
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 6c4607abb40e7..1be7fe06d8be3 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -657,9 +657,16 @@ LogicalResult cir::CastOp::verify() {
              << "requires floating point !cir.complex type for result";
     return success();
   }
-  default:
-    llvm_unreachable("Unknown CastOp kind?");
+  case cir::CastKind::member_ptr_to_bool: {
+    if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
+      return emitOpError()
+             << "requires !cir.data_member or !cir.method type for source";
+    if (!mlir::isa<cir::BoolType>(resType))
+      return emitOpError() << "requires !cir.bool type for result";
+    return success();
+  }
   }
+  llvm_unreachable("Unknown CastOp kind?");
 }
 
 static bool isIntOrBoolCast(cir::CastOp op) {
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 145f8574893f4..2a928a556b762 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -57,8 +57,8 @@ class CIRGenericCXXABILoweringPattern : public 
mlir::ConversionPattern {
   matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
                   mlir::ConversionPatternRewriter &rewriter) const override {
     // Do not match on operations that have dedicated ABI lowering rewrite 
rules
-    if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::ConstantOp,
-                  cir::CmpOp, cir::DerivedDataMemberOp, cir::FuncOp,
+    if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::CastOp, 
cir::CmpOp,
+                  cir::ConstantOp, cir::DerivedDataMemberOp, cir::FuncOp,
                   cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
       return mlir::failure();
 
@@ -130,6 +130,44 @@ mlir::LogicalResult 
CIRAllocaOpABILowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
+    cir::CastOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type srcTy = op.getSrc().getType();
+  assert((mlir::isa<cir::DataMemberType, cir::MethodType>(srcTy)) &&
+         "input to bitcast in ABI lowering must be a data member or method");
+
+  switch (op.getKind()) {
+  case cir::CastKind::bitcast: {
+    mlir::Type destTy = getTypeConverter()->convertType(op.getType());
+    mlir::Value loweredResult;
+    if (mlir::isa<cir::DataMemberType>(srcTy))
+      loweredResult = lowerModule->getCXXABI().lowerDataMemberBitcast(
+          op, destTy, adaptor.getSrc(), rewriter);
+    else
+      loweredResult = lowerModule->getCXXABI().lowerMethodBitcast(
+          op, destTy, adaptor.getSrc(), rewriter);
+    rewriter.replaceOp(op, loweredResult);
+    return mlir::success();
+  }
+  case cir::CastKind::member_ptr_to_bool: {
+    mlir::Value loweredResult;
+    if (mlir::isa<cir::MethodType>(srcTy))
+      loweredResult = lowerModule->getCXXABI().lowerMethodToBoolCast(
+          op, adaptor.getSrc(), rewriter);
+    else
+      loweredResult = lowerModule->getCXXABI().lowerDataMemberToBoolCast(
+          op, adaptor.getSrc(), rewriter);
+    rewriter.replaceOp(op, loweredResult);
+    return mlir::success();
+  }
+  default:
+    break;
+  }
+
+  return mlir::failure();
+}
+
 mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
     cir::ConstantOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
index 0dedfa7221f5f..a7ff9f848fb7a 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
@@ -81,6 +81,24 @@ class CIRCXXABI {
   virtual mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
                                          mlir::Value loweredRhs,
                                          mlir::OpBuilder &builder) const = 0;
+
+  virtual mlir::Value
+  lowerDataMemberBitcast(cir::CastOp op, mlir::Type loweredDstTy,
+                         mlir::Value loweredSrc,
+                         mlir::OpBuilder &builder) const = 0;
+
+  virtual mlir::Value
+  lowerDataMemberToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
+                            mlir::OpBuilder &builder) const = 0;
+
+  virtual mlir::Value lowerMethodBitcast(cir::CastOp op,
+                                         mlir::Type loweredDstTy,
+                                         mlir::Value loweredSrc,
+                                         mlir::OpBuilder &builder) const = 0;
+
+  virtual mlir::Value lowerMethodToBoolCast(cir::CastOp op,
+                                            mlir::Value loweredSrc,
+                                            mlir::OpBuilder &builder) const = 
0;
 };
 
 /// Creates an Itanium-family ABI.
diff --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
index d944fa3294684..82f17340264c4 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
@@ -67,6 +67,21 @@ class LowerItaniumCXXABI : public CIRCXXABI {
   mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
                                  mlir::Value loweredRhs,
                                  mlir::OpBuilder &builder) const override;
+
+  mlir::Value lowerDataMemberBitcast(cir::CastOp op, mlir::Type loweredDstTy,
+                                     mlir::Value loweredSrc,
+                                     mlir::OpBuilder &builder) const override;
+
+  mlir::Value
+  lowerDataMemberToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
+                            mlir::OpBuilder &builder) const override;
+
+  mlir::Value lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
+                                 mlir::Value loweredSrc,
+                                 mlir::OpBuilder &builder) const override;
+
+  mlir::Value lowerMethodToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
+                                    mlir::OpBuilder &builder) const override;
 };
 
 } // namespace
@@ -249,4 +264,50 @@ LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, 
mlir::Value loweredLhs,
                             loweredRhs);
 }
 
+mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
+    cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
+    mlir::OpBuilder &builder) const {
+  if (loweredSrc.getType() == loweredDstTy)
+    return loweredSrc;
+
+  return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
+                             cir::CastKind::bitcast, loweredSrc);
+}
+
+mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
+    cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder) const {
+  // Itanium C++ ABI 2.3:
+  //   A NULL pointer is represented as -1.
+  auto nullAttr = cir::IntAttr::get(getPtrDiffCIRTy(lm), -1);
+  auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
+  return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
+                            loweredSrc, nullValue);
+}
+
+mlir::Value
+LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
+                                       mlir::Value loweredSrc,
+                                       mlir::OpBuilder &builder) const {
+  if (loweredSrc.getType() == loweredDstTy)
+    return loweredSrc;
+
+  return loweredSrc;
+}
+
+mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
+    cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder) const {
+  // Itanium C++ ABI 2.3.2:
+  //
+  //   In the standard representation, a null member function pointer is
+  //   represented with ptr set to a null pointer. The value of adj is
+  //   unspecified for null member function pointers.
+  cir::IntType ptrdiffCIRTy = getPtrDiffCIRTy(lm);
+  mlir::Value ptrdiffZero = cir::ConstantOp::create(
+      builder, op.getLoc(), cir::IntAttr::get(ptrdiffCIRTy, 0));
+  mlir::Value ptrField = cir::ExtractMemberOp::create(
+      builder, op.getLoc(), ptrdiffCIRTy, loweredSrc, 0);
+  return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne, ptrField,
+                            ptrdiffZero);
+}
+
 } // namespace cir
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp 
b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp
index 91cf4b1ae5386..d3aca69c3914c 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp
@@ -133,3 +133,58 @@ auto derived_to_base_zero_offset(int Derived::*ptr) -> int 
Base1::* {
 // OGCG-NEXT:   store i64 %{{.*}}, ptr %[[PTR_ADDR]]
 // OGCG-NEXT:   %[[RET:.*]] = load i64, ptr %[[PTR_ADDR]]
 // OGCG-NEXT:   ret i64 %[[RET]]
+
+struct Foo {
+  int a;
+};
+
+struct Bar {
+  int a;
+};
+
+bool to_bool(int Foo::*x) {
+  return x;
+}
+
+// CIR-BEFORE: cir.func {{.*}} @_Z7to_boolM3Fooi
+// CIR-BEFORE:   %[[X:.*]] = cir.load{{.*}} %{{.*}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-BEFORE:   %{{.*}} = cir.cast member_ptr_to_bool %[[X]] : 
!cir.data_member<!s32i in !rec_Foo> -> !cir.bool
+
+// CIR-AFTER: cir.func {{.*}} @_Z7to_boolM3Fooi
+// CIR-AFTER:   %[[NULL_VAL:.*]] = cir.const #cir.int<-1> : !s64i
+// CIR-AFTER:   %[[BOOL_VAL:.*]] = cir.cmp(ne, %{{.*}}, %[[NULL_VAL]]) : 
!s64i, !cir.bool
+
+// LLVM: define {{.*}} i1 @_Z7to_boolM3Fooi
+// LLVM:   %[[X:.*]] = load i64, ptr %{{.*}}
+// LLVM:   %[[IS_NULL:.*]] = icmp ne i64 %[[X]], -1
+
+// OGCG: define {{.*}} i1 @_Z7to_boolM3Fooi
+// OGCG:   %[[X:.*]] = load i64, ptr %{{.*}}
+// OGCG:   %[[IS_NULL:.*]] = icmp ne i64 %[[X]], -1
+
+auto bitcast(int Foo::*x) {
+  return reinterpret_cast<int Bar::*>(x);
+}
+
+// CIR-BEFORE: cir.func {{.*}} @_Z7bitcastM3Fooi
+// CIR-BEFORE:   %[[X:.*]] = cir.load{{.*}} %{{.*}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-BEFORE:   %{{.*}} = cir.cast bitcast %[[X]] : !cir.data_member<!s32i in 
!rec_Foo> -> !cir.data_member<!s32i in !rec_Bar>
+
+// CIR-AFTER: cir.func {{.*}} @_Z7bitcastM3Fooi(%[[ARG0:.*]]: !s64i
+// CIR-AFTER:   %[[X_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["x", 
init] {alignment = 8 : i64}
+// CIR-AFTER:   %[[RET_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["__retval"] {alignment = 8 : i64}
+// CIR-AFTER:   cir.store %[[ARG0]], %[[X_ADDR]]
+// CIR-AFTER:   %[[X:.*]] = cir.load{{.*}} %[[X_ADDR]]
+// CIR-AFTER:   cir.store %[[X]], %[[RET_ADDR]]
+// CIR-AFTER:   %[[RET:.*]] = cir.load %[[RET_ADDR]]
+// CIR-AFTER:   cir.return %[[RET]] : !s64i
+
+// LLVM: define {{.*}} i64 @_Z7bitcastM3Fooi
+// LLVM:   %[[X:.*]] = load i64, ptr %{{.*}}
+// LLVM:   store i64 %[[X]], ptr %[[RET_ADDR:.*]]
+// LLVM:   %[[RET:.*]] = load i64, ptr %[[RET_ADDR:.*]]
+// LLVM:   ret i64 %[[RET]]
+
+// OGCG: define {{.*}} i64 @_Z7bitcastM3Fooi
+// OGCG:   %[[X:.*]] = load i64, ptr %{{.*}}
+// OGCG:   ret i64 %[[X]]
diff --git a/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp 
b/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp
new file mode 100644
index 0000000000000..4f18a6a6a9540
--- /dev/null
+++ b/clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-cir -mmlir -mlir-print-ir-before=cir-cxxabi-lowering %s -o %t.cir 2> 
%t-before.cir
+// RUN: FileCheck --check-prefix=CIR-BEFORE --input-file=%t-before.cir %s
+// RUN: FileCheck --check-prefix=CIR-AFTER --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s 
-o %t.ll
+// RUN: FileCheck --input-file=%t.ll --check-prefix=OGCG %s
+
+struct Foo {
+  void m1(int);
+  virtual void m2(int);
+  virtual void m3(int);
+};
+
+struct Bar {
+  void m4();
+};
+
+bool memfunc_to_bool(void (Foo::*func)(int)) {
+  return func;
+}
+
+// CIR-BEFORE: cir.func {{.*}} @_Z15memfunc_to_boolM3FooFviE
+// CIR-BEFORE:   %{{.*}} = cir.cast member_ptr_to_bool %{{.*}} : 
!cir.method<!cir.func<(!s32i)> in !rec_Foo> -> !cir.bool
+
+// CIR-AFTER: cir.func {{.*}} @_Z15memfunc_to_boolM3FooFviE
+// CIR-AFTER:   %[[FUNC:.*]] = cir.load{{.*}} %{{.*}} : 
!cir.ptr<!rec_anon_struct>, !rec_anon_struct
+// CIR-AFTER:   %[[NULL_VAL:.*]] = cir.const #cir.int<0> : !s64i
+// CIR-AFTER:   %[[FUNC_PTR:.*]] = cir.extract_member %[[FUNC]][0] : 
!rec_anon_struct -> !s64i
+// CIR-AFTER:   %[[BOOL_VAL:.*]] = cir.cmp(ne, %[[FUNC_PTR]], %[[NULL_VAL]]) : 
!s64i, !cir.bool
+
+// LLVM: define {{.*}} i1 @_Z15memfunc_to_boolM3FooFviE
+// LLVM:   %[[FUNC:.*]] = load { i64, i64 }, ptr %{{.*}}
+// LLVM:   %[[FUNC_PTR:.*]] = extractvalue { i64, i64 } %[[FUNC]], 0
+// LLVM:   %{{.*}} = icmp ne i64 %[[FUNC_PTR]], 0
+
+// Note: OGCG uses an extra temporary for the function argument because it
+//       composes it from coerced arguments. We'll do that in CIR too after
+//       calling convention lowering is implemented.
+
+// OGCG: define {{.*}} i1 @_Z15memfunc_to_boolM3FooFviE
+// OGCG:   %[[FUNC_TMP:.*]] = load { i64, i64 }, ptr %{{.*}}
+// OGCG:   store { i64, i64 } %[[FUNC_TMP]], ptr %[[FUNC_ADDR:.*]]
+// OGCG:   %[[FUNC:.*]] = load { i64, i64 }, ptr %[[FUNC_ADDR]]
+// OGCG:   %[[FUNC_PTR:.*]] = extractvalue { i64, i64 } %[[FUNC]], 0
+// OGCG:   %{{.*}} = icmp ne i64 %[[FUNC_PTR]], 0
+
+auto memfunc_reinterpret(void (Foo::*func)(int)) -> void (Bar::*)() {
+  return reinterpret_cast<void (Bar::*)()>(func);
+}
+
+// CIR-BEFORE: cir.func {{.*}} @_Z19memfunc_reinterpretM3FooFviE
+// CIR-BEFORE:   %{{.*}} = cir.cast bitcast %{{.*}} : 
!cir.method<!cir.func<(!s32i)> in !rec_Foo> -> !cir.method<!cir.func<()> in 
!rec_Bar>
+
+// CIR-AFTER: cir.func {{.*}} @_Z19memfunc_reinterpretM3FooFviE
+// CIR-AFTER:   %[[FUNC:.*]] = cir.load{{.*}} %{{.*}} : 
!cir.ptr<!rec_anon_struct>, !rec_anon_struct
+// CIR-AFTER:   cir.store %[[FUNC]], %[[RET_ADDR:.*]] : !rec_anon_struct, 
!cir.ptr<!rec_anon_struct>
+// CIR-AFTER:   %[[RET:.*]] = cir.load{{.*}} %[[RET_ADDR]] : 
!cir.ptr<!rec_anon_struct>, !rec_anon_struct
+// CIR-AFTER:   cir.return %[[RET]] : !rec_anon_struct
+
+// LLVM: define {{.*}} { i64, i64 } @_Z19memfunc_reinterpretM3FooFviE
+// LLVM:   %[[FUNC:.*]] = load { i64, i64 }, ptr %{{.*}}
+// LLVM:   store { i64, i64 } %[[FUNC]], ptr %[[RET_ADDR:.*]]
+// LLVM:   %[[RET:.*]] = load { i64, i64 }, ptr %[[RET_ADDR]]
+// LLVM:   ret { i64, i64 } %[[RET]]
+
+// OGCG: define {{.*}} { i64, i64 } @_Z19memfunc_reinterpretM3FooFviE
+// OGCG:   %[[FUNC:.*]] = load { i64, i64 }, ptr %{{.*}}
+// OGCG:   store { i64, i64 } %[[FUNC]], ptr %[[RET_ADDR:.*]]
+// OGCG:   %[[RET:.*]] = load { i64, i64 }, ptr %[[RET_ADDR]]
+// OGCG:   ret { i64, i64 } %[[RET]]
diff --git a/clang/test/CIR/IR/invalid-cast.cir 
b/clang/test/CIR/IR/invalid-cast.cir
new file mode 100644
index 0000000000000..321934215e84d
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-cast.cir
@@ -0,0 +1,27 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_Foo = !cir.record<struct "Foo" {!s32i}>
+
+module {
+  cir.func no_inline dso_local @_Z7to_boolM3Fooi(%arg0: !cir.data_member<!s32i 
in !rec_Foo>) -> !s32i {
+    // expected-error@+1 {{requires !cir.bool type for result}}
+    %0 = cir.cast member_ptr_to_bool %arg0 : !cir.data_member<!s32i in 
!rec_Foo> -> !s32i
+    cir.return %0 : !s32i
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+!rec_Foo = !cir.record<struct "Foo" {!s32i}>
+
+module {
+  cir.func no_inline dso_local @_Z7to_boolM3Fooi(%arg0: !s32i) -> !cir.bool {
+    // expected-error@+1 {{requires !cir.data_member or !cir.method type for 
source}}
+    %0 = cir.cast member_ptr_to_bool %arg0 : !s32i -> !cir.bool
+    cir.return %0 : !cir.bool
+  }
+}

``````````

</details>


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

Reply via email to