aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Attr.h26
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def2
-rw-r--r--include/clang/Parse/AttributeList.h1
-rw-r--r--lib/Parse/AttributeList.cpp3
-rw-r--r--lib/Sema/SemaDeclAttr.cpp34
-rw-r--r--test/SemaObjC/attr-objc-exception.m16
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();
+