]> granicus.if.org Git - clang/commitdiff
Patch finishes off application of printf attribute on blocks.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 19 May 2009 17:08:59 +0000 (17:08 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 19 May 2009 17:08:59 +0000 (17:08 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72111 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaExpr.cpp
test/Sema/block-printf-attribute-1.c [new file with mode: 0644]

index 0bf86876e29326d3f0300e4666f0b14866c17e6e..4c4763f48ea64627fff154c03ad2c87103a98ae0 100644 (file)
@@ -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; }
index 2c2e4d3c0f1860b77a5a4b7bb451723182a6e699..c5099319ddb03b6a3cf7e4c586c3823011ea3aa5 100644 (file)
@@ -64,7 +64,7 @@ static bool isFunctionOrMethodOrBlock(Decl *d) {
     QualType Ty = V->getType();
     return Ty->isBlockPointerType();
   }
-  return false;
+  return isa<BlockDecl>(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<FunctionProtoType>(FnTy);
   else {
-    assert(isa<ObjCMethodDecl>(d));
+    assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(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<FunctionProtoType>(FnTy)->getNumArgs();
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+    return BD->getNumParams();
   return cast<ObjCMethodDecl>(d)->param_size();
 }
 
 static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) {
   if (const FunctionType *FnTy = getFunctionType(d))
     return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
-  
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+    return BD->getParamDecl(Idx)->getType();
   
   return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
 }
@@ -100,7 +103,9 @@ static bool isFunctionOrMethodVariadic(Decl *d) {
   if (const FunctionType *FnTy = getFunctionType(d)) {
     const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
     return proto->isVariadic();
-  } else {
+  } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+    return BD->IsVariadic();
+  else {
     return cast<ObjCMethodDecl>(d)->isVariadic();
   }
 }
index ed62b254d560f0c5af1548a3a73bbf34e9bb0a49..3f99c684b8921925d851c5792a05b8be05810d67 100644 (file)
@@ -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 (file)
index 0000000..ce30b8e
--- /dev/null
@@ -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
+
+}
+