diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 7 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 72 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 46 |
4 files changed, 70 insertions, 63 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index e99e9f2b18..cad5487ea3 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -539,11 +539,16 @@ public: void CollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<FieldDecl*> &Fields); - + + void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars, + bool CollectSynthesized = true); void CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI); + unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD); //===--------------------------------------------------------------------===// // Type Operators diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b36d1f3dbf..1d2ddbd128 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -613,6 +613,20 @@ void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI, 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, + bool CollectSynthesized) { + for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), + E = OI->ivar_end(); I != E; ++I) { + Ivars.push_back(*I); + } + if (CollectSynthesized) + CollectSynthesizedIvars(OI, Ivars); +} + void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this), @@ -645,6 +659,38 @@ void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, } } +unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) { + unsigned count = 0; + for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this), + E = PD->prop_end(*this); I != E; ++I) + if ((*I)->getPropertyIvarDecl()) + ++count; + + // Also look into nested protocols. + for (ObjCProtocolDecl::protocol_iterator P = PD->protocol_begin(), + E = PD->protocol_end(); P != E; ++P) + count += CountProtocolSynthesizedIvars(*P); + return count; +} + +unsigned ASTContext::CountSynthesizedIvars(const ObjCInterfaceDecl *OI) +{ + unsigned count = 0; + for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this), + E = OI->prop_end(*this); I != E; ++I) { + if ((*I)->getPropertyIvarDecl()) + ++count; + } + // Also look into interface's protocol list for properties declared + // in the protocol and whose ivars are synthesized. + for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(), + PE = OI->protocol_end(); P != PE; ++P) { + ObjCProtocolDecl *PD = (*P); + count += CountProtocolSynthesizedIvars(PD); + } + return count; +} + /// getInterfaceLayoutImpl - Get or compute information about the /// layout of the given interface. /// @@ -664,14 +710,13 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, unsigned FieldCount = D->ivar_size(); // Add in synthesized ivar count if laying out an implementation. if (Impl) { - llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - CollectSynthesizedIvars(D, Ivars); - FieldCount += Ivars.size(); + unsigned SynthCount = CountSynthesizedIvars(D); + FieldCount += SynthCount; // If there aren't any sythesized ivars then reuse the interface // entry. Note we can't cache this because we simply free all // entries later; however we shouldn't look up implementations // frequently. - if (FieldCount == D->ivar_size()) + if (SynthCount == 0) return getObjCLayout(D, 0); } @@ -701,20 +746,11 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, // Layout each ivar sequentially. unsigned i = 0; - for (ObjCInterfaceDecl::ivar_iterator IVI = D->ivar_begin(), - IVE = D->ivar_end(); IVI != IVE; ++IVI) { - const ObjCIvarDecl* Ivar = (*IVI); - NewEntry->LayoutField(Ivar, i++, false, StructPacking, *this); - } - // And synthesized ivars, if this is an implementation. - if (Impl) { - // FIXME. Do we need to colltect twice? - llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - CollectSynthesizedIvars(D, Ivars); - for (unsigned k = 0, e = Ivars.size(); k != e; ++k) - NewEntry->LayoutField(Ivars[k], i++, false, StructPacking, *this); - } - + llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; + ShallowCollectObjCIvars(D, Ivars, Impl); + for (unsigned k = 0, e = Ivars.size(); k != e; ++k) + NewEntry->LayoutField(Ivars[k], i++, false, StructPacking, *this); + // Finally, round the size of the total struct up to the alignment of the // struct itself. NewEntry->FinalizeLayout(); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 5e7eec9819..a70f718a76 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -1544,14 +1544,8 @@ LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, const ObjCInterfaceDecl *OID, const ObjCIvarDecl *OIVD) { - for (ObjCInterfaceDecl::ivar_iterator IVI = OID->ivar_begin(), - IVE = OID->ivar_end(); IVI != IVE; ++IVI) - if (OIVD == *IVI) - return OID; - - // Also look in synthesized ivars. llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - Context.CollectSynthesizedIvars(OID, Ivars); + Context.ShallowCollectObjCIvars(OID, Ivars); for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { if (OIVD == Ivars[k]) return OID; diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 8f1404da65..75755ece76 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -47,14 +47,8 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, // ASTContext::getObjCLayout is implemented. This should be fixed to // get the information from the layout directly. Index = 0; - for (ObjCInterfaceDecl::ivar_iterator IVI = OID->ivar_begin(), - IVE = OID->ivar_end(); IVI != IVE; ++IVI, ++Index) - if (OIVD == *IVI) - return OID; - - // Also look in synthesized ivars. llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - Context.CollectSynthesizedIvars(OID, Ivars); + Context.ShallowCollectObjCIvars(OID, Ivars); for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { if (OIVD == Ivars[k]) return OID; @@ -908,15 +902,6 @@ protected: unsigned Align, bool AddToUsed); - /// GetNamedIvarList - Return the list of ivars in the interface - /// itself (not including super classes and not including unnamed - /// bitfields). - /// - /// For the non-fragile ABI, this also includes synthesized property - /// ivars. - void GetNamedIvarList(const ObjCInterfaceDecl *OID, - llvm::SmallVector<ObjCIvarDecl*, 16> &Res) const; - CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, llvm::Value *Sel, @@ -2198,10 +2183,13 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; - GetNamedIvarList(OID, OIvars); + CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { ObjCIvarDecl *IVD = OIvars[i]; + // Ignore unnamed bit-fields. + if (!IVD->getDeclName()) + continue; Ivar[0] = GetMethodVarName(IVD->getIdentifier()); Ivar[1] = GetMethodVarType(IVD); Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, @@ -4696,25 +4684,6 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( /// } /// -void CGObjCCommonMac::GetNamedIvarList(const ObjCInterfaceDecl *OID, - llvm::SmallVector<ObjCIvarDecl*, 16> &Res) const { - for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), - E = OID->ivar_end(); I != E; ++I) { - // Ignore unnamed bit-fields. - if (!(*I)->getDeclName()) - continue; - - Res.push_back(*I); - } - - // Also save synthesize ivars. - // FIXME. Why can't we just use passed in Res small vector? - llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; - CGM.getContext().CollectSynthesizedIvars(OID, Ivars); - for (unsigned k = 0, e = Ivars.size(); k != e; ++k) - Res.push_back(Ivars[k]); -} - llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( const ObjCImplementationDecl *ID) { @@ -4727,10 +4696,13 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( // Collect declared and synthesized ivars in a small vector. llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; - GetNamedIvarList(OID, OIvars); + CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { ObjCIvarDecl *IVD = OIvars[i]; + // Ignore unnamed bit-fields. + if (!IVD->getDeclName()) + continue; Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, ComputeIvarBaseOffset(CGM, ID, IVD)); Ivar[1] = GetMethodVarName(IVD->getIdentifier()); |