From: Fariborz Jahanian Date: Wed, 17 Dec 2008 21:40:49 +0000 (+0000) Subject: This patch will build the Records lazily per Steve's comments. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a769c004a2874504c17ea8afccbc4ad35fc33c9f;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61154 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index cd503130ac..2bd274cbde 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -72,6 +72,9 @@ class ASTContext { llvm::DenseMap ASTObjCInterfaces; + llvm::DenseMap 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 //===--------------------------------------------------------------------===// diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 1ccc8a5570..007c63d688 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -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 &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, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 9f8db595b7..4983d217c3 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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 &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(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 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 diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index a7e878fc24..ec8a1ff044 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -338,18 +338,6 @@ ObjCIvarDecl * return 0; } -void ObjCInterfaceDecl::CollectObjCIvars(std::vector &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(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(*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 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. diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 10b1e15ae3..e8a38a286b 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -273,13 +273,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { // We are issuing warnings elsewhere! ObjCInterfaceType OIT = cast(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(RD)); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6ef9ecd817..5ae266ef00 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3029,7 +3029,7 @@ void Sema::ActOnFields(Scope* S, ObjCIvarDecl **ClsFields = reinterpret_cast(&RecFields[0]); if (ObjCInterfaceDecl *ID = dyn_cast(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(EnclosingDecl)) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 5887f29d4f..d4cef9b0de 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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.