bool CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout) { const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); // If we have a primary base, lay it out first. if (PrimaryBase) { if (!Layout.isPrimaryBaseVirtual()) { if (!LayoutNonVirtualBase(PrimaryBase, CharUnits::Zero())) return false; } else { if (!LayoutVirtualBase(PrimaryBase, CharUnits::Zero())) return false; } // Otherwise, add a vtable / vf-table if the layout says to do so. } else if (Layout.hasOwnVFPtr()) { llvm::Type *FunctionType = llvm::FunctionType::get(llvm::Type::getInt32Ty(Types.getLLVMContext()), /*isVarArg=*/true); llvm::Type *VTableTy = FunctionType->getPointerTo(); if (getTypeAlignment(VTableTy) > Alignment) { // FIXME: Should we allow this to happen in Sema? assert(!Packed && "Alignment is wrong even with packed struct!"); return false; } assert(NextFieldOffset.isZero() && "VTable pointer must come first!"); AppendField(CharUnits::Zero(), VTableTy->getPointerTo()); } // Layout the non-virtual bases. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { if (I->isVirtual()) continue; const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); // We've already laid out the primary base. if (BaseDecl == PrimaryBase && !Layout.isPrimaryBaseVirtual()) continue; if (!LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl))) return false; } // Add a vb-table pointer if the layout insists. if (Layout.hasOwnVBPtr()) { CharUnits VBPtrOffset = Layout.getVBPtrOffset(); llvm::Type *Vbptr = llvm::Type::getInt32PtrTy(Types.getLLVMContext()); AppendPadding(VBPtrOffset, getTypeAlignment(Vbptr)); AppendField(VBPtrOffset, Vbptr); } return true; }
void CGRecordLayoutBuilder::LayoutBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout) { // Check if we need to add a vtable pointer. if (RD->isDynamicClass() && !Layout.getPrimaryBase()) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(Types.getLLVMContext()); assert(NextFieldOffsetInBytes == 0 && "Vtable pointer must come first!"); AppendField(NextFieldOffsetInBytes, Int8PtrTy->getPointerTo()); } }