aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/AttrImpl.cpp4
-rw-r--r--lib/Checker/CheckObjCDealloc.cpp3
-rw-r--r--lib/Checker/ObjCUnusedIVarsChecker.cpp3
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp7
-rw-r--r--lib/Frontend/PCHWriter.cpp6
-rw-r--r--lib/Parse/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp24
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: