add parser and type checking support for attribute((objc_exception)).

We don't have "zero cost" exceptions for ObjC yet, so there is no codegen
support required.

llvm-svn: 64546
This commit is contained in:
Chris Lattner 2009-02-14 08:09:34 +00:00
parent 9844408ad6
commit 677a35804f
6 changed files with 65 additions and 17 deletions

View File

@ -43,6 +43,7 @@ public:
NoThrow,
ObjCGC,
ObjCNSObject,
ObjCException,
Overloadable, // Clang-specific
Packed,
Section,
@ -290,7 +291,6 @@ public:
NoThrowAttr() : Attr(NoThrow) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == NoThrow; }
static bool classof(const NoThrowAttr *A) { return true; }
};
@ -300,7 +300,6 @@ public:
ConstAttr() : Attr(Const) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Const; }
static bool classof(const ConstAttr *A) { return true; }
};
@ -310,7 +309,6 @@ public:
PureAttr() : Attr(Pure) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Pure; }
static bool classof(const PureAttr *A) { return true; }
};
@ -322,12 +320,11 @@ public:
NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull),
ArgNums(0), Size(0) {
if (size) {
assert (arg_nums);
ArgNums = new unsigned[size];
Size = size;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
}
if (size == 0) return;
assert(arg_nums);
ArgNums = new unsigned[size];
Size = size;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
}
virtual ~NonNullAttr() {
@ -459,6 +456,17 @@ static bool classof(const Attr *A) { return A->getKind() == ObjCNSObject; }
static bool classof(const ObjCNSObjectAttr *A) { return true; }
};
class ObjCExceptionAttr : public Attr {
public:
ObjCExceptionAttr() : Attr(ObjCException) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == ObjCException; }
static bool classof(const ObjCExceptionAttr *A) { return true; }
};
class OverloadableAttr : public Attr {
public:
OverloadableAttr() : Attr(Overloadable) { }

View File

@ -314,6 +314,8 @@ DIAG(err_attribute_argument_n_not_string, ERROR,
"'%0' attribute requires parameter %1 to be a string")
DIAG(err_attribute_argument_out_of_bounds, ERROR,
"'%0' attribute parameter %1 is out of bounds")
DIAG(err_attribute_requires_objc_interface, ERROR,
"attribute may only be applied to an Objective-C interface")
DIAG(err_nonnull_pointers_only, ERROR,
"nonnull attribute only applies to pointer arguments")
DIAG(err_format_strftime_third_parameter, ERROR,

View File

@ -75,6 +75,7 @@ public:
AT_warn_unused_result,
AT_weak,
AT_objc_gc,
AT_objc_exception,
AT_blocks,
AT_sentinel,
AT_const,

View File

@ -110,6 +110,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
if (!memcmp(Str, "address_space", 13)) return AT_address_space;
if (!memcmp(Str, "always_inline", 13)) return AT_always_inline;
break;
case 14:
if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception;
break;
case 15:
if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
break;

View File

@ -568,7 +568,7 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(new VisibilityAttr(type));
}
static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleObjCGCAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (!Attr.getParameterName()) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
<< "objc_gc" << 1;
@ -579,11 +579,10 @@ static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
ObjCGCAttr::GCAttrTypes type;
if (Attr.getParameterName()->isStr("weak")) {
if (isa<FieldDecl>(d) && !isa<ObjCIvarDecl>(d))
if (isa<FieldDecl>(D) && !isa<ObjCIvarDecl>(D))
S.Diag(Attr.getLoc(), diag::warn_attribute_weak_on_field);
type = ObjCGCAttr::Weak;
}
@ -595,15 +594,31 @@ static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
d->addAttr(new ObjCGCAttr(type));
D->addAttr(new ObjCGCAttr(type));
}
static void HandleObjCNSObject(Decl *d, const AttributeList &Attr, Sema &S) {
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
Sema &S) {
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return;
}
ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
if (OCI == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
return;
}
D->addAttr(new ObjCExceptionAttr());
}
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)) {
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
QualType T = TD->getUnderlyingType();
if (!T->isPointerType() ||
!T->getAsPointerType()->getPointeeType()->isRecordType()) {
@ -611,7 +626,7 @@ static void HandleObjCNSObject(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
}
d->addAttr(new ObjCNSObjectAttr);
D->addAttr(new ObjCNSObjectAttr);
}
static void
@ -1406,6 +1421,9 @@ 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_objc_exception:
HandleObjCExceptionAttr(D, Attr, S);
break;
case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;

View File

@ -0,0 +1,16 @@
// RUN: clang %s -fsyntax-only -verify
__attribute__((__objc_exception__))
@interface NSException {
int x;
}
@end
__attribute__((__objc_exception__)) // expected-error {{attribute may only be applied to an Objective-C interface}}
int X;
__attribute__((__objc_exception__)) // expected-error {{attribute may only be applied to an Objective-C interface}}
void foo();