summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTContext.h5
-rw-r--r--clang/lib/AST/ASTContext.cpp50
-rw-r--r--clang/lib/CodeGen/CGObjCMac.cpp38
-rw-r--r--clang/test/CodeGenObjC/protocol-property-synth.m33
4 files changed, 97 insertions, 29 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 8b4c89b6e8b..335fc40aea2 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -535,6 +535,11 @@ public:
void CollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<FieldDecl*> &Fields);
+
+ void CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
//===--------------------------------------------------------------------===//
// Type Operators
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(
diff --git a/clang/test/CodeGenObjC/protocol-property-synth.m b/clang/test/CodeGenObjC/protocol-property-synth.m
new file mode 100644
index 00000000000..e91f3552310
--- /dev/null
+++ b/clang/test/CodeGenObjC/protocol-property-synth.m
@@ -0,0 +1,33 @@
+// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
+
+@interface BaseClass {
+ id _delegate;
+}
+@end
+
+@protocol MyProtocol
+@optional
+@property(assign) id delegate;
+@end
+
+@protocol AnotherProtocol
+@optional
+@property(assign) id myanother;
+@end
+
+@protocol SubProtocol <MyProtocol>
+@property(assign) id another;
+@end
+
+@interface SubClass : BaseClass <SubProtocol, AnotherProtocol> {
+}
+
+@end
+
+@implementation BaseClass @end
+
+@implementation SubClass
+@synthesize delegate = _Subdelegate;
+@synthesize another;
+@synthesize myanother;
+@end
OpenPOWER on IntegriCloud