@@ -222,13 +222,7 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
222222
223223 const CXXRecordDecl *classDecl = cd->getParent ();
224224
225- // This code doesn't use range-based iteration because we may need to emit
226- // code between the virtual base initializers and the non-virtual base or
227- // between the non-virtual base initializers and the member initializers.
228- CXXConstructorDecl::init_const_iterator b = cd->init_begin (),
229- e = cd->init_end ();
230-
231- // Virtual base initializers first, if any. They aren't needed if:
225+ // Virtual base initializers aren't needed if:
232226 // - This is a base ctor variant
233227 // - There are no vbases
234228 // - The class is abstract, so a complete object of it cannot be constructed
@@ -238,31 +232,60 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
238232 bool constructVBases = ctorType != Ctor_Base &&
239233 classDecl->getNumVBases () != 0 &&
240234 !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 ()) {
235+ if (constructVBases &&
236+ !cgm.getTarget ().getCXXABI ().hasConstructorVariants ()) {
249237 cgm.errorNYI (cd->getSourceRange (),
250- " emitCtorPrologue: virtual base initializer " );
238+ " emitCtorPrologue: virtual base without variants " );
251239 return ;
252240 }
253241
254- // Handle non-virtual base initializers.
255- for (; b != e && (*b)->isBaseInitializer (); b++) {
256- assert (!(*b)->isBaseVirtual ());
242+ // Create three separate ranges for the different types of initializers.
243+ auto allInits = cd->inits ();
244+
245+ // Find the boundaries between the three groups.
246+ auto virtualBaseEnd = std::find_if (
247+ allInits.begin (), allInits.end (), [](const CXXCtorInitializer *Init) {
248+ return !(Init->isBaseInitializer () && Init->isBaseVirtual ());
249+ });
250+
251+ auto nonVirtualBaseEnd = std::find_if (virtualBaseEnd, allInits.end (),
252+ [](const CXXCtorInitializer *Init) {
253+ return !Init->isBaseInitializer ();
254+ });
255+
256+ // Create the three ranges.
257+ auto virtualBaseInits = llvm::make_range (allInits.begin (), virtualBaseEnd);
258+ auto nonVirtualBaseInits =
259+ llvm::make_range (virtualBaseEnd, nonVirtualBaseEnd);
260+ auto memberInits = llvm::make_range (nonVirtualBaseEnd, allInits.end ());
261+
262+ const mlir::Value oldThisValue = cxxThisValue;
257263
264+ auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
258265 if (cgm.getCodeGenOpts ().StrictVTablePointers &&
259266 cgm.getCodeGenOpts ().OptimizationLevel > 0 &&
260- isInitializerOfDynamicClass (*b)) {
267+ isInitializerOfDynamicClass (baseInit)) {
268+ // It's OK to continue after emitting the error here. The missing code
269+ // just "launders" the 'this' pointer.
261270 cgm.errorNYI (cd->getSourceRange (),
262- " emitCtorPrologue: strict vtable pointers" );
263- return ;
271+ " emitCtorPrologue: strict vtable pointers for vbase" );
264272 }
265- emitBaseInitializer (getLoc (cd->getBeginLoc ()), classDecl, *b);
273+ emitBaseInitializer (getLoc (cd->getBeginLoc ()), classDecl, baseInit);
274+ };
275+
276+ // Process virtual base initializers.
277+ for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
278+ if (!constructVBases)
279+ continue ;
280+ emitInitializer (virtualBaseInit);
281+ }
282+
283+ assert (!cir::MissingFeatures::msabi ());
284+
285+ // Then, non-virtual base initializers.
286+ for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
287+ assert (!nonVirtualBaseInit->isBaseVirtual ());
288+ emitInitializer (nonVirtualBaseInit);
266289 }
267290
268291 cxxThisValue = oldThisValue;
@@ -276,8 +299,7 @@ void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
276299 // lowering or optimization phases to keep the memory accesses more
277300 // explicit. For now, we don't insert memcpy at all.
278301 assert (!cir::MissingFeatures::ctorMemcpyizer ());
279- for (; b != e; b++) {
280- CXXCtorInitializer *member = (*b);
302+ for (CXXCtorInitializer *member : memberInits) {
281303 assert (!member->isBaseInitializer ());
282304 assert (member->isAnyMemberInitializer () &&
283305 " Delegating initializer on non-delegating constructor" );
@@ -370,7 +392,7 @@ void CIRGenFunction::initializeVTablePointers(mlir::Location loc,
370392 initializeVTablePointer (loc, vptr);
371393
372394 if (rd->getNumVBases ())
373- cgm.errorNYI (loc, " initializeVTablePointers: virtual base " );
395+ cgm.getCXXABI (). initializeHiddenVirtualInheritanceMembers (* this , rd );
374396}
375397
376398CIRGenFunction::VPtrsVector
@@ -418,8 +440,17 @@ void CIRGenFunction::getVTablePointers(BaseSubobject base,
418440 const CXXRecordDecl *nextBaseDecl;
419441
420442 if (nextBase.isVirtual ()) {
421- cgm.errorNYI (rd->getSourceRange (), " getVTablePointers: virtual base" );
422- return ;
443+ // Check if we've visited this virtual base before.
444+ if (!vbases.insert (baseDecl).second )
445+ continue ;
446+
447+ const ASTRecordLayout &layout =
448+ getContext ().getASTRecordLayout (vtableClass);
449+
450+ nextBaseDecl = nearestVBase;
451+ baseOffset = layout.getVBaseClassOffset (baseDecl);
452+ baseOffsetFromNearestVBase = CharUnits::Zero ();
453+ baseDeclIsNonVirtualPrimaryBase = false ;
423454 } else {
424455 const ASTRecordLayout &layout = getContext ().getASTRecordLayout (rd);
425456
0 commit comments