Skip to content

Commit bae033b

Browse files
authored
[CIR] Add support for null data member pointers (llvm#171945)
This adds the CIR support for handling null data member pointer values.
1 parent 776f593 commit bae033b

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

‎clang/lib/CIR/CodeGen/CIRGenBuilder.h‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy{
194194
returncir::DataMemberAttr::get(ty, memberIndex);
195195
}
196196

197+
cir::DataMemberAttr getNullDataMemberAttr(cir::DataMemberType ty){
198+
returncir::DataMemberAttr::get(ty);
199+
}
200+
197201
// Return true if the value is a null constant such as null pointer, (+0.0)
198202
// for floating-point or zero initializer
199203
boolisNullValue(mlir::Attribute attr) const{
@@ -360,6 +364,12 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy{
360364
returncir::IsFPClassOp::create(*this, loc, src, flags);
361365
}
362366

367+
/// Create constant nullptr for pointer-to-data-member type ty.
368+
cir::ConstantOp getNullDataMemberPtr(cir::DataMemberType ty,
369+
mlir::Location loc){
370+
returncir::ConstantOp::create(*this, loc, getNullDataMemberAttr(ty));
371+
}
372+
363373
// TODO: split this to createFPExt/createFPTrunc when we have dedicated cast
364374
// operations.
365375
mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType){

‎clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,23 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce){
22102210
return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
22112211
}
22122212

2213+
case CK_NullToMemberPointer:{
2214+
if (mustVisitNullValue(subExpr))
2215+
cgf.emitIgnoredExpr(subExpr);
2216+
2217+
assert(!cir::MissingFeatures::cxxABI());
2218+
2219+
const MemberPointerType *mpt = ce->getType()->getAs<MemberPointerType>();
2220+
if (mpt->isMemberFunctionPointerType()){
2221+
cgf.cgm.errorNYI(subExpr->getSourceRange(),
2222+
"CK_NullToMemberPointer: member function pointer");
2223+
return{};
2224+
}
2225+
2226+
auto ty = mlir::cast<cir::DataMemberType>(cgf.convertType(destTy));
2227+
return builder.getNullDataMemberPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
2228+
}
2229+
22132230
case CK_LValueToRValue:
22142231
assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy));
22152232
assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");

‎clang/test/CIR/CodeGen/pointer-to-data-member.cpp‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,43 @@ int test5(Incomplete *ic, int Incomplete::*member){
303303
// OGCG: %[[RT_MEMBER:.*]] = getelementptr inbounds i8, ptr %[[IC]], i64 %[[MEMBER]]
304304
// OGCG: %[[RET:.*]] = load i32, ptr %[[RT_MEMBER]]
305305
// OGCG: ret i32 %[[RET]]
306+
307+
autotest_null() -> int Point::*{
308+
returnnullptr;
309+
}
310+
311+
// CIR: cir.func{{.*}} @_Z9test_nullv() -> !cir.data_member<!s32i in !rec_Point>{
312+
// CIR: %[[RETVAL_ADDR:.*]] = cir.alloca !cir.data_member<!s32i in !rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>, ["__retval"]
313+
// CIR: %[[CONST_NULL:.*]] = cir.const #cir.data_member<null> : !cir.data_member<!s32i in !rec_Point>
314+
// CIR: cir.store %[[CONST_NULL]], %[[RETVAL_ADDR]]
315+
// CIR: %[[RET:.*]] = cir.load %[[RETVAL_ADDR]]
316+
// CIR: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Point>
317+
318+
// LLVM: define{{.*}} i64 @_Z9test_nullv()
319+
// LLVM: %[[RETVAL_ADDR:.*]] = alloca i64
320+
// LLVM: store i64 -1, ptr %[[RETVAL_ADDR]]
321+
// LLVM: %[[RET:.*]] = load i64, ptr %[[RETVAL_ADDR]]
322+
// LLVM: ret i64 %[[RET]]
323+
324+
// OGCG: define{{.*}} i64 @_Z9test_nullv()
325+
// OGCG: ret i64 -1
326+
327+
autotest_null_incomplete() -> int Incomplete::*{
328+
returnnullptr;
329+
}
330+
331+
// CIR: cir.func{{.*}} @_Z20test_null_incompletev() -> !cir.data_member<!s32i in !rec_Incomplete>{
332+
// CIR: %[[RETVAL_ADDR:.*]] = cir.alloca !cir.data_member<!s32i in !rec_Incomplete>, !cir.ptr<!cir.data_member<!s32i in !rec_Incomplete>>, ["__retval"]
333+
// CIR: %[[CONST_NULL:.*]] = cir.const #cir.data_member<null> : !cir.data_member<!s32i in !rec_Incomplete>
334+
// CIR: cir.store %[[CONST_NULL]], %[[RETVAL_ADDR]]
335+
// CIR: %[[RET:.*]] = cir.load %[[RETVAL_ADDR]]
336+
// CIR: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Incomplete>
337+
338+
// LLVM: define{{.*}} i64 @_Z20test_null_incompletev()
339+
// LLVM: %[[RETVAL_ADDR:.*]] = alloca i64
340+
// LLVM: store i64 -1, ptr %[[RETVAL_ADDR]]
341+
// LLVM: %[[RET:.*]] = load i64, ptr %[[RETVAL_ADDR]]
342+
// LLVM: ret i64 %[[RET]]
343+
344+
// OGCG: define{{.*}} i64 @_Z20test_null_incompletev()
345+
// OGCG: ret i64 -1

0 commit comments

Comments
(0)