diff options
author | Nuno Lopes <nunoplopes@sapo.pt> | 2008-03-25 23:01:48 +0000 |
---|---|---|
committer | Nuno Lopes <nunoplopes@sapo.pt> | 2008-03-25 23:01:48 +0000 |
commit | 623207d603653cf71d18b26d25ad79e2b7b096e5 (patch) | |
tree | b9c78c1dcfb8f3004a29ffbf64ff66fccf6e610e | |
parent | 5efdf8457fee9f8587c201ac67b80aca5cd050b7 (diff) | |
download | bcm5719-llvm-623207d603653cf71d18b26d25ad79e2b7b096e5.tar.gz bcm5719-llvm-623207d603653cf71d18b26d25ad79e2b7b096e5.zip |
allow the format attribute to be specified in function pointer prototypes
# this is my first commit here, so please be gentle :)
llvm-svn: 48807
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 32 | ||||
-rw-r--r-- | clang/test/Sema/format-attribute.c | 3 |
2 files changed, 27 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index eea285cf41a..e9922dfdf99 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2136,6 +2136,24 @@ void Sema::HandleNothrowAttribute(Decl *d, AttributeList *rawAttr) { d->addAttr(new NoThrowAttr()); } +static const FunctionTypeProto *getFunctionProto(Decl *d) { + ValueDecl *decl = dyn_cast<ValueDecl>(d); + if (!decl) return 0; + + QualType Ty = decl->getType(); + + if (Ty->isFunctionPointerType()) { + const PointerType *PtrTy = Ty->getAsPointerType(); + Ty = PtrTy->getPointeeType(); + } + + if (const FunctionType *FnTy = Ty->getAsFunctionType()) + return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType()); + + return 0; +} + + /// Handle __attribute__((format(type,idx,firstarg))) attributes /// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html void Sema::HandleFormatAttribute(Decl *d, AttributeList *rawAttr) { @@ -2152,22 +2170,20 @@ void Sema::HandleFormatAttribute(Decl *d, AttributeList *rawAttr) { return; } - FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); - if (!Fn) { + // GCC ignores the format attribute on K&R style function + // prototypes, so we ignore it as well + const FunctionTypeProto *proto = getFunctionProto(d); + + if (!proto) { Diag(rawAttr->getLoc(), diag::warn_attribute_wrong_decl_type, "format", "function"); return; } - const FunctionTypeProto *proto = - dyn_cast<FunctionTypeProto>(Fn->getType()->getAsFunctionType()); - if (!proto) - return; - // 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 = Fn->getNumParams(); + unsigned NumArgs = proto->getNumArgs(); unsigned FirstIdx = 1; const char *Format = rawAttr->getParameterName()->getName(); diff --git a/clang/test/Sema/format-attribute.c b/clang/test/Sema/format-attribute.c index 0b166e3c4dc..df3e4b59591 100644 --- a/clang/test/Sema/format-attribute.c +++ b/clang/test/Sema/format-attribute.c @@ -14,3 +14,6 @@ void g(xpto c) __attribute__((format(printf, 1, 0))); // no-error void y(char *str) __attribute__((format(strftime, 1,0))); // no-error void z(char *str, int c, ...) __attribute__((format(strftime, 1,2))); // expected-error {{strftime format attribute requires 3rd parameter to be 0}} + +int (*f_ptr)(char*,...) __attribute__((format(printf, 1,2))); // no-error +int (*f2_ptr)(double,...) __attribute__((format(printf, 1, 2))); // expected-error {{format argument not a string type}} |