[clang] [CIR] Add initial support for virtual base classes (PR #155534)

Andy Kaylor via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 27 09:18:47 PDT 2025


================
@@ -238,31 +238,44 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
   bool constructVBases = ctorType != Ctor_Base &&
                          classDecl->getNumVBases() != 0 &&
                          !classDecl->isAbstract();
-  if (constructVBases) {
-    cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: virtual base");
-    return;
-  }
-
-  const mlir::Value oldThisValue = cxxThisValue;
-  if (!constructVBases && b != e && (*b)->isBaseInitializer() &&
-      (*b)->isBaseVirtual()) {
+  if (constructVBases &&
+      !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
     cgm.errorNYI(cd->getSourceRange(),
-                 "emitCtorPrologue: virtual base initializer");
+                 "emitCtorPrologue: virtual base without variants");
     return;
   }
 
-  // Handle non-virtual base initializers.
-  for (; b != e && (*b)->isBaseInitializer(); b++) {
-    assert(!(*b)->isBaseVirtual());
+  const mlir::Value oldThisValue = cxxThisValue;
 
+  // Initialize virtual bases.
+  auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
     if (cgm.getCodeGenOpts().StrictVTablePointers &&
         cgm.getCodeGenOpts().OptimizationLevel > 0 &&
-        isInitializerOfDynamicClass(*b)) {
+        isInitializerOfDynamicClass(baseInit)) {
+      // It's OK to continue after emitting the error here. The missing code
+      // just "launders" the 'this' pointer.
       cgm.errorNYI(cd->getSourceRange(),
-                   "emitCtorPrologue: strict vtable pointers");
-      return;
+                   "emitCtorPrologue: strict vtable pointers for vbase");
     }
-    emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, *b);
+    emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
+  };
+
+  for (; b != e && (*b)->isBaseInitializer() && (*b)->isBaseVirtual(); b++) {
+    if (!constructVBases)
----------------
andykaylor wrote:

This is inside the loop because if we are not constructing vbases we need to update the iterator to move past them. The initializers are ordered such that all virtual bases occur before the first non-virtual base. This loop is necessary to position the iterator for the loop below.

The MS CXXABI throws a bit of a wrench into the possibility of a range loop, because we need to insert a branch to a continue block between the virtual initializers and the non-virtual initializers, but we can probably use a flag to check for the conditions to do that. I'll play around with this loop in OGCG and see if I can simplify it without breaking anything.

https://github.com/llvm/llvm-project/pull/155534


More information about the cfe-commits mailing list