void CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases) { ASTContext &C = getASTContext(); // C++ [dcl.init.aggr]p1: // An aggregate is an array or a class (clause 9) with [...] // no base classes [...]. data().Aggregate = false; if (data().Bases) C.Deallocate(data().Bases); // The set of seen virtual base types. llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes; // The virtual bases of this class. llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases; data().Bases = new(C) CXXBaseSpecifier [NumBases]; data().NumBases = NumBases; for (unsigned i = 0; i < NumBases; ++i) { data().Bases[i] = *Bases[i]; // Keep track of inherited vbases for this base class. const CXXBaseSpecifier *Base = Bases[i]; QualType BaseType = Base->getType(); // Skip dependent types; we can't do any checking on them now. if (BaseType->isDependentType()) continue; CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); // Now go through all virtual bases of this base and add them. for (CXXRecordDecl::base_class_iterator VBase = BaseClassDecl->vbases_begin(), E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { // Add this base if it's not already in the list. if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) VBases.push_back(VBase); } if (Base->isVirtual()) { // Add this base if it's not already in the list. if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) VBases.push_back(Base); } } if (VBases.empty()) return; // Create base specifier for any direct or indirect virtual bases. data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; data().NumVBases = VBases.size(); for (int I = 0, E = VBases.size(); I != E; ++I) { TypeSourceInfo *VBaseTypeInfo = VBases[I]->getTypeSourceInfo(); // Skip dependent types; we can't do any checking on them now. if (VBaseTypeInfo->getType()->isDependentType()) continue; CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>( VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl()); data().VBases[I] = CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true, VBaseClassDecl->getTagKind() == TTK_Class, VBases[I]->getAccessSpecifier(), VBaseTypeInfo); } }
void CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases) { ASTContext &C = getASTContext(); // C++ [dcl.init.aggr]p1: // An aggregate is an array or a class (clause 9) with [...] // no base classes [...]. data().Aggregate = false; if (data().Bases) C.Deallocate(data().Bases); int vbaseCount = 0; llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases; bool hasDirectVirtualBase = false; data().Bases = new(C) CXXBaseSpecifier [NumBases]; data().NumBases = NumBases; for (unsigned i = 0; i < NumBases; ++i) { data().Bases[i] = *Bases[i]; // Keep track of inherited vbases for this base class. const CXXBaseSpecifier *Base = Bases[i]; QualType BaseType = Base->getType(); // Skip dependent types; we can't do any checking on them now. if (BaseType->isDependentType()) continue; CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); if (Base->isVirtual()) hasDirectVirtualBase = true; for (CXXRecordDecl::base_class_iterator VBase = BaseClassDecl->vbases_begin(), E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { // Add this vbase to the array of vbases for current class if it is // not already in the list. // FIXME. Note that we do a linear search as number of such classes are // very few. int i; for (i = 0; i < vbaseCount; ++i) if (UniqueVbases[i]->getType() == VBase->getType()) break; if (i == vbaseCount) { UniqueVbases.push_back(VBase); ++vbaseCount; } } } if (hasDirectVirtualBase) { // Iterate one more time through the direct bases and add the virtual // base to the list of vritual bases for current class. for (unsigned i = 0; i < NumBases; ++i) { const CXXBaseSpecifier *VBase = Bases[i]; if (!VBase->isVirtual()) continue; int j; for (j = 0; j < vbaseCount; ++j) if (UniqueVbases[j]->getType() == VBase->getType()) break; if (j == vbaseCount) { UniqueVbases.push_back(VBase); ++vbaseCount; } } } if (vbaseCount > 0) { // build AST for inhireted, direct or indirect, virtual bases. data().VBases = new (C) CXXBaseSpecifier [vbaseCount]; data().NumVBases = vbaseCount; for (int i = 0; i < vbaseCount; i++) { QualType QT = UniqueVbases[i]->getType(); // Skip dependent types; we can't do any checking on them now. if (QT->isDependentType()) continue; CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>(QT->getAs<RecordType>()->getDecl()); data().VBases[i] = CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true, VBaseClassDecl->getTagKind() == RecordDecl::TK_class, UniqueVbases[i]->getAccessSpecifier(), QT); } } }