Implemenent objective-c's NSObject attribute as a way of ddeclaraing c-type
objects as an objective-c object. llvm-svn: 62197
This commit is contained in:
parent
a63bede3c6
commit
255c0958dd
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
AT_blocks,
|
||||
AT_sentinel,
|
||||
AT_const,
|
||||
AT_nsobject,
|
||||
UnknownAttribute
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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".
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue