Skip to content

[CIR] Enable support for nested struct members in C++ #142205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 30, 2025

Conversation

andykaylor
Copy link
Contributor

This enables us to compile C++ code with nested structures. The necessary support for this was already in place, but we were hitting an NYI error in a place where the implementation only needed to check for base classes. Base classes really aren't implemented yet, so the error is left in place but it is now behind a check for a non-zero number of bases so that the simple case is unblocked.

This enables us to compile C++ code with nested structures. The necessary
support for this was already in place, but we were hitting an NYI error
in a place where the implementation only needed to check for base classes.
Base classes really aren't implemented yet, so the error is left in place
but it is now behind a check for a non-zero number of bases so that the
simple case is unblocked.
@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels May 30, 2025
@llvmbot
Copy link
Member

llvmbot commented May 30, 2025

@llvm/pr-subscribers-clangir

Author: Andy Kaylor (andykaylor)

Changes

This enables us to compile C++ code with nested structures. The necessary support for this was already in place, but we were hitting an NYI error in a place where the implementation only needed to check for base classes. Base classes really aren't implemented yet, so the error is left in place but it is now behind a check for a non-zero number of bases so that the simple case is unblocked.


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

2 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+7-5)
  • (modified) clang/test/CIR/CodeGen/struct.cpp (+28)
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 0665ea0506875..d962372a4bcc0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -152,11 +152,13 @@ isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt,
   // out, don't do it.  This includes virtual base classes which get laid out
   // when a class is translated, even though they aren't embedded by-value into
   // the class.
