diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 9 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 18 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 82 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 56 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 42 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 4 |
9 files changed, 122 insertions, 101 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ab7202c285..2790c79417 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1009,13 +1009,12 @@ public: /// of class definition. const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); - void CollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<FieldDecl*> &Fields); - void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); - void CollectNonClassIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + + void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 26e8d3ee89..c48e229599 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -464,6 +464,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// List of categories defined for this class. /// FIXME: Why is this a linked list?? ObjCCategoryDecl *CategoryList; + + /// IvarList - List of all ivars defined by this class; including class + /// extensions and implementation. This list is built lazily. + ObjCIvarDecl *IvarList; bool ForwardDecl:1; // declared with @class. bool InternalInterface:1; // true - no @interface for @implementation @@ -518,7 +522,10 @@ public: return std::distance(ivar_begin(), ivar_end()); } bool ivar_empty() const { return ivar_begin() == ivar_end(); } - + + ObjCIvarDecl *all_declared_ivar_begin(); + void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; } + /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, @@ -640,7 +647,7 @@ private: QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), - DeclAccess(ac), Synthesized(synthesized) {} + NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, @@ -654,6 +661,9 @@ public: /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. const ObjCInterfaceDecl *getContainingInterface() const; + + ObjCIvarDecl *getNextIvar() { return NextIvar; } + void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } void setAccessControl(AccessControl ac) { DeclAccess = ac; } @@ -671,6 +681,10 @@ public: static bool classof(const ObjCIvarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCIvar; } private: + /// NextIvar - Next Ivar in the list of ivars declared in class; class's + /// extensions and class's implementation + ObjCIvarDecl *NextIvar; + // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; unsigned Synthesized : 1; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4940216d88..511f2321a7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1754,7 +1754,7 @@ public: /// CollectIvarsToConstructOrDestruct - Collect those ivars which require /// initialization. - void CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, + void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); //===--------------------------------------------------------------------===// // Statement Parsing Callbacks: SemaStmt.cpp. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 95893a4616..ee4608badc 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -829,60 +829,37 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) { return ABIAlign; } -static void CollectLocalObjCIvars(ASTContext *Ctx, - const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<FieldDecl*> &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)); - } -} - -void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl<FieldDecl*> &Fields) { - if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) - CollectObjCIvars(SuperClass, Fields); - CollectLocalObjCIvars(this, OI, Fields); -} - /// ShallowCollectObjCIvars - /// Collect all ivars, including those synthesized, in the current class. /// void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { - for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), - E = OI->ivar_end(); I != E; ++I) { - Ivars.push_back(*I); - } - - CollectNonClassIvars(OI, Ivars); -} - -/// CollectNonClassIvars - -/// This routine collects all other ivars which are not declared in the class. -/// This includes synthesized ivars (via @synthesize) and those in -// class's @implementation. + // FIXME. This need be removed but there are two many places which + // assume const-ness of ObjCInterfaceDecl + ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI); + for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; + Iv= Iv->getNextIvar()) + Ivars.push_back(Iv); +} + +/// DeepCollectObjCIvars - +/// This routine first collects all declared, but not synthesized, ivars in +/// super class and then collects all ivars, including those synthesized for +/// current class. This routine is used for implementation of current class +/// when all ivars, declared and synthesized are known. /// -void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI, +void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, + bool leafClass, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { - // Find ivars declared in class extension. - for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) { - for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), - E = CDecl->ivar_end(); I != E; ++I) { - Ivars.push_back(*I); - } - } - - // Also add any ivar defined in this class's implementation. This - // includes synthesized ivars. - if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) { - for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), - E = ImplDecl->ivar_end(); I != E; ++I) + if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) + DeepCollectObjCIvars(SuperClass, false, Ivars); + if (!leafClass) { + for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), + E = OI->ivar_end(); I != E; ++I) Ivars.push_back(*I); } + else + ShallowCollectObjCIvars(OI, Ivars); } /// CollectInheritedProtocols - Collect all protocols in current class and @@ -3853,15 +3830,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, const IdentifierInfo *II = OI->getIdentifier(); S += II->getName(); S += '='; - llvm::SmallVector<FieldDecl*, 32> RecFields; - CollectObjCIvars(OI, RecFields); - for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { - if (RecFields[i]->isBitField()) - getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true, - RecFields[i]); + llvm::SmallVector<ObjCIvarDecl*, 32> Ivars; + DeepCollectObjCIvars(OI, true, Ivars); + for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { + FieldDecl *Field = cast<FieldDecl>(Ivars[i]); + if (Field->isBitField()) + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); else - getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true, - FD); + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD); } S += '}'; return; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 32f9433d9a..4167841838 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -442,7 +442,8 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal) : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id), TypeForDecl(0), SuperClass(0), - CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal), + CategoryList(0), IvarList(0), + ForwardDecl(FD), InternalInterface(isInternal), ClassLoc(CLoc) { } @@ -455,6 +456,49 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { getASTContext().setObjCImplementation(this, ImplD); } +/// all_declared_ivar_begin - return first ivar declared in this class, +/// its extensions and its implementation. Lazily build the list on first +/// access. +ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { + if (IvarList) + return IvarList; + + ObjCIvarDecl *curIvar = 0; + if (!ivar_empty()) { + ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); + IvarList = (*I); ++I; + for (curIvar = IvarList; I != E; curIvar = *I, ++I) + curIvar->setNextIvar(*I); + } + + for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl; + CDecl = CDecl->getNextClassExtension()) { + if (!CDecl->ivar_empty()) { + ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), + E = CDecl->ivar_end(); + if (!IvarList) { + IvarList = (*I); ++I; + curIvar = IvarList; + } + for ( ;I != E; curIvar = *I, ++I) + curIvar->setNextIvar(*I); + } + } + + if (ObjCImplementationDecl *ImplDecl = getImplementation()) { + if (!ImplDecl->ivar_empty()) { + ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), + E = ImplDecl->ivar_end(); + if (!IvarList) { + IvarList = (*I); ++I; + curIvar = IvarList; + } + for ( ;I != E; curIvar = *I, ++I) + curIvar->setNextIvar(*I); + } + } + return IvarList; +} /// FindCategoryDeclaration - Finds category declaration in the list of /// categories for this class and returns it. Name of the category is passed @@ -556,6 +600,16 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) || isa<ObjCCategoryDecl>(DC)) && "Invalid ivar decl context!"); + // Once a new ivar is created in any of class/class-extension/implementation + // decl contexts, the previously built IvarList must be rebuilt. + ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC); + if (!ID) { + if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) + ID = IM->getClassInterface(); + else + ID = (cast<ObjCCategoryDecl>(DC))->getClassInterface(); + } + ID->setIvarList(0); } return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW, synthesized); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index ec13dd1cd2..57e36d9f94 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -3871,13 +3871,11 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) return llvm::Constant::getNullValue(PtrTy); - llvm::SmallVector<FieldDecl*, 32> RecFields; + llvm::SmallVector<ObjCIvarDecl*, 32> Ivars; const ObjCInterfaceDecl *OI = OMD->getClassInterface(); - CGM.getContext().CollectObjCIvars(OI, RecFields); + CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars); - // Add this implementations synthesized ivars. - llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - CGM.getContext().CollectNonClassIvars(OI, Ivars); + llvm::SmallVector<FieldDecl*, 32> RecFields; for (unsigned k = 0, e = Ivars.size(); k != e; ++k) RecFields.push_back(cast<FieldDecl>(Ivars[k])); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index fa87b77957..cf3112dd51 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6921,7 +6921,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { if (!getLangOptions().CPlusPlus) return; - if (const ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { + if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { llvm::SmallVector<ObjCIvarDecl*, 8> ivars; CollectIvarsToConstructOrDestruct(OID, ivars); if (ivars.empty()) diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 2d3da3c9aa..dda36e92ce 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1395,6 +1395,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, DefaultSynthesizeProperties(S, IC, IDecl); ImplMethodsVsClassMethods(S, IC, IDecl); AtomicPropertySetterGetterRules(IC, IDecl); + if (LangOpts.ObjCNonFragileABI2) while (IDecl->getSuperClass()) { DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); @@ -1651,11 +1652,11 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, } // Collect the instance variables - llvm::SmallVector<FieldDecl*, 32> RecFields; - Context.CollectObjCIvars(Class, RecFields); + llvm::SmallVector<ObjCIvarDecl*, 32> Ivars; + Context.DeepCollectObjCIvars(Class, true, Ivars); // For each ivar, create a fresh ObjCAtDefsFieldDecl. - for (unsigned i = 0; i < RecFields.size(); i++) { - FieldDecl* ID = RecFields[i]; + for (unsigned i = 0; i < Ivars.size(); i++) { + FieldDecl* ID = cast<FieldDecl>(Ivars[i]); RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>()); Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(), ID->getIdentifier(), ID->getType(), @@ -1770,38 +1771,13 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { /// CollectIvarsToConstructOrDestruct - Collect those ivars which require /// initialization. -void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, +void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { - for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), - E = OI->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Iv = (*I); + for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; + Iv= Iv->getNextIvar()) { QualType QT = Context.getBaseElementType(Iv->getType()); if (QT->isRecordType()) - Ivars.push_back(*I); - } - - // Find ivars to construct/destruct in class extension. - for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) { - for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), - E = CDecl->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Iv = (*I); - QualType QT = Context.getBaseElementType(Iv->getType()); - if (QT->isRecordType()) - Ivars.push_back(*I); - } - } - - // Also add any ivar defined in this class's implementation. This - // includes synthesized ivars. - if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) { - for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), - E = ImplDecl->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Iv = (*I); - QualType QT = Context.getBaseElementType(Iv->getType()); - if (QT->isRecordType()) - Ivars.push_back(*I); - } + Ivars.push_back(Iv); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index bc68e91e3e..e8bf195787 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -392,6 +392,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); ID->setCategoryList( cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); + // We will rebuild this list lazily. + ID->setIvarList(0); ID->setForwardDecl(Record[Idx++]); ID->setImplicitInterfaceDecl(Record[Idx++]); ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -402,6 +404,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { VisitFieldDecl(IVD); IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]); + // This field will be built lazily. + IVD->setNextIvar(0); bool synth = Record[Idx++]; IVD->setSynthesize(synth); } |