[clang] 75827f0 - [CIR] Fix path generation to understand redecls (#213051)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 30 09:59:31 PDT 2026
Author: Erich Keane
Date: 2026-07-30T09:59:25-07:00
New Revision: 75827f0bdc8895e1059b2dfa4ac5b8efdc413809
URL: https://github.com/llvm/llvm-project/commit/75827f0bdc8895e1059b2dfa4ac5b8efdc413809
DIFF: https://github.com/llvm/llvm-project/commit/75827f0bdc8895e1059b2dfa4ac5b8efdc413809.diff
LOG: [CIR] Fix path generation to understand redecls (#213051)
Found this during a self-build, an additional decl was confusing the
check between getParent and the currentClass. This patch generalizes it
to use the 'isSameEntity' function which makes sure they are the same.
Also, as a drive-by, the test had some check-lines that andy submitted a
while back, that were accidentially not being tested, so fixed the
check-title to be actually checked.
Added:
Modified:
clang/lib/CIR/CodeGen/CIRGenModule.cpp
clang/test/CIR/CodeGen/pointer-to-data-member.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 39975bb39e9d2..32ff7045ecbf1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2347,7 +2347,7 @@ bool CIRGenModule::findFieldMemberPath(const CXXRecordDecl *currentClass,
getTypes().getCIRGenRecordLayout(currentClass);
// The field is declared directly in this class.
- if (field->getParent() == currentClass) {
+ if (astContext.isSameEntity(field->getParent(), currentClass)) {
int32_t fieldIdx;
if (currentClass->isUnion()) {
// For unions, getCIRFieldNo always returns 0 for every union member (all
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
index 957bc1131f403..ab0cd26ae8129 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -373,12 +373,12 @@ auto test_null() -> int Point::* {
return nullptr;
}
-// CIR: cir.func {{.*}} @_Z9test_nullv() -> !cir.data_member<!s32i in !rec_Point> {
-// CIR: %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
-// CIR: %[[CONST_NULL:.*]] = cir.const #cir.data_member<null> : !cir.data_member<!s32i in !rec_Point>
-// CIR: cir.store %[[CONST_NULL]], %[[RETVAL_ADDR]]
-// CIR: %[[RET:.*]] = cir.load %[[RETVAL_ADDR]]
-// CIR: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Point>
+// CIR-BEFORE: cir.func {{.*}} @_Z9test_nullv() -> !cir.data_member<!s32i in !rec_Point>
+// CIR-BEFORE: %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
+// CIR-BEFORE: %[[CONST_NULL:.*]] = cir.const #cir.data_member<null> : !cir.data_member<!s32i in !rec_Point>
+// CIR-BEFORE: cir.store %[[CONST_NULL]], %[[RETVAL_ADDR]]
+// CIR-BEFORE: %[[RET:.*]] = cir.load %[[RETVAL_ADDR]]
+// CIR-BEFORE: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Point>
// LLVM: define {{.*}} i64 @_Z9test_nullv()
// LLVM: %[[RETVAL_ADDR:.*]] = alloca i64
@@ -393,12 +393,12 @@ auto test_null_incomplete() -> int Incomplete::* {
return nullptr;
}
-// CIR: cir.func {{.*}} @_Z20test_null_incompletev() -> !cir.data_member<!s32i in !rec_Incomplete> {
-// CIR: %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!cir.data_member<!s32i in !rec_Incomplete>>
-// CIR: %[[CONST_NULL:.*]] = cir.const #cir.data_member<null> : !cir.data_member<!s32i in !rec_Incomplete>
-// CIR: cir.store %[[CONST_NULL]], %[[RETVAL_ADDR]]
-// CIR: %[[RET:.*]] = cir.load %[[RETVAL_ADDR]]
-// CIR: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Incomplete>
+// CIR-BEFORE: cir.func {{.*}} @_Z20test_null_incompletev() -> !cir.data_member<!s32i in !rec_Incomplete>
+// CIR-BEFORE: %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!cir.data_member<!s32i in !rec_Incomplete>>
+// CIR-BEFORE: %[[CONST_NULL:.*]] = cir.const #cir.data_member<null> : !cir.data_member<!s32i in !rec_Incomplete>
+// CIR-BEFORE: cir.store %[[CONST_NULL]], %[[RETVAL_ADDR]]
+// CIR-BEFORE: %[[RET:.*]] = cir.load %[[RETVAL_ADDR]]
+// CIR-BEFORE: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Incomplete>
// LLVM: define {{.*}} i64 @_Z20test_null_incompletev()
// LLVM: %[[RETVAL_ADDR:.*]] = alloca i64
@@ -408,3 +408,75 @@ auto test_null_incomplete() -> int Incomplete::* {
// OGCG: define {{.*}} i64 @_Z20test_null_incompletev()
// OGCG: ret i64 -1
+
+struct hasField { unsigned field; };
+struct hasField;
+template< unsigned hasField::*ptr>
+void changeFieldPtr(hasField &hf) {
+ hf.*ptr = 1;
+}
+// CIR-BEFORE-LABEL: cir.func {{.*}}_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_
+// CIR-BEFORE: %[[ARG:.*]] = cir.alloca "hf" {{.*}} : !cir.ptr<!cir.ptr<!rec_hasField>>
+// CIR-BEFORE: %[[ONE:.*]] = cir.const #cir.int<1>
+// CIR-BEFORE: %[[LOAD_ARG:.*]] = cir.load %[[ARG]] : !cir.ptr<!cir.ptr<!rec_hasField>>, !cir.ptr<!rec_hasField>
+// CIR-BEFORE: %[[GET_DM:.*]] = cir.const #cir.data_member<[0]> : !cir.data_member<!u32i in !rec_hasField>
+// CIR-BEFORE: %[[GET_MEM:.*]] = cir.get_runtime_member %[[LOAD_ARG]][%[[GET_DM]] : !cir.data_member<!u32i in !rec_hasField>] : !cir.ptr<!rec_hasField> -> !cir.ptr<!u32i>
+// CIR-BEFORE: cir.store {{.*}}%[[ONE]], %[[GET_MEM]] : !u32i, !cir.ptr<!u32i>
+
+// CIR-AFTER-LABEL: cir.func {{.*}}_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_
+// CIR-AFTER: %[[ARG:.*]] = cir.alloca "hf" {{.*}} : !cir.ptr<!cir.ptr<!rec_hasField>>
+// CIR-AFTER: %[[ONE:.*]] = cir.const #cir.int<1>
+// CIR-AFTER: %[[LOAD_ARG:.*]] = cir.load %[[ARG]] : !cir.ptr<!cir.ptr<!rec_hasField>>, !cir.ptr<!rec_hasField>
+// CIR-AFTER: %[[ZERO:.*]] = cir.const #cir.int<0> : !s64i
+// CIR-AFTER: %[[ARG_AS_PTR:.*]] = cir.cast bitcast %[[LOAD_ARG]] : !cir.ptr<!rec_hasField> -> !cir.ptr<!s8i>
+// CIR-AFTER: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_AS_PTR]], %[[ZERO]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
+// CIR-AFTER: %[[GET_MEM:.*]] = cir.cast bitcast %[[STRIDE]] : !cir.ptr<!s8i> -> !cir.ptr<!u32i>
+// CIR-AFTER: cir.store {{.*}}%[[ONE]], %[[GET_MEM]] : !u32i, !cir.ptr<!u32i>
+
+// LLVM-LABEL: define linkonce_odr void @_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_
+// LLVM: %[[ARG:.*]] = alloca ptr
+// LLVM: %[[LOAD_ARG:.*]] = load ptr, ptr %[[ARG]]
+// LLVM: %[[GET_MEM:.*]] = getelementptr i8, ptr %[[LOAD_ARG]], i64 0
+// LLVM: store i32 1, ptr %[[GET_MEM]]
+
+// OGCG has these ordered separately, so this has to live here :/
+// OGCG-LABEL: define dso_local void @_Z11useHasFieldv()
+// OGCG: %[[X:.*]] = alloca ptr
+// OGCG: store ptr @_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_, ptr %[[X]]
+// OGCG: %[[LOAD_X:.*]] = load ptr, ptr %[[X]]
+// OGCG: call void %[[LOAD_X]]({{.*}})
+
+// OGCG-LABEL: define linkonce_odr void @_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_
+// OGCG: %[[ARG:.*]] = alloca ptr
+// OGCG: %[[LOAD_ARG:.*]] = load ptr, ptr %[[ARG]]
+// OGCG: %[[GET_MEM:.*]] = getelementptr inbounds i8, ptr %[[LOAD_ARG]], i64 0
+// OGCG: store i32 1, ptr %[[GET_MEM]]
+
+using ptrTy = void (*)(hasField&);
+void useHasField() {
+ auto x = ptrTy(changeFieldPtr<&hasField::field>);
+
+ hasField hf;
+ x(hf);
+}
+
+// CIR-BEFORE-LABEL: cir.func {{.*}}@_Z11useHasFieldv()
+// CIR-BEFORE: %[[X:.*]] = cir.alloca "x" {{.*}}: !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>>
+// CIR-BEFORE: %[[GET_FUNC:.*]] = cir.get_global @_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_ : !cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>
+// CIR-BEFORE: cir.store {{.*}} %[[GET_FUNC]], %[[X]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>, !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>>
+// CIR-BEFORE: %[[LOAD_X:.*]] = cir.load {{.*}}%[[X]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>
+// CIR-BEFORE: cir.call %[[LOAD_X]](%{{.*}}) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>, !cir.ptr<!rec_hasField> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, llvm.noundef}) -> ()
+
+// CIR-AFTER-LABEL: cir.func {{.*}}@_Z11useHasFieldv()
+// CIR-AFTER: %[[X:.*]] = cir.alloca "x" {{.*}}: !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>>
+// CIR-AFTER: %[[GET_FUNC:.*]] = cir.get_global @_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_ : !cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>
+// CIR-AFTER: cir.store {{.*}} %[[GET_FUNC]], %[[X]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>, !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>>
+// CIR-AFTER: %[[LOAD_X:.*]] = cir.load {{.*}}%[[X]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>
+// CIR-AFTER: cir.call %[[LOAD_X]](%{{.*}}) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_hasField>)>>, !cir.ptr<!rec_hasField> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, llvm.noundef}) -> ()
+
+// LLVM-LABEL: define dso_local void @_Z11useHasFieldv()
+// LLVM: %[[X:.*]] = alloca ptr
+// LLVM: store ptr @_Z14changeFieldPtrIXadL_ZN8hasField5fieldEEEEvRS0_, ptr %[[X]]
+// LLVM: %[[LOAD_X:.*]] = load ptr, ptr %[[X]]
+// LLVM: call void %[[LOAD_X]]({{.*}})
+
More information about the cfe-commits
mailing list