@@ -238,31 +238,44 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
238238 bool constructVBases = ctorType != Ctor_Base &&
239239 classDecl->getNumVBases () != 0 &&
240240 !classDecl->isAbstract ();
241- if (constructVBases) {
242- cgm.errorNYI (cd->getSourceRange (), " emitCtorPrologue: virtual base" );
243- return ;
244- }
245-
246- const mlir::Value oldThisValue = cxxThisValue;
247- if (!constructVBases && b != e && (*b)->isBaseInitializer () &&
248- (*b)->isBaseVirtual ()) {
241+ if (constructVBases &&
242+ !cgm.getTarget ().getCXXABI ().hasConstructorVariants ()) {
249243 cgm.errorNYI (cd->getSourceRange (),
250- " emitCtorPrologue: virtual base initializer " );
244+ " emitCtorPrologue: virtual base without variants " );
251245 return ;
252246 }
253247
254- // Handle non-virtual base initializers.
255- for (; b != e && (*b)->isBaseInitializer (); b++) {
256- assert (!(*b)->isBaseVirtual ());
248+ const mlir::Value oldThisValue = cxxThisValue;
257249
250+ // Initialize virtual bases.
251+ auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
258252 if (cgm.getCodeGenOpts ().StrictVTablePointers &&
259253 cgm.getCodeGenOpts ().OptimizationLevel > 0 &&
260- isInitializerOfDynamicClass (*b)) {
254+ isInitializerOfDynamicClass (baseInit)) {
255+ // It's OK to continue after emitting the error here. The missing code
256+ // just "launders" the 'this' pointer.
261257 cgm.errorNYI (cd->getSourceRange (),
262- " emitCtorPrologue: strict vtable pointers" );
263- return ;
258+ " emitCtorPrologue: strict vtable pointers for vbase" );
264259 }
265- emitBaseInitializer (getLoc (cd->getBeginLoc ()), classDecl, *b);
260+ emitBaseInitializer (getLoc (cd->getBeginLoc ()), classDecl, baseInit);
261+ };
262+
263+ for (; b != e && (*b)->isBaseInitializer () && (*b)->isBaseVirtual (); b++) {
264+ if (!constructVBases)
265+ continue ;
266+ emitInitializer (*b);
267+ }
268+
269+ // The loop above and the loop below could obviously be merged in their
270+ // current form, but when we implement support for the MS C++ ABI, we will
271+ // need to insert a branch after the last virtual base initializer, so
272+ // separate loops will be useful then. The missing code is covered by the
273+ // "virtual base without variants" diagnostic above.
274+
275+ // Handle non-virtual base initializers.
276+ for (; b != e && (*b)->isBaseInitializer (); b++) {
277+ assert (!(*b)->isBaseVirtual ());
278+ emitInitializer (*b);
266279 }
267280
268281 cxxThisValue = oldThisValue;
@@ -370,7 +383,7 @@ void CIRGenFunction::initializeVTablePointers(mlir::Location loc,
370383 initializeVTablePointer (loc, vptr);
371384
372385 if (rd->getNumVBases ())
373- cgm.errorNYI (loc, " initializeVTablePointers: virtual base " );
386+ cgm.getCXXABI (). initializeHiddenVirtualInheritanceMembers (* this , rd );
374387}
375388
376389CIRGenFunction::VPtrsVector
@@ -418,8 +431,17 @@ void CIRGenFunction::getVTablePointers(BaseSubobject base,
418431 const CXXRecordDecl *nextBaseDecl;
419432
420433 if (nextBase.isVirtual ()) {
421- cgm.errorNYI (rd->getSourceRange (), " getVTablePointers: virtual base" );
422- return ;
434+ // Check if we've visited this virtual base before.
435+ if (!vbases.insert (baseDecl).second )
436+ continue ;
437+
438+ const ASTRecordLayout &layout =
439+ getContext ().getASTRecordLayout (vtableClass);
440+
441+ nextBaseDecl = nearestVBase;
442+ baseOffset = layout.getVBaseClassOffset (baseDecl);
443+ baseOffsetFromNearestVBase = CharUnits::Zero ();
444+ baseDeclIsNonVirtualPrimaryBase = false ;
423445 } else {
424446 const ASTRecordLayout &layout = getContext ().getASTRecordLayout (rd);
425447
0 commit comments