]> granicus.if.org Git - clang/commitdiff
Patch to add type parameter support for attribute iboutletcollection.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 17 Aug 2010 20:23:12 +0000 (20:23 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 17 Aug 2010 20:23:12 +0000 (20:23 +0000)
Radar 8308053.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111275 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Attr.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/AttrImpl.cpp
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/SemaDeclAttr.cpp
test/SemaObjC/iboutletcollection-attr.m [new file with mode: 0644]

index 699fff9ffb5218e799287e537983ce7b6318fbca..5b741c669a53fbda47927fbcc086b15c6d7acb7e 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/StringRef.h"
 #include "clang/Basic/AttrKinds.h"
+#include "clang/AST/Type.h"
 #include <cassert>
 #include <cstring>
 #include <algorithm>
@@ -27,6 +28,7 @@ namespace clang {
   class IdentifierInfo;
   class ObjCInterfaceDecl;
   class Expr;
+  class QualType;
 }
 
 // Defined in ASTContext.h
@@ -286,12 +288,12 @@ public:
 };
 
 class IBOutletCollectionAttr : public Attr {
-  const ObjCInterfaceDecl *D;
+  QualType QT;
 public:
-  IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0)
-    : Attr(attr::IBOutletCollection), D(d) {}
+  IBOutletCollectionAttr(QualType qt = QualType())
+    : Attr(attr::IBOutletCollection), QT(qt) {}
 
-  const ObjCInterfaceDecl *getClass() const { return D; }
+  QualType getType() const { return QT; }
 
   virtual Attr *clone(ASTContext &C) const;
 
index 47c0afffcfac49210f42cd60013d14b8df41e00a..b243ca0ea53dced112a0e732ce929a23800a2a3e 100644 (file)
@@ -826,6 +826,8 @@ def err_attributes_are_not_compatible : Error<
   "%0 and %1 attributes are not compatible">;
 def err_attribute_wrong_number_arguments : Error<
   "attribute requires %0 argument(s)">;
+def err_iboutletcollection_type : Error<
+  "invalid type %0 as argument of iboutletcollection attribue">;
 def err_attribute_missing_parameter_name : Error<
   "attribute requires unquoted parameter">;
 def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
index dcd3c5bc434bcade8ef2f87a8438ce4db5effb68..994d45cf7450950a25ddec12b0404dd100da2217 100644 (file)
@@ -163,7 +163,7 @@ Attr *IBOutletAttr::clone(ASTContext &C) const {
 }
 
 Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
-  return ::new (C) IBOutletCollectionAttr(D);
+  return ::new (C) IBOutletCollectionAttr(QT);
 }
 
 Attr *IBActionAttr::clone(ASTContext &C) const {
index aa5ce7aad6a01d5996890eedfc6e83b9439e10d9..a581951da72ce11238f046ac785cb51e53d6e734 100644 (file)
@@ -1190,9 +1190,8 @@ Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
       break;
 
     case attr::IBOutletCollection: {
-      ObjCInterfaceDecl *D =
-        cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
-      New = ::new (*Context) IBOutletCollectionAttr(D);
+      QualType QT = GetType(Record[Idx++]);
+      New = ::new (*Context) IBOutletCollectionAttr(QT);
       break;
     }
 
index 76fd5528dc8f578cf67c60dab471871f21c2e7a2..ac30fd34ccc4dab3256247a85e66c933eb2fc5a6 100644 (file)
@@ -2051,7 +2051,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
 
     case attr::IBOutletCollection: {
       const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
-      AddDeclRef(ICA->getClass(), Record);
+      AddTypeRef(ICA->getType(), Record);
       break;
     }
 
index a234a7379519265f64971af4a48db9ee09a63d04..1e3405768aebee4eff5bfdbd9030802f122b5129 100644 (file)
@@ -263,7 +263,7 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
                                      Sema &S) {
 
   // The iboutletcollection attribute can have zero or one arguments.
-  if (Attr.getNumArgs() > 1) {
+  if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     return;
   }
@@ -274,9 +274,26 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
     S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName();
     return;
   }
-
-  // FIXME: Eventually accept the type argument.
-  d->addAttr(::new (S.Context) IBOutletCollectionAttr());
+  IdentifierInfo *II = Attr.getParameterName();
+  if (!II)
+    II = &S.Context.Idents.get("id");
+  Sema::TypeTy *TypeRep = S.getTypeName(*II, Attr.getLoc(), 
+                        S.getScopeForContext(d->getDeclContext()->getParent()));
+  if (!TypeRep) {
+    S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+    return;
+  }
+  QualType QT(QualType::getFromOpaquePtr(TypeRep));
+  // Diagnose use of non-object type in iboutletcollection attribute.
+  // FIXME. Gnu attribute extension ignores use of builtin types in
+  // attributes. So, __attribute__((iboutletcollection(char))) will be
+  // treated as __attribute__((iboutletcollection())).
+  if (!QT->isObjCIdType() && !QT->isObjCClassType() &&
+      !QT->isObjCObjectType()) {
+    S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+    return;
+  }
+  d->addAttr(::new (S.Context) IBOutletCollectionAttr(QT));
 }
 
 static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
diff --git a/test/SemaObjC/iboutletcollection-attr.m b/test/SemaObjC/iboutletcollection-attr.m
new file mode 100644 (file)
index 0000000..cad4d29
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify %s
+// rdar: // 8308053
+
+@interface I {
+    __attribute__((iboutletcollection(I))) id ivar1;
+    __attribute__((iboutletcollection(id))) id ivar2;
+    __attribute__((iboutletcollection())) id ivar3;
+    __attribute__((iboutletcollection)) id ivar4;
+}
+@property (nonatomic, retain) __attribute__((iboutletcollection(I))) id prop1;
+@property (nonatomic, retain) __attribute__((iboutletcollection(id))) id prop2;
+@property (nonatomic, retain) __attribute__((iboutletcollection())) id prop3;
+@property (nonatomic, retain) __attribute__((iboutletcollection)) id prop4;
+@end
+
+typedef void *PV;
+@interface BAD {
+    __attribute__((iboutletcollection(I, 1))) id ivar1; // expected-error {{attribute requires 1 argument(s)}}
+    __attribute__((iboutletcollection(B))) id ivar2; // expected-error {{invalid type 'B' as argument of iboutletcollection attribue}}
+    __attribute__((iboutletcollection(PV))) id ivar3; // // expected-error {{invalid type 'PV' as argument of iboutletcollection attribue}}
+}
+@property (nonatomic, retain) __attribute__((iboutletcollection(I,2,3))) id prop1; // expected-error {{attribute requires 1 argument(s)}}
+@property (nonatomic, retain) __attribute__((iboutletcollection(B))) id prop2; // expected-error {{invalid type 'B' as argument of iboutletcollection attribue}}
+@end
+