From: Daniel Dunbar Date: Fri, 26 Sep 2008 04:12:28 +0000 (+0000) Subject: Sema support for format and noreturn attributes on Objective-C methods. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3568249c2d72d58b835a22d9186f5a6b4fc4bcd6;p=clang 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 --- 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(d); + +} + +static unsigned getFunctionOrMethodNumArgs(Decl *d) { + if (const FunctionTypeProto *proto = getFunctionProto(d)) { + return proto->getNumArgs(); + } else { + return cast(d)->getNumParams(); + } +} + +static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) { + if (const FunctionTypeProto *proto = getFunctionProto(d)) { + return proto->getArgType(Idx); + } else { + return cast(d)->getParamDecl(Idx)->getType(); + } +} + +static bool isFunctionOrMethodVariadic(Decl *d) { + if (const FunctionTypeProto *proto = getFunctionProto(d)) { + return proto->isVariadic(); + } else { + return cast(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(d); - if (!Fn) { + if (!isa(d) && !isa(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 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