ir-gen for nested non-virtual base member access

in current class.

llvm-svn: 77554
This commit is contained in:
Fariborz Jahanian 2009-07-30 00:10:25 +00:00
parent da9ba9ec2c
commit d375454dcf
2 changed files with 98 additions and 5 deletions

View File

@ -155,19 +155,61 @@ llvm::Value *CodeGenFunction::LoadCXXThis() {
return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
}
static bool
GetNestedPaths(llvm::SmallVectorImpl<const CXXRecordDecl *> &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<CXXRecordDecl>(i->getType()->getAs<RecordType>()->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<CXXRecordDecl>(i->getType()->getAs<RecordType>()->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<const CXXRecordDecl *, 16> 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);

View File

@ -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();
}