]> granicus.if.org Git - clang/commitdiff
Implemenent objective-c's NSObject attribute as a way of ddeclaraing c-type
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 13 Jan 2009 23:34:40 +0000 (23:34 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 13 Jan 2009 23:34:40 +0000 (23:34 +0000)
objects as an objective-c object.

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

include/clang/AST/ASTContext.h
include/clang/AST/Attr.h
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/AttributeList.h
lib/AST/ASTContext.cpp
lib/Parse/AttributeList.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaExpr.cpp
test/SemaObjC/nsobject-attribute.m [new file with mode: 0644]

index ee217522dcd6f6b206a04239a3b612aa6118589a..9c4eb61f94911561ef2c8f0b915ccbccd43fd58a 100644 (file)
@@ -356,6 +356,10 @@ public:
   /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
   /// ID type).
   bool isObjCObjectPointerType(QualType Ty) const;
+  
+  /// isObjCNSObjectType - Return true if this is an NSObject object with
+  /// its NSObject attribute set.
+  bool isObjCNSObjectType(QualType Ty) const;
     
   //===--------------------------------------------------------------------===//
   //                         Type Sizing and Analysis
index 9e9c858126270a9d7b2d641c03cbf6746e95eb28..726d35007226105f9192a4810a11d04fdaff72f8 100644 (file)
@@ -42,6 +42,7 @@ public:
     NoReturn,
     NoThrow,
     ObjCGC,
+    ObjCNSObject,
     Packed,
     StdCall,
     TransparentUnion,
@@ -418,6 +419,15 @@ public:
   static bool classof(const ObjCGCAttr *A) { return true; }
 };
 
+class ObjCNSObjectAttr : public Attr {
+// Implement isa/cast/dyncast/etc.
+public:
+  ObjCNSObjectAttr() : Attr(ObjCNSObject) {}
+  
+static bool classof(const Attr *A) { return A->getKind() == ObjCNSObject; }
+static bool classof(const ObjCNSObjectAttr *A) { return true; }
+};
+  
 class BlocksAttr : public Attr {
 public:
   enum BlocksAttrTypes {
@@ -433,7 +443,7 @@ public:
   // Implement isa/cast/dyncast/etc.
 
   static bool classof(const Attr *A) { return A->getKind() == Blocks; }
-  static bool classof(const ObjCGCAttr *A) { return true; }
+  static bool classof(const BlocksAttr *A) { return true; }
 };
 
 }  // end namespace clang
index 52c6cbf2fa681a46d91c064216560cae4720e0f5..10117b98eae305985e2fb9b9249f73525e836e38 100644 (file)
@@ -412,6 +412,8 @@ DIAG(err_expected_asm_operand, ERROR,
      "expected string literal or '[' for asm operand")
 DIAG(err_expected_selector_for_method, ERROR,
      "expected selector for Objective-C method")
+DIAG(err_nsobject_attribute, ERROR,
+     "__attribute ((NSObject)) is for pointer types only")
 
 DIAG(err_unexpected_at, ERROR,
      "unexpected '@' in program")
index d3e546204c92bd862b260848f60a654be45b233b..9c8c70945e11bfc61890497a8f43f6d1e32ff797 100644 (file)
@@ -76,6 +76,7 @@ public:
     AT_blocks,
     AT_sentinel,
     AT_const,
+    AT_nsobject,
     UnknownAttribute
   };
   
index b5487565ae76dd1e4d221bafbef2f918ec5fca8a..c64c1010bee729b90fbb070e71e6da91459e2ef0 100644 (file)
@@ -2078,6 +2078,19 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
 //                        Type Predicates.
 //===----------------------------------------------------------------------===//
 
+/// isObjCNSObjectType - Return true if this is an NSObject object using
+/// NSObject attribute on a c-style pointer type.
+/// FIXME - Make it work directly on types.
+///
+bool ASTContext::isObjCNSObjectType(QualType Ty) const {
+  if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
+    if (TypedefDecl *TD = TDT->getDecl())
+      if (TD->getAttr<ObjCNSObjectAttr>())
+        return true;
+  }
+  return false;  
+}
+
 /// isObjCObjectPointerType - Returns true if type is an Objective-C pointer
 /// to an object type.  This includes "id" and "Class" (two 'special' pointers
 /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
