diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 106f95edc07a..22ff22e22e4e 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -963,27 +963,32 @@ public: return false; } - void InstallThunks(Index_t AddressPoint) { + void InstallThunks() { for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end(); i != e; ++i) { const CXXMethodDecl *MD = i->first; Index_t idx = Index[MD]; Index_t nv_O = i->second.first; Index_t v_O = i->second.second; - methods[AddressPoint + idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O); + submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O); } Thunks.clear(); } - void OverrideMethods(const CXXRecordDecl *RD, Index_t AddressPoint, + void OverrideMethods(std::vector *Path, bool MorallyVirtual, Index_t Offset) { - for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; - ++mi) - if (mi->isVirtual()) { - const CXXMethodDecl *MD = *mi; - llvm::Constant *m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty)); - OverrideMethod(MD, m, MorallyVirtual, Offset, methods, AddressPoint); - } + for (std::vector::reverse_iterator i =Path->rbegin(), + e = Path->rend(); i != e; ++i) { + const CXXRecordDecl *RD = *i; + for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) + if (mi->isVirtual()) { + const CXXMethodDecl *MD = *mi; + llvm::Constant *m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), + Ptr8Ty)); + OverrideMethod(MD, m, MorallyVirtual, Offset, submethods, 0); + } + } } void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) { @@ -1027,10 +1032,9 @@ public: if (Base != PrimaryBase || PrimaryBaseWasVirtual) { uint64_t o = Offset + Layout.getBaseClassOffset(Base); StartNewTable(); - Index_t AP; - AP = GenerateVtableForBase(Base, MorallyVirtual, o, false, RD); - OverrideMethods(RD, AP, MorallyVirtual, o); - InstallThunks(AP); + std::vector S; + S.push_back(RD); + GenerateVtableForBase(Base, MorallyVirtual, o, false, &S); } } } @@ -1067,9 +1071,9 @@ public: methods.push_back(rtti); Index_t AddressPoint = methods.size(); + InstallThunks(); methods.insert(methods.end(), submethods.begin(), submethods.end()); submethods.clear(); - InstallThunks(AddressPoint); // and then the non-virtual bases. NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, @@ -1099,7 +1103,7 @@ public: int64_t GenerateVtableForBase(const CXXRecordDecl *RD, bool MorallyVirtual = false, int64_t Offset = 0, bool ForVirtualBase = false, - const CXXRecordDecl *FinalD = 0) { + std::vector *Path = 0) { if (!RD->isDynamicClass()) return 0; @@ -1123,11 +1127,23 @@ public: // And add the virtuals for the class to the primary vtable. AddMethods(RD, MorallyVirtual, Offset); + if (Path) + OverrideMethods(Path, MorallyVirtual, Offset); + return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual, Offset, ForVirtualBase); } - void GenerateVtableForVBases(const CXXRecordDecl *RD) { + void GenerateVtableForVBases(const CXXRecordDecl *RD, + std::vector *Path = 0) { + bool alloc = false; + if (Path == 0) { + alloc = true; + Path = new std::vector; + } + // FIXME: We also need to override using all paths to a virtual base, + // right now, we just process the first path + Path->push_back(RD); for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = @@ -1137,14 +1153,14 @@ public: IndirectPrimary.insert(Base); StartNewTable(); int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); - Index_t AP; - AP = GenerateVtableForBase(Base, true, BaseOffset, true, RD); - OverrideMethods(RD, AP, true, BaseOffset); - InstallThunks(AP); + GenerateVtableForBase(Base, true, BaseOffset, true, Path); } if (Base->getNumVBases()) - GenerateVtableForVBases(Base); + GenerateVtableForVBases(Base, Path); } + Path->pop_back(); + if (alloc) + delete Path; } }; @@ -1195,12 +1211,12 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { linktype = llvm::GlobalValue::WeakAnyLinkage; std::vector methods; llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); - int64_t Offset; + int64_t AddressPoint; VtableBuilder b(methods, RD, CGM); // First comes the vtables for all the non-virtual bases... - Offset = b.GenerateVtableForBase(RD); + AddressPoint = b.GenerateVtableForBase(RD); // then the vtables for all the virtual bases. b.GenerateVtableForVBases(RD); @@ -1213,7 +1229,7 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { vtable = Builder.CreateBitCast(vtable, Ptr8Ty); vtable = Builder.CreateGEP(vtable, llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), - Offset*LLVMPointerWidth/8)); + AddressPoint*LLVMPointerWidth/8)); return vtable; }