]> granicus.if.org Git - clang/commitdiff
add parser and type checking support for attribute((objc_exception)).
authorChris Lattner <sabre@nondot.org>
Sat, 14 Feb 2009 08:09:34 +0000 (08:09 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 14 Feb 2009 08:09:34 +0000 (08:09 +0000)
We don't have "zero cost" exceptions for ObjC yet, so there is no codegen
support required.

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

include/clang/AST/Attr.h
include/clang/Basic/DiagnosticSemaKinds.def
include/clang/Parse/AttributeList.h
lib/Parse/AttributeList.cpp
lib/Sema/SemaDeclAttr.cpp
test/SemaObjC/attr-objc-exception.m [new file with mode: 0644]

index fcfc54e2f6a37c37a43f3c8ece985e3f3cd7d304..288a1c4a328371b109ed5780c7f57466f9d89abf 100644 (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) { }
index ee9a8d388bfe6060b6ed9ca3307d7d3a071717c6..95d7001ed9b3f98b5feeb5933f954544a03915f4 100644 (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,
index 7775981baf53b01bd78ae5d9754d078ee6a23121..97ad2917ba1a9a7a425561002f572eaf5ca5ce94 100644 (file)
@@ -75,6 +75,7 @@ public:
     AT_warn_unused_result,
     AT_weak,
     AT_objc_gc,
+    AT_objc_exception,
     AT_blocks,
     AT_sentinel,
     AT_const,
index 6ce55ea5c59de9be59abfad0c2d6e5499dbf42bc..06cd67abe50372006805de8e90a7a2028d2c76f8 100644 (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;
index 347d8f5e0739f978e2a0d3b519583e3cfe0e2983..a28d0a6d6de18520b7e43708ac75f7230f32227e 100644 (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;
diff --git a/test/SemaObjC/attr-objc-exception.m b/test/SemaObjC/attr-objc-exception.m
new file mode 100644 (file)
index 0000000..12d0b31
--- /dev/null
@@ -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();
+