-  if (isa<CXXRecordDecl>(rd)) {
-    assert(!cir::MissingFeatures::cxxSupport());
-    cgt.getCGModule().errorNYI(rd->getSourceRange(),
-                               "isSafeToConvert: CXXRecordDecl");
-    return false;
+  if (auto *crd = dyn_cast<CXXRecordDecl>(rd)) {
+    if (crd->getNumBases() > 0) {
+      assert(!cir::MissingFeatures::cxxSupport());
+      cgt.getCGModule().errorNYI(rd->getSourceRange(),
+                                 "isSafeToConvert: CXXRecordDecl with bases");
+      return false;
+    }
   }
 
   // If this type would require laying out members that are currently being laid
diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp
index 5948d1423d448..1c0c311a2f1b6 100644
--- a/clang/test/CIR/CodeGen/struct.cpp
+++ b/clang/test/CIR/CodeGen/struct.cpp
@@ -65,3 +65,31 @@ char f2(CompleteS &s) {
 // OGCG:   %[[S_REF:.*]] = load ptr, ptr %[[S_ADDR]]
 // OGCG:   %[[S_ADDR2:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[S_REF]], i32 0, i32 1
 // OGCG:   %[[S_B:.*]] = load i8, ptr %[[S_ADDR2]]
+
+struct Inner {
+  int n;
+};
+
+struct Outer {
+  Inner i;
+};
+
+void f3() {
+  Outer o;
+  o.i.n;
+}
+
+// CIR: cir.func @_Z2f3v()
+// CIR:   %[[O:.*]] = cir.alloca !rec_Outer, !cir.ptr<!rec_Outer>, ["o"]
+// CIR:   %[[O_I:.*]] = cir.get_member %[[O]][0] {name = "i"}
+// CIR:   %[[O_I_N:.*]] = cir.get_member %[[O_I]][0] {name = "n"}
+
+// LLVM: define{{.*}} void @_Z2f3v()
+// LLVM:   %[[O:.*]] = alloca %struct.Outer, i64 1, align 4
+// LLVM:   %[[O_I:.*]] = getelementptr %struct.Outer, ptr %[[O]], i32 0, i32 0
+// LLVM:   %[[O_I_N:.*]] = getelementptr %struct.Inner, ptr %[[O_I]], i32 0, i32 0
+
+// OGCG: define{{.*}} void @_Z2f3v()
+// OGCG:   %[[O:.*]] = alloca %struct.Outer, align 4
+// OGCG:   %[[O_I:.*]] = getelementptr inbounds nuw %struct.Outer, ptr %[[O]], i32 0, i32 0
+// OGCG:   %[[O_I_N:.*]] = getelementptr inbounds nuw %struct.Inner, ptr %[[O_I]], i32 0, i32 0

@llvmbot
Copy link
Member

llvmbot commented May 30, 2025

@llvm/pr-subscribers-clang

Author: Andy Kaylor (andykaylor)

Changes

This enables us to compile C++ code with nested structures. The necessary support for this was already in place, but we were hitting an NYI error in a place where the implementation only needed to check for base classes. Base classes really aren't implemented yet, so the error is left in place but it is now behind a check for a non-zero number of bases so that the simple case is unblocked.


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

2 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+7-5)
  • (modified) clang/test/CIR/CodeGen/struct.cpp (+28)
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 0665ea0506875..d962372a4bcc0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -152,11 +152,13 @@ isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt,
   // out, don't do it.  This includes virtual base classes which get laid out
   // when a class is translated, even though they aren't embedded by-value into
   // the class.
-  if (isa<CXXRecordDecl>(rd)) {
-    assert(!cir::MissingFeatures::cxxSupport());
-    cgt.getCGModule().errorNYI(rd->getSourceRange(),
-                               "isSafeToConvert: CXXRecordDecl");
-    return false;
+  if (auto *crd = dyn_cast<CXXRecordDecl>(rd)) {
+    if (crd->getNumBases() > 0) {
+      assert(!cir::MissingFeatures::cxxSupport());
+      cgt.getCGModule().errorNYI(rd->getSourceRange(),
+                                 "isSafeToConvert: CXXRecordDecl with bases");
+      return false;
+    }
   }
 
   // If this type would require laying out members that are currently being laid
diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp
index 5948d1423d448..1c0c311a2f1b6 100644
--- a/clang/test/CIR/CodeGen/struct.cpp
+++ b/clang/test/CIR/CodeGen/struct.cpp
@@ -65,3 +65,31 @@ char f2(CompleteS &s) {
 // OGCG:   %[[S_REF:.*]] = load ptr, ptr %[[S_ADDR]]
 // OGCG:   %[[S_ADDR2:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[S_REF]], i32 0, i32 1
 // OGCG:   %[[S_B:.*]] = load i8, ptr %[[S_ADDR2]]
+
+struct Inner {
+  int n;
+};
+
+struct Outer {
+  Inner i;
+};
+
+void f3() {
+  Outer o;
+  o.i.n;
+}
+
+// CIR: cir.func @_Z2f3v()
+// CIR:   %[[O:.*]] = cir.alloca !rec_Outer, !cir.ptr<!rec_Outer>, ["o"]
+// CIR:   %[[O_I:.*]] = cir.get_member %[[O]][0] {name = "i"}
+// CIR:   %[[O_I_N:.*]] = cir.get_member %[[O_I]][0] {name = "n"}
+
+// LLVM: define{{.*}} void @_Z2f3v()
+// LLVM:   %[[O:.*]] = alloca %struct.Outer, i64 1, align 4
+// LLVM:   %[[O_I:.*]] = getelementptr %struct.Outer, ptr %[[O]], i32 0, i32 0
+// LLVM:   %[[O_I_N:.*]] = getelementptr %struct.Inner, ptr %[[O_I]], i32 0, i32 0
+
+// OGCG: define{{.*}} void @_Z2f3v()
+// OGCG:   %[[O:.*]] = alloca %struct.Outer, align 4
+// OGCG:   %[[O_I:.*]] = getelementptr inbounds nuw %struct.Outer, ptr %[[O]], i32 0, i32 0
+// OGCG:   %[[O_I_N:.*]] = getelementptr inbounds nuw %struct.Inner, ptr %[[O_I]], i32 0, i32 0

@andykaylor andykaylor merged commit 94dfe87 into llvm:main May 30, 2025
14 checks passed
@andykaylor andykaylor deleted the cir-inner-struct branch May 30, 2025 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants