From: Fariborz Jahanian Date: Tue, 19 May 2009 17:08:59 +0000 (+0000) Subject: Patch finishes off application of printf attribute on blocks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d66f22d9f8423579322a6dd16587ed52b0a58834;p=clang Patch finishes off application of printf attribute on blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72111 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0bf86876e2..4c4763f48e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1211,6 +1211,8 @@ public: /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } /// class BlockDecl : public Decl, public DeclContext { + // FIXME: This can be packed into the bitfields in Decl. + bool isVariadic : 1; /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. @@ -1222,7 +1224,7 @@ class BlockDecl : public Decl, public DeclContext { protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), - ParamInfo(0), NumParams(0), Body(0) {} + isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} virtual ~BlockDecl(); virtual void Destroy(ASTContext& C); @@ -1232,6 +1234,9 @@ public: SourceLocation getCaretLocation() const { return getLocation(); } + bool IsVariadic() const { return isVariadic; } + void setIsVariadic(bool value) { isVariadic = value; } + CompoundStmt *getBody() const { return (CompoundStmt*) Body; } Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; } void setBody(CompoundStmt *B) { Body = (Stmt*) B; } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 2c2e4d3c0f..c5099319dd 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -64,7 +64,7 @@ static bool isFunctionOrMethodOrBlock(Decl *d) { QualType Ty = V->getType(); return Ty->isBlockPointerType(); } - return false; + return isa(d); } /// hasFunctionProto - Return true if the given decl has a argument @@ -74,7 +74,7 @@ static bool hasFunctionProto(Decl *d) { if (const FunctionType *FnTy = getFunctionType(d)) return isa(FnTy); else { - assert(isa(d)); + assert(isa(d) || isa(d)); return true; } } @@ -85,13 +85,16 @@ static bool hasFunctionProto(Decl *d) { static unsigned getFunctionOrMethodNumArgs(Decl *d) { if (const FunctionType *FnTy = getFunctionType(d)) return cast(FnTy)->getNumArgs(); + if (const BlockDecl *BD = dyn_cast(d)) + return BD->getNumParams(); return cast(d)->param_size(); } static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) { if (const FunctionType *FnTy = getFunctionType(d)) return cast(FnTy)->getArgType(Idx); - + if (const BlockDecl *BD = dyn_cast(d)) + return BD->getParamDecl(Idx)->getType(); return cast(d)->param_begin()[Idx]->getType(); } @@ -100,7 +103,9 @@ static bool isFunctionOrMethodVariadic(Decl *d) { if (const FunctionType *FnTy = getFunctionType(d)) { const FunctionProtoType *proto = cast(FnTy); return proto->isVariadic(); - } else { + } else if (const BlockDecl *BD = dyn_cast(d)) + return BD->IsVariadic(); + else { return cast(d)->isVariadic(); } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ed62b254d5..3f99c684b8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5140,7 +5140,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { } CurBlock->TheDecl->setParams(Context, &CurBlock->Params[0], CurBlock->Params.size()); - + CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo); for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), E = CurBlock->TheDecl->param_end(); AI != E; ++AI) diff --git a/test/Sema/block-printf-attribute-1.c b/test/Sema/block-printf-attribute-1.c new file mode 100644 index 0000000000..ce30b8e855 --- /dev/null +++ b/test/Sema/block-printf-attribute-1.c @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fblocks + +int main() +{ + void (^b) (int arg, const char * format, ...) __attribute__ ((__format__ (__printf__, 1, 3))) = // expected-error {{format argument not a string type}} + ^ __attribute__ ((__format__ (__printf__, 1, 3))) (int arg, const char * format, ...) {}; // expected-error {{format argument not a string type}} + + void (^z) (int arg, const char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3))) = ^ __attribute__ ((__format__ (__printf__, 2, 3))) (int arg, const char * format, ...) {}; + + // FIXME: argument type poking not yet supportted. + z(1, "%s", 1); /* { dg-warning "format \\'\%s\\' expects type \\'char \\*\\'\, but argument 3 has type \\'int\\'" } */ + z(1, "%s", "HELLO"); // OK + +} +