From fa23c1d9adc99c662c1c0e192817185809d95614 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 13 Jan 2009 23:34:40 +0000 Subject: [PATCH] Implemenent objective-c's NSObject attribute as a way of ddeclaraing c-type 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 | 4 +++ include/clang/AST/Attr.h | 12 ++++++++- include/clang/Basic/DiagnosticKinds.def | 2 ++ include/clang/Parse/AttributeList.h | 1 + lib/AST/ASTContext.cpp | 19 ++++++++++++- lib/Parse/AttributeList.cpp | 1 + lib/Sema/SemaDeclAttr.cpp | 17 ++++++++++++ lib/Sema/SemaExpr.cpp | 9 ++++++- test/SemaObjC/nsobject-attribute.m | 36 +++++++++++++++++++++++++ 9 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 test/SemaObjC/nsobject-attribute.m diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ee217522dc..9c4eb61f94 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -356,6 +356,10 @@ public: /// to struct), Interface* (pointer to ObjCInterfaceType) and id

(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 diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 9e9c858126..726d350072 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -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 diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 52c6cbf2fa..10117b98ea 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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") diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index d3e546204c..9c8c70945e 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -76,6 +76,7 @@ public: AT_blocks, AT_sentinel, AT_const, + AT_nsobject, UnknownAttribute }; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b5487565ae..c64c1010be 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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(Ty)) { + if (TypedefDecl *TD = TDT->getDecl()) + if (TD->getAttr()) + 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

(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); } //===----------------------------------------------------------------------===// diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 0a418bb9cc..6c1583a0fe 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -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; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 759ef0950b..f444c71e4f 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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(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; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d7a041d0ec..0c97611618 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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 index 0000000000..5243a72f69 --- /dev/null +++ b/test/SemaObjC/nsobject-attribute.m @@ -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; +} + -- 2.40.0