void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *PB, int64_t Offset, llvm::SmallSet<const CXXRecordDecl*, 32> &mark, llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); #if 0 const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base); const CXXRecordDecl *PB = L.getPrimaryBase(); if (PB && L.getPrimaryBaseWasVirtual() && IndirectPrimary.count(PB)) { int64_t BaseOffset; // FIXME: calculate this. BaseOffset = (1<<63) | (1<<31); VBases.push_back(PB); VBaseOffsets.push_back(BaseOffset); } #endif int64_t BaseOffset = Offset;; // FIXME: Calculate BaseOffset. if (i->isVirtual()) { if (Base == PB) { // Only lay things out once. if (mark.count(Base)) continue; // Mark it so we don't lay it out twice. mark.insert(Base); assert (IndirectPrimary.count(Base) && "IndirectPrimary was wrong"); VBases.push_back(Base); VBaseOffsets.push_back(Offset); } else if (IndirectPrimary.count(Base)) { // Someone else will eventually lay this out. ; } else { // Only lay things out once. if (mark.count(Base)) continue; // Mark it so we don't lay it out twice. mark.insert(Base); LayoutVirtualBase(Base); BaseOffset = *(VBaseOffsets.end()-1); } } if (Base->getNumVBases()) { const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base); const CXXRecordDecl *PB = L.getPrimaryBase(); LayoutVirtualBases(Base, PB, BaseOffset, mark, IndirectPrimary); } } }
void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class, const CXXRecordDecl *RD, const CXXRecordDecl *PB, uint64_t Offset, llvm::SmallSet<const CXXRecordDecl*, 32> &mark, llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { assert(!i->getType()->isDependentType() && "Cannot layout class with dependent bases."); const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); uint64_t BaseOffset = Offset; if (i->isVirtual()) { if (Base == PB) { // Only lay things out once. if (mark.count(Base)) continue; // Mark it so we don't lay it out twice. mark.insert(Base); assert (IndirectPrimary.count(Base) && "IndirectPrimary was wrong"); VBases.push_back(std::make_pair(Base, Offset)); } else if (IndirectPrimary.count(Base)) { // Someone else will eventually lay this out. ; } else { // Only lay things out once. if (mark.count(Base)) continue; // Mark it so we don't lay it out twice. mark.insert(Base); LayoutVirtualBase(Base); BaseOffset = VBases.back().second; } } else { if (RD == Class) BaseOffset = getBaseOffset(Base); else { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); BaseOffset = Offset + Layout.getBaseClassOffset(Base); } } if (Base->getNumVBases()) { const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase(); LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark, IndirectPrimary); } } }
static const TypeVec throwsException(const FunctionDecl *Func, llvm::SmallSet<const FunctionDecl *, 32> &CallStack) { if (CallStack.count(Func)) return TypeVec(); if (const Stmt *Body = Func->getBody()) { CallStack.insert(Func); const TypeVec Result = throwsException(Body, TypeVec(), CallStack); CallStack.erase(Func); return Result; } TypeVec Result; if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) { for (const QualType Ex : FPT->exceptions()) { Result.push_back(Ex.getTypePtr()); } } return Result; }
void ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, const CXXRecordDecl *&FirstPrimary, llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); if (!i->isVirtual()) { SelectPrimaryVBase(Base, FirstPrimary, IndirectPrimary); if (PrimaryBase) return; continue; } if (IsNearlyEmpty(Base)) { if (FirstPrimary==0) FirstPrimary = Base; if (!IndirectPrimary.count(Base)) { setPrimaryBase(Base, true); return; } } } }