Adds recognition of sentinel attribute on block declarations.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71788 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 7606e84..7a6a537 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -719,10 +719,32 @@
     if (!MD->isVariadic()) {
       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
       return;
-    }    
+    }
+  } else if (isa<BlockDecl>(d)) {
+    // Note! BlockDecl is typeless. Variadic diagnostics
+    // will be issued by the caller.
+    ;
+  } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
+    // FIXME: share code with case of BlockDecl.
+    QualType Ty = V->getType();
+    if (Ty->isBlockPointerType()) {
+      const BlockPointerType *BPT = Ty->getAsBlockPointerType();
+      QualType FnType = BPT->getPointeeType();
+      const FunctionType *FT = FnType->getAsFunctionType();
+      assert(FT && "Block has non-function type?");
+      if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+        S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
+        return;
+      }
+    }
+    else {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 6 /*function, method or */;
+      return;
+    }
   } else {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-      << Attr.getName() << 3 /*function or method*/;
+      << Attr.getName() << 6 /*function, method or */;
     return;
   }
   d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));