aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-09-26 04:12:28 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-09-26 04:12:28 +0000
commit3568249c2d72d58b835a22d9186f5a6b4fc4bcd6 (patch)
tree8fa6fb9164338d856a97353a5aa6dfcd609d27b6
parent085e8f7da37a227ceee7f98b724e0a42e04d01ca (diff)
Sema support for format and noreturn attributes on Objective-C methods.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56640 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclAttr.cpp47
-rw-r--r--lib/Sema/SemaDeclObjC.cpp5
-rw-r--r--test/SemaObjC/method-attributes.m8
3 files changed, 50 insertions, 10 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 764724aeca..2bdb885f53 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -45,6 +45,40 @@ static const FunctionTypeProto *getFunctionProto(Decl *d) {
return 0;
}
+// FIXME: We should provide an abstraction around a method or function
+// to provide the following bits of information.
+
+/// isFunctionOrMethod - Return true if the given decl is a (non-K&R)
+/// function or an Objective-C method.
+static bool isFunctionOrMethod(Decl *d) {
+ return getFunctionProto(d) || isa<ObjCMethodDecl>(d);
+
+}
+
+static unsigned getFunctionOrMethodNumArgs(Decl *d) {
+ if (const FunctionTypeProto *proto = getFunctionProto(d)) {
+ return proto->getNumArgs();
+ } else {
+ return cast<ObjCMethodDecl>(d)->getNumParams();
+ }
+}
+
+static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) {
+ if (const FunctionTypeProto *proto = getFunctionProto(d)) {
+ return proto->getArgType(Idx);
+ } else {
+ return cast<ObjCMethodDecl>(d)->getParamDecl(Idx)->getType();
+ }
+}
+
+static bool isFunctionOrMethodVariadic(Decl *d) {
+ if (const FunctionTypeProto *proto = getFunctionProto(d)) {
+ return proto->isVariadic();
+ } else {
+ return cast<ObjCMethodDecl>(d)->isVariadic();
+ }
+}
+
static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
const PointerType *PT = T->getAsPointerType();
if (!PT)
@@ -360,8 +394,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
- if (!Fn) {
+ if (!isa<FunctionDecl>(d) && !isa<ObjCMethodDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
"noreturn", "function");
return;
@@ -637,9 +670,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// GCC ignores the format attribute on K&R style function
// prototypes, so we ignore it as well
- const FunctionTypeProto *proto = getFunctionProto(d);
-
- if (!proto) {
+ if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
"format", "function");
return;
@@ -648,7 +679,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: in C++ the implicit 'this' function parameter also counts.
// this is needed in order to be compatible with GCC
// the index must start in 1 and the limit is numargs+1
- unsigned NumArgs = proto->getNumArgs();
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d);
unsigned FirstIdx = 1;
const char *Format = Attr.getParameterName()->getName();
@@ -703,7 +734,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned ArgIdx = Idx.getZExtValue() - 1;
// make sure the format string is really a string
- QualType Ty = proto->getArgType(ArgIdx);
+ QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
if (is_CFString) {
if (!isCFStringType(Ty, S.Context)) {
@@ -741,7 +772,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check if the function is variadic if the 3rd argument non-zero
if (FirstArg != 0) {
- if (proto->isVariadic()) {
+ if (isFunctionOrMethodVariadic(d)) {
++NumArgs; // +1 for ...
} else {
S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index dbb3cf22ad..1b166c4094 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -978,8 +978,6 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
MethodDeclKind == tok::objc_optional ?
ObjCMethodDecl::Optional :
ObjCMethodDecl::Required);
- if (AttrList)
- ProcessDeclAttributeList(ObjCMethod, AttrList);
llvm::SmallVector<ParmVarDecl*, 16> Params;
@@ -1004,6 +1002,9 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
ObjCMethod->setObjCDeclQualifier(
CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
const ObjCMethodDecl *PrevMethod = 0;
+
+ if (AttrList)
+ ProcessDeclAttributeList(ObjCMethod, AttrList);
// For implementations (which can be very "coarse grain"), we add the
// method now. This allows the AST to implement lookup methods that work
diff --git a/test/SemaObjC/method-attributes.m b/test/SemaObjC/method-attributes.m
new file mode 100644
index 0000000000..d16d6ffe78
--- /dev/null
+++ b/test/SemaObjC/method-attributes.m
@@ -0,0 +1,8 @@
+// RUN: clang -fsyntax-only %s
+
+@class NSString;
+
+@interface A
+-t1 __attribute__((noreturn));
+- (NSString *)stringByAppendingFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2)));
+@end