forked from OSchip/llvm-project
This patch will build the Records lazily per Steve's comments.
Note that one test duplicate-ivar-check.m will fail because I need to re-implement duplicate ivar checking. llvm-svn: 61154
This commit is contained in:
parent
3d1f552643
commit
f327e89dab
|
@ -72,6 +72,9 @@ class ASTContext {
|
|||
llvm::DenseMap<const ObjCInterfaceDecl*,
|
||||
const ASTRecordLayout*> ASTObjCInterfaces;
|
||||
|
||||
llvm::DenseMap<const ObjCInterfaceDecl*,
|
||||
const RecordDecl*> ASTRecordForInterface;
|
||||
|
||||
/// BuiltinVaListType - built-in va list type.
|
||||
/// This is initially null and set by Sema::LazilyCreateBuiltin when
|
||||
/// a builtin that takes a valist is encountered.
|
||||
|
@ -387,6 +390,7 @@ public:
|
|||
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D);
|
||||
|
||||
const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D);
|
||||
const RecordDecl *addRecordToClass(const ObjCInterfaceDecl *D);
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Operators
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -277,10 +277,6 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
|
|||
Type *TypeForDecl;
|
||||
friend class ASTContext;
|
||||
|
||||
// FIXME: We should be able to get away with this slot by saving the
|
||||
// record decl. build lazily in a map.
|
||||
RecordDecl *RecordForDecl;
|
||||
|
||||
/// Class's super class.
|
||||
ObjCInterfaceDecl *SuperClass;
|
||||
|
||||
|
@ -317,7 +313,7 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
|
|||
ObjCInterfaceDecl(SourceLocation atLoc, IdentifierInfo *Id,
|
||||
SourceLocation CLoc, bool FD, bool isInternal)
|
||||
: NamedDecl(ObjCInterface, atLoc, Id), DeclContext(ObjCInterface),
|
||||
TypeForDecl(0), RecordForDecl(0), SuperClass(0),
|
||||
TypeForDecl(0), SuperClass(0),
|
||||
Ivars(0), NumIvars(0),
|
||||
InstanceMethods(0), NumInstanceMethods(0),
|
||||
ClassMethods(0), NumClassMethods(0),
|
||||
|
@ -352,11 +348,6 @@ public:
|
|||
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
|
||||
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
|
||||
|
||||
void CollectObjCIvars(std::vector<FieldDecl*> &Fields);
|
||||
void setRecordForDecl(RecordDecl *Decl) { RecordForDecl = Decl; }
|
||||
RecordDecl *getRecordForDecl() const { return RecordForDecl; }
|
||||
RecordDecl *getRecordForDecl() { return RecordForDecl; }
|
||||
|
||||
typedef ObjCIvarDecl * const *ivar_iterator;
|
||||
ivar_iterator ivar_begin() const { return Ivars; }
|
||||
ivar_iterator ivar_end() const { return Ivars + ivar_size();}
|
||||
|
@ -388,7 +379,6 @@ public:
|
|||
SourceLocation RBracLoc);
|
||||
FieldDecl *lookupFieldDeclForIvar(ASTContext &Context,
|
||||
const ObjCIvarDecl *ivar);
|
||||
void addRecordToClass(ASTContext &Context);
|
||||
|
||||
void addMethods(ObjCMethodDecl **insMethods, unsigned numInsMembers,
|
||||
ObjCMethodDecl **clsMethods, unsigned numClsMembers,
|
||||
|
|
|
@ -472,6 +472,46 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
|
|||
Alignment = std::max(Alignment, FieldAlign);
|
||||
}
|
||||
|
||||
static void CollectObjCIvars(const ObjCInterfaceDecl *OI,
|
||||
std::vector<FieldDecl*> &Fields) {
|
||||
const ObjCInterfaceDecl *SuperClass = OI->getSuperClass();
|
||||
if (SuperClass)
|
||||
CollectObjCIvars(SuperClass, Fields);
|
||||
for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
|
||||
E = OI->ivar_end(); I != E; ++I) {
|
||||
ObjCIvarDecl *IVDecl = (*I);
|
||||
if (!IVDecl->isInvalidDecl())
|
||||
Fields.push_back(cast<FieldDecl>(IVDecl));
|
||||
}
|
||||
}
|
||||
|
||||
/// addRecordToClass - produces record info. for the class for its
|
||||
/// ivars and all those inherited.
|
||||
///
|
||||
const RecordDecl *ASTContext::addRecordToClass(const ObjCInterfaceDecl *D)
|
||||
{
|
||||
const RecordDecl *&RD = ASTRecordForInterface[D];
|
||||
if (RD)
|
||||
return RD;
|
||||
std::vector<FieldDecl*> RecFields;
|
||||
CollectObjCIvars(D, RecFields);
|
||||
RecordDecl *NewRD = RecordDecl::Create(*this, TagDecl::TK_struct, 0,
|
||||
D->getLocation(),
|
||||
D->getIdentifier());
|
||||
/// FIXME! Can do collection of ivars and adding to the record while
|
||||
/// doing it.
|
||||
for (unsigned int i = 0; i != RecFields.size(); i++) {
|
||||
FieldDecl *Field = FieldDecl::Create(*this, NewRD,
|
||||
RecFields[i]->getLocation(),
|
||||
RecFields[i]->getIdentifier(),
|
||||
RecFields[i]->getType(),
|
||||
RecFields[i]->getBitWidth(), false, 0);
|
||||
NewRD->addDecl(*this, Field);
|
||||
}
|
||||
NewRD->completeDefinition(*this);
|
||||
RD = NewRD;
|
||||
return RD;
|
||||
}
|
||||
|
||||
/// getASTObjcInterfaceLayout - Get or compute information about the layout of
|
||||
/// the specified Objective C, which indicates its size and ivar
|
||||
|
|
|
@ -338,18 +338,6 @@ ObjCIvarDecl *
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ObjCInterfaceDecl::CollectObjCIvars(std::vector<FieldDecl*> &Fields) {
|
||||
ObjCInterfaceDecl *SuperClass = getSuperClass();
|
||||
if (SuperClass)
|
||||
SuperClass->CollectObjCIvars(Fields);
|
||||
for (ObjCInterfaceDecl::ivar_iterator I = ivar_begin(),
|
||||
E = ivar_end(); I != E; ++I) {
|
||||
ObjCIvarDecl *IVDecl = (*I);
|
||||
if (!IVDecl->isInvalidDecl())
|
||||
Fields.push_back(cast<FieldDecl>(IVDecl));
|
||||
}
|
||||
}
|
||||
|
||||
/// ObjCAddInstanceVariablesToClass - Inserts instance variables
|
||||
/// into ObjCInterfaceDecl's fields.
|
||||
///
|
||||
|
@ -369,44 +357,17 @@ void ObjCInterfaceDecl::addInstanceVariablesToClass(ObjCIvarDecl **ivars,
|
|||
///
|
||||
FieldDecl *ObjCInterfaceDecl::lookupFieldDeclForIvar(ASTContext &Context,
|
||||
const ObjCIvarDecl *ivar) {
|
||||
/* When a super class's ivar is referenced in the subclass method with no ivar
|
||||
of its own, record for the sub-class is not built yet. Build it lazily
|
||||
here. */
|
||||
if (!RecordForDecl)
|
||||
addRecordToClass(Context);
|
||||
const RecordDecl *RecordForDecl = Context.addRecordToClass(this);
|
||||
assert(RecordForDecl && "lookupFieldDeclForIvar no storage for class");
|
||||
DeclarationName Member = ivar->getDeclName();
|
||||
DeclContext::lookup_result Lookup = RecordForDecl->lookup(Context, Member);
|
||||
DeclContext::lookup_result Lookup = (const_cast< RecordDecl *>(RecordForDecl))
|
||||
->lookup(Context, Member);
|
||||
assert((Lookup.first != Lookup.second) && "field decl not found");
|
||||
FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*Lookup.first);
|
||||
assert(MemberDecl && "field decl not found");
|
||||
return MemberDecl;
|
||||
}
|
||||
|
||||
/// addRecordToClass - produces record info. for the class for its
|
||||
/// ivars and all those inherited.
|
||||
///
|
||||
void ObjCInterfaceDecl::addRecordToClass(ASTContext &Context)
|
||||
{
|
||||
std::vector<FieldDecl*> RecFields;
|
||||
CollectObjCIvars(RecFields);
|
||||
RecordDecl *RD = RecordDecl::Create(Context, TagDecl::TK_struct, 0,
|
||||
getLocation(),
|
||||
getIdentifier());
|
||||
/// FIXME! Can do collection of ivars and adding to the record while
|
||||
/// doing it.
|
||||
for (unsigned int i = 0; i != RecFields.size(); i++) {
|
||||
FieldDecl *Field = FieldDecl::Create(Context, RD,
|
||||
RecFields[i]->getLocation(),
|
||||
RecFields[i]->getIdentifier(),
|
||||
RecFields[i]->getType(),
|
||||
RecFields[i]->getBitWidth(), false, 0);
|
||||
RD->addDecl(Context, Field);
|
||||
}
|
||||
RD->completeDefinition(Context);
|
||||
RecordForDecl = RD;
|
||||
}
|
||||
|
||||
/// ObjCAddInstanceVariablesToClassImpl - Checks for correctness of Instance
|
||||
/// Variables (Ivars) relative to what declared in @implementation;s class.
|
||||
/// Ivars into ObjCImplementationDecl's fields.
|
||||
|
|
|
@ -273,13 +273,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
|||
// We are issuing warnings elsewhere!
|
||||
ObjCInterfaceType OIT = cast<ObjCInterfaceType>(Ty);
|
||||
ObjCInterfaceDecl *ID = OIT.getDecl();
|
||||
RecordDecl *RD = ID->getRecordForDecl();
|
||||
if(!RD) {
|
||||
// Sometimes, class type is being directly generated in code gen for
|
||||
// built-in class types.
|
||||
ID->addRecordToClass(Context);
|
||||
RD = ID->getRecordForDecl();
|
||||
}
|
||||
const RecordDecl *RD = Context.addRecordToClass(ID);
|
||||
return ConvertTagDeclType(cast<TagDecl>(RD));
|
||||
}
|
||||
|
||||
|
|
|
@ -3029,7 +3029,7 @@ void Sema::ActOnFields(Scope* S,
|
|||
ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(&RecFields[0]);
|
||||
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
|
||||
ID->addInstanceVariablesToClass(ClsFields, RecFields.size(), RBrac);
|
||||
ID->addRecordToClass(Context);
|
||||
#if 0
|
||||
// Must enforce the rule that ivars in the base classes may not be
|
||||
// duplicates.
|
||||
FieldIDs.clear();
|
||||
|
@ -3049,6 +3049,7 @@ void Sema::ActOnFields(Scope* S,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (ObjCImplementationDecl *IMPDecl =
|
||||
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
|
||||
|
|
|
@ -599,7 +599,6 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
|
|||
/// Add implementations's ivar to the synthesize class's ivar list.
|
||||
if (IDecl->ImplicitInterfaceDecl()) {
|
||||
IDecl->addInstanceVariablesToClass(ivars, numIvars, RBrace);
|
||||
IDecl->addRecordToClass(Context);
|
||||
return;
|
||||
}
|
||||
// If implementation has empty ivar list, just return.
|
||||
|
|
Loading…
Reference in New Issue