From: Mike Stump Date: Thu, 20 Aug 2009 02:11:48 +0000 (+0000) Subject: Ensure we don't output repeated vbase offsets. I have a testcase for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7fa0d93a3bbe290244f4f157078d9a0d6e87b44f;p=clang Ensure we don't output repeated vbase offsets. I have a testcase for this, but need to fixup the actual offset value before I can check it in. WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79506 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index d3dad897a8..4a8bba8078 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -788,6 +788,7 @@ class VtableBuilder { const CXXRecordDecl *Class; const ASTRecordLayout &BLayout; llvm::SmallSet IndirectPrimary; + llvm::SmallSet SeenVBase; llvm::Constant *rtti; llvm::LLVMContext &VMContext; CodeGenModule &CGM; // Per-module state. @@ -829,6 +830,25 @@ public: } } + void GenerateVBaseOffsets(std::vector &offsets, + const CXXRecordDecl *RD, + uint64_t Offset, const ASTRecordLayout &Layout) { + for (CXXRecordDecl::base_class_const_iterator i =RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + if (i->isVirtual() && !SeenVBase.count(Base)) { + SeenVBase.insert(Base); + int64_t BaseOffset = Offset/8 + Layout.getVBaseClassOffset(Base) / 8; + llvm::Constant *m; + m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), BaseOffset); + m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); + offsets.push_back(m); + } + GenerateVBaseOffsets(offsets, Base, Offset, Layout); + } + } + void GenerateMethods(const CXXRecordDecl *RD) { llvm::Constant *m; @@ -864,9 +884,8 @@ public: // The virtual base offsets come first... // FIXME: Audit, is this right? if (PrimaryBase == 0 || forPrimary || !PrimaryBaseWasVirtual) { - llvm::SmallSet SeenVBase; std::vector offsets; - GenerateVBaseOffsets(offsets, RD, SeenVBase, Offset, Layout); + GenerateVBaseOffsets(offsets, RD, Offset, Layout); for (std::vector::reverse_iterator i = offsets.rbegin(), e = offsets.rend(); i != e; ++i) methods.push_back(*i); @@ -907,6 +926,7 @@ public: cast(i->getType()->getAs()->getDecl()); if (Base != PrimaryBase || PrimaryBaseWasVirtual) { uint64_t o = Offset + Layout.getBaseClassOffset(Base); + SeenVBase.clear(); GenerateVtableForBase(Base, true, false, o, false); } } @@ -921,32 +941,13 @@ public: if (i->isVirtual() && !IndirectPrimary.count(Base)) { // Mark it so we don't output it twice. IndirectPrimary.insert(Base); + SeenVBase.clear(); GenerateVtableForBase(Base, false, true, 0, true); } if (Base->getNumVBases()) GenerateVtableForVBases(Base, Class); } } - - void GenerateVBaseOffsets(std::vector &offsets, - const CXXRecordDecl *RD, - llvm::SmallSet &SeenVBase, - uint64_t Offset, const ASTRecordLayout &Layout) { - for (CXXRecordDecl::base_class_const_iterator i =RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast(i->getType()->getAs()->getDecl()); - if (i->isVirtual() && !SeenVBase.count(Base)) { - SeenVBase.insert(Base); - int64_t BaseOffset = Offset/8 + Layout.getVBaseClassOffset(Base) / 8; - llvm::Constant *m; - m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), BaseOffset); - m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); - offsets.push_back(m); - } - GenerateVBaseOffsets(offsets, Base, SeenVBase, Offset, Layout); - } - } }; llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index d5857bc9af..85ebaca6a1 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -341,7 +341,7 @@ class test8_D : test8_B1, test8_B2, test8_B3 { // CHECK-LP32-NEXT: .long __ZN8test8_B19ftest8_B1Ev // CHECK-LP32-NEXT: .long 20 // CHECK-LP32-NEXT: .long 12 -// CHECK-LP32: .long 4294967292 +// CHECK-LP32-NEXT: .long 4294967292 // CHECK-LP32-NEXT: .long __ZTI7test8_D // CHECK-LP32-NEXT: .long __ZN9test8_B2a10ftest8_B2aEv // CHECK-LP32-NEXT: .long __ZN8test8_B29ftest8_B2Ev @@ -368,7 +368,7 @@ class test8_D : test8_B1, test8_B2, test8_B3 { // CHECK-LP64-NEXT: .quad __ZN8test8_B19ftest8_B1Ev // CHECK-LP64-NEXT: .quad 40 // CHECK-LP64-NEXT: .quad 24 -// CHECK-LP64: .quad 18446744073709551608 +// CHECK-LP64-NEXT: .quad 18446744073709551608 // CHECK-LP64-NEXT: .quad __ZTI7test8_D // CHECK-LP64-NEXT: .quad __ZN9test8_B2a10ftest8_B2aEv // CHECK-LP64-NEXT: .quad __ZN8test8_B29ftest8_B2Ev