From c238a79a97ad35227a28acf16028ab63127c2fb7 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 30 Jul 2009 00:10:25 +0000 Subject: [PATCH] ir-gen for nested non-virtual base member access in current class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77554 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXX.cpp | 52 +++++++++++++++++-- test/CodeGenCXX/nested-base-member-access.cpp | 51 ++++++++++++++++++ 2 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 test/CodeGenCXX/nested-base-member-access.cpp diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index f80956b93f..bce22e5ec3 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -155,19 +155,61 @@ llvm::Value *CodeGenFunction::LoadCXXThis() { return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); } +static bool +GetNestedPaths(llvm::SmallVectorImpl &NestedBasePaths, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl) { + assert(!ClassDecl->isPolymorphic() && + "FIXME: We don't support polymorphic classes yet!"); + for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(), + e = ClassDecl->bases_end(); i != e; ++i) { + if (i->isVirtual()) + continue; + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + if (Base == BaseClassDecl) { + NestedBasePaths.push_back(BaseClassDecl); + return true; + } + } + // BaseClassDecl not an immediate base of ClassDecl. + for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(), + e = ClassDecl->bases_end(); i != e; ++i) { + if (i->isVirtual()) + continue; + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + if (GetNestedPaths(NestedBasePaths, Base, BaseClassDecl)) { + NestedBasePaths.push_back(Base); + return true; + } + } + return false; +} + llvm::Value *CodeGenFunction::AddressCXXOfBaseClass(llvm::Value *BaseValue, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl) { if (ClassDecl == BaseClassDecl) return BaseValue; + llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + llvm::SmallVector NestedBasePaths; + GetNestedPaths(NestedBasePaths, ClassDecl, BaseClassDecl); + assert(NestedBasePaths.size() > 0 && + "AddressCXXOfBaseClass - inheritence path failed"); + NestedBasePaths.push_back(ClassDecl); + uint64_t Offset = 0; + // Accessing a member of the base class. Must add delata to // the load of 'this'. - // FIXME. Once type layout is complete, this will probably change. - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(ClassDecl); - llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - uint64_t Offset = Layout.getBaseClassOffset(BaseClassDecl) / 8; + for (unsigned i = NestedBasePaths.size()-1; i > 0; i--) { + const CXXRecordDecl *DerivedClass = NestedBasePaths[i]; + const CXXRecordDecl *BaseClass = NestedBasePaths[i-1]; + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(DerivedClass); + Offset += Layout.getBaseClassOffset(BaseClass) / 8; + } llvm::Value *OffsetVal = llvm::ConstantInt::get( CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset); diff --git a/test/CodeGenCXX/nested-base-member-access.cpp b/test/CodeGenCXX/nested-base-member-access.cpp new file mode 100644 index 0000000000..aee7a12232 --- /dev/null +++ b/test/CodeGenCXX/nested-base-member-access.cpp @@ -0,0 +1,51 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +extern "C" int printf(...); + +struct M { + M(int i){ iM = i; } + int iM; + void MPR() { printf("iM = %d\n", iM); } + +}; + +struct Q { + Q(int i){ iQ = i; } + int iQ; + void QPR() { printf("iQ = %d\n", iQ); } +}; + +struct IQ { + IQ(int i) { iIQ = i; } + void IQPR() { printf("iIQ = %d\n", iIQ); } + int iIQ; +}; + +struct L : IQ { + L(int i) : IQ(i+100) { iL = i; } + int iL; +}; + +struct P : Q, L { + P(int i) : Q(i+100), L(i+200) { iP = i; } + int iP; + void PPR() { printf("iP = %d\n", iP); } +}; + + +struct N : M,P { + N() : M(100), P(200) {} + void PR() { this->MPR(); this->PPR(); this->QPR(); + IQPR(); + printf("iM = %d\n", iM); + printf("iP = %d\n", iP); + printf("iQ = %d\n", iQ); + printf("iL = %d\n", iL); + printf("iIQ = %d\n", iIQ); + } +}; + +int main() { + N n1; + n1.PR(); +} -- 2.40.0