@@ -2101,7 +2114,11 @@ bool ASTContext::isObjCObjectPointerType(QualType Ty) const {
     return true;
   
   // If this a pointer to an interface (e.g. NSString*), it is ok.
-  return Ty->getAsPointerType()->getPointeeType()->isObjCInterfaceType();
+  if (Ty->getAsPointerType()->getPointeeType()->isObjCInterfaceType())
+    return true;
+  
+  // If is has NSObject attribute, OK as well.
+  return isObjCNSObjectType(Ty);
 }
 
 //===----------------------------------------------------------------------===//
index 0a418bb9cc19a06228674d0b4bcd629e8da98b89..6c1583a0feb97ab81115a8784935b2f598eadd51 100644 (file)
@@ -81,6 +81,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
     if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
     if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
     if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
+    if (!memcmp(Str, "NSObject", 8)) return AT_nsobject;
     break;
   case 9:
     if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
index 759ef0950b54ff0f89bcef0080fece79918b0816..f444c71e4f5e8c285ab27d6194bb480d842cbbf9 100644 (file)
@@ -578,6 +578,22 @@ static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   d->addAttr(new ObjCGCAttr(type));
 }
 
+static void HandleObjCNSObject(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(d)) {
+    QualType T = TD->getUnderlyingType();
+    if (!T->isPointerType() ||
+        !T->getAsPointerType()->getPointeeType()->isRecordType()) {
+      S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
+      return;
+    }
+  }
+  d->addAttr(new ObjCNSObjectAttr);
+}
+
 static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   if (!Attr.getParameterName()) {    
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
@@ -1228,6 +1244,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
     HandleTransparentUnionAttr(D, Attr, S);
     break;
   case AttributeList::AT_objc_gc:     HandleObjCGCAttr    (D, Attr, S); break;
+  case AttributeList::AT_nsobject:    HandleObjCNSObject  (D, Attr, S); break;
   case AttributeList::AT_blocks:      HandleBlocksAttr    (D, Attr, S); break;
   case AttributeList::AT_sentinel:    HandleSentinelAttr  (D, Attr, S); break;
   case AttributeList::AT_const:       HandleConstAttr     (D, Attr, S); break;
index d7a041d0ecf9d2d20b6c9bacf2fa4438dac90e12..0c97611618086778ebfe13aa48bd3b86a9a500af 100644 (file)
@@ -3023,7 +3023,14 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
   if (CompoundType.isNull()) {
     // Simple assignment "x = y".
     ConvTy = CheckSingleAssignmentConstraints(LHSType, RHS);
-    
+    // Special case of NSObject attributes on c-style pointer types.
+    if (ConvTy == IncompatiblePointer &&
+        ((Context.isObjCNSObjectType(LHSType) &&
+          Context.isObjCObjectPointerType(RHSType)) ||
+         (Context.isObjCNSObjectType(RHSType) &&
+          Context.isObjCObjectPointerType(LHSType))))
+      ConvTy = Compatible;
+  
     // If the RHS is a unary plus or minus, check to see if they = and + are
     // right next to each other.  If so, the user may have typo'd "x =+ 4"
     // instead of "x += 4".
diff --git a/test/SemaObjC/nsobject-attribute.m b/test/SemaObjC/nsobject-attribute.m
new file mode 100644 (file)
index 0000000..5243a72
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: clang -fsyntax-only -verify %s
+
+typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef;
+static int count;
+static CGColorRef tmp = 0;
+
+typedef struct S1  __attribute__ ((NSObject)) CGColorRef1; // expected-error {{__attribute ((NSObject)) is for pointer types only}}
+typedef void *  __attribute__ ((NSObject)) CGColorRef2; // expected-error {{__attribute ((NSObject)) is for pointer types only}}
+
+@interface HandTested {
+@public
+    CGColorRef x;
+}
+@property(copy) CGColorRef x;
+@end
+
+void setProperty(id self, id value)  {
+  ((HandTested *)self)->x = value;
+}
+
+id getProperty(id self) {
+     return (id)((HandTested *)self)->x;
+}
+
+@implementation HandTested
+@synthesize x=x;
+@end
+
+int main(char *argc, char *argv[]) {
+    HandTested *to;
+    to.x = tmp;  // setter
+    if (tmp != to.x)
+      to.x = tmp;
+    return 0;
+}
+