diff options
-rw-r--r-- | include/clang/AST/Attr.h | 26 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.def | 2 | ||||
-rw-r--r-- | include/clang/Parse/AttributeList.h | 1 | ||||
-rw-r--r-- | lib/Parse/AttributeList.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 34 | ||||
-rw-r--r-- | test/SemaObjC/attr-objc-exception.m | 16 |
6 files changed, 65 insertions, 17 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index fcfc54e2f6..288a1c4a32 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -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) { } diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index ee9a8d388b..95d7001ed9 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -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, diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 7775981baf..97ad2917ba 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -75,6 +75,7 @@ public: AT_warn_unused_result, AT_weak, AT_objc_gc, + AT_objc_exception, AT_blocks, AT_sentinel, AT_const, diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 6ce55ea5c5..06cd67abe5 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -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; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 347d8f5e07..a28d0a6d6d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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; diff --git a/test/SemaObjC/attr-objc-exception.m b/test/SemaObjC/attr-objc-exception.m new file mode 100644 index 0000000000..12d0b31ce8 --- /dev/null +++ b/test/SemaObjC/attr-objc-exception.m @@ -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(); + |