diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 50 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 38 |
2 files changed, 59 insertions, 29 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 52eadef75ab..ac46180b94d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -685,6 +685,38 @@ void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI, CollectLocalObjCIvars(this, OI, Fields); } +void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { + for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this), + E = PD->prop_end(*this); I != E; ++I) + if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) + Ivars.push_back(Ivar); + + // Also look into nested protocols. + for (ObjCProtocolDecl::protocol_iterator P = PD->protocol_begin(), + E = PD->protocol_end(); P != E; ++P) + CollectProtocolSynthesizedIvars(*P, Ivars); +} + +/// CollectSynthesizedIvars - +/// This routine collect synthesized ivars for the designated class. +/// +void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { + for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this), + E = OI->prop_end(*this); I != E; ++I) { + if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) + Ivars.push_back(Ivar); + } + // 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); + CollectProtocolSynthesizedIvars(PD, Ivars); + } +} + /// getInterfaceLayoutImpl - Get or compute information about the /// layout of the given interface. /// @@ -704,11 +736,9 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, unsigned FieldCount = D->ivar_size(); // Add in synthesized ivar count if laying out an implementation. if (Impl) { - for (ObjCInterfaceDecl::prop_iterator I = D->prop_begin(*this), - E = D->prop_end(*this); I != E; ++I) - if ((*I)->getPropertyIvarDecl()) - ++FieldCount; - + llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; + CollectSynthesizedIvars(D, Ivars); + FieldCount += Ivars.size(); // 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 @@ -750,11 +780,11 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, } // And synthesized ivars, if this is an implementation. if (Impl) { - for (ObjCInterfaceDecl::prop_iterator I = D->prop_begin(*this), - E = D->prop_end(*this); I != E; ++I) { - if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) - NewEntry->LayoutField(Ivar, i++, false, StructPacking, *this); - } + // 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); } // Finally, round the size of the total struct up to the alignment of the diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 9d57fcb786b..9418d0a2557 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -53,15 +53,14 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, return OID; // Also look in synthesized ivars. - for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(Context), - E = OID->prop_end(Context); I != E; ++I) { - if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) { - if (OIVD == Ivar) - return OID; - ++Index; - } + llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; + Context.CollectSynthesizedIvars(OID, Ivars); + for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { + if (OIVD == Ivars[k]) + return OID; + ++Index; } - + // Otherwise check in the super class. if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) return FindIvarInterface(Context, Super, OIVD, Index); @@ -3153,14 +3152,13 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( llvm::SmallVector<FieldDecl*, 32> RecFields; const ObjCInterfaceDecl *OI = OMD->getClassInterface(); CGM.getContext().CollectObjCIvars(OI, RecFields); - + // Add this implementations synthesized ivars. - for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(CGM.getContext()), - E = OI->prop_end(CGM.getContext()); I != E; ++I) { - if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl()) - RecFields.push_back(cast<FieldDecl>(IV)); - } - + llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; + CGM.getContext().CollectSynthesizedIvars(OI, Ivars); + for (unsigned k = 0, e = Ivars.size(); k != e; ++k) + RecFields.push_back(cast<FieldDecl>(Ivars[k])); + if (RecFields.empty()) return llvm::Constant::getNullValue(PtrTy); @@ -4677,10 +4675,12 @@ void CGObjCCommonMac::GetNamedIvarList(const ObjCInterfaceDecl *OID, Res.push_back(*I); } - for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(CGM.getContext()), - E = OID->prop_end(CGM.getContext()); I != E; ++I) - if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl()) - Res.push_back(IV); + // 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( |