diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/AttrImpl.cpp | 4 | ||||
-rw-r--r-- | lib/Checker/CheckObjCDealloc.cpp | 3 | ||||
-rw-r--r-- | lib/Checker/ObjCUnusedIVarsChecker.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/AttributeList.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 24 |
7 files changed, 45 insertions, 3 deletions
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp index 0345226787..1f3510d7b5 100644 --- a/lib/AST/AttrImpl.cpp +++ b/lib/AST/AttrImpl.cpp @@ -143,6 +143,10 @@ Attr *IBOutletAttr::clone(ASTContext &C) const { return ::new (C) IBOutletAttr; } +Attr *IBOutletCollectionAttr::clone(ASTContext &C) const { + return ::new (C) IBOutletCollectionAttr(D); +} + Attr *IBActionAttr::clone(ASTContext &C) const { return ::new (C) IBActionAttr; } diff --git a/lib/Checker/CheckObjCDealloc.cpp b/lib/Checker/CheckObjCDealloc.cpp index c23be873f4..11ddaca9d6 100644 --- a/lib/Checker/CheckObjCDealloc.cpp +++ b/lib/Checker/CheckObjCDealloc.cpp @@ -115,7 +115,8 @@ void clang::CheckObjCDealloc(const ObjCImplementationDecl* D, QualType T = ID->getType(); if (!T->isObjCObjectPointerType() || - ID->getAttr<IBOutletAttr>()) // Skip IBOutlets. + ID->getAttr<IBOutletAttr>() || // Skip IBOutlets. + ID->getAttr<IBOutletCollectionAttr>()) // Skip IBOutletCollections. continue; containsPointerIvar = true; diff --git a/lib/Checker/ObjCUnusedIVarsChecker.cpp b/lib/Checker/ObjCUnusedIVarsChecker.cpp index 0e47621d42..2523cff9d8 100644 --- a/lib/Checker/ObjCUnusedIVarsChecker.cpp +++ b/lib/Checker/ObjCUnusedIVarsChecker.cpp @@ -114,7 +114,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D, // (b) explicitly marked unused // (c) are iboutlets if (ID->getAccessControl() != ObjCIvarDecl::Private || - ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>()) + ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>() || + ID->getAttr<IBOutletCollectionAttr>()) continue; M[ID] = Unused; diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 1e8bd2fe55..0aee70cedc 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -726,6 +726,13 @@ Attr *PCHReader::ReadAttributes() { New = ::new (*Context) IBOutletAttr(); break; + case Attr::IBOutletCollectionKind: { + ObjCInterfaceDecl *D = + cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); + New = ::new (*Context) IBOutletCollectionAttr(D); + break; + } + SIMPLE_ATTR(Malloc); SIMPLE_ATTR(NoDebug); SIMPLE_ATTR(NoInline); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 88d197271d..f8415cd052 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1917,6 +1917,12 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::NoThrow: break; + case Attr::IBOutletCollectionKind: { + const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr); + AddDeclRef(ICA->getClass(), Record); + break; + } + case Attr::NonNull: { const NonNullAttr *NonNull = cast<NonNullAttr>(Attr); Record.push_back(NonNull->size()); diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 53406280bb..1ebff22e44 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -84,6 +84,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("fastcall", AT_fastcall) .Case("ibaction", AT_IBAction) .Case("iboutlet", AT_IBOutlet) + .Case("iboutletcollection", AT_IBOutletCollection) .Case("noreturn", AT_noreturn) .Case("noinline", AT_noinline) .Case("override", AT_override) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3ae681a17d..c6dcc3b97b 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -259,6 +259,26 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName(); } +static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, + Sema &S) { + + // The iboutletcollection attribute can have zero or one arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // The IBOutletCollection attributes only apply to instance variables of + // Objective-C classes. + if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) { + S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName(); + return; + } + + // FIXME: Eventually accept the type argument. + d->addAttr(::new (S.Context) IBOutletCollectionAttr()); +} + static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { // GCC ignores the nonnull attribute on K&R style function prototypes, so we // ignore it as well @@ -1884,7 +1904,9 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, return; switch (Attr.getKind()) { case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break; - case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break; + case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break; + case AttributeList::AT_IBOutletCollection: + HandleIBOutletCollection(D, Attr, S); break; case AttributeList::AT_address_space: case AttributeList::AT_objc_gc: case AttributeList::AT_vector_size: |