Auto merge of #1410 - emilio:unbreak-osx-stuff, r=emilio

Puts blocks behind a switch.

Since #1378 broke a bunch of OSX builds.

Most people don't care about them and they're in some OSX system headers which
means that this could break normal C and C++ stuff.

This introduces --generate-block / generate_block to generate these signatures,
and adds tests so that this is getting tested.
diff --git a/Cargo.lock b/Cargo.lock
index d8d7cf9..d67dfdd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -26,7 +26,7 @@
 
 [[package]]
 name = "bindgen"
-version = "0.41.0"
+version = "0.42.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cexpr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index e5038f3..f331f18 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@
 repository = "https://github.com/rust-lang-nursery/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
 homepage = "https://rust-lang-nursery.github.io/rust-bindgen/"
-version = "0.41.0"
+version = "0.42.0"
 build = "build.rs"
 
 include = [
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 9119870..3340b4c 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -621,6 +621,10 @@
                 inst.codegen(ctx, result, item)
             }
             TypeKind::BlockPointer(inner) => {
+                if !ctx.options().generate_block {
+                    return;
+                }
+
                 let inner_item = inner.into_resolver()
                     .through_type_refs()
                     .resolve(ctx);
@@ -3135,6 +3139,10 @@
             TypeKind::TemplateAlias(..) |
             TypeKind::Alias(..) |
             TypeKind::BlockPointer(..) => {
+                if self.is_block_pointer() && !ctx.options().generate_block {
+                    let void = raw_type(ctx, "c_void");
+                    return Ok(void.to_ptr(/* is_const = */ false));
+                }
                 let template_params = item.used_template_params(ctx)
                     .into_iter()
                     .filter(|param| param.is_template_param(ctx, &()))
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 22ccdaa..75d5960 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -90,6 +90,14 @@
         self.name.as_ref().map(|name| &**name)
     }
 
+    /// Whether this is a block pointer type.
+    pub fn is_block_pointer(&self) -> bool {
+        match self.kind {
+            TypeKind::BlockPointer(..) => true,
+            _ => false,
+        }
+    }
+
     /// Is this a compound type?
     pub fn is_comp(&self) -> bool {
         match self.kind {
diff --git a/src/lib.rs b/src/lib.rs
index 80191ce..b7608ce 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -373,6 +373,10 @@
             output_vector.push("--objc-extern-crate".into());
         }
 
+        if self.options.generate_block {
+            output_vector.push("--generate-block".into());
+        }
+
         if self.options.block_extern_crate {
             output_vector.push("--block-extern-crate".into());
         }
@@ -704,6 +708,12 @@
         self
     }
 
+    /// Generate proper block signatures instead of void pointers.
+    pub fn generate_block(mut self, doit: bool) -> Self {
+        self.options.generate_block = doit;
+        self
+    }
+
     /// Generate `#[macro_use] extern crate block;` instead of `use block;`
     /// in the prologue of the files generated from apple block files
     pub fn block_extern_crate(mut self, doit: bool) -> Self {
@@ -1467,6 +1477,10 @@
 
     /// Instead of emitting 'use block;' to files generated from objective c files,
     /// generate '#[macro_use] extern crate block;'
+    generate_block: bool,
+
+    /// Instead of emitting 'use block;' to files generated from objective c files,
+    /// generate '#[macro_use] extern crate block;'
     block_extern_crate: bool,
 
     /// Whether to use the clang-provided name mangling. This is true and
@@ -1593,6 +1607,7 @@
             generate_comments: true,
             generate_inline_functions: false,
             whitelist_recursively: true,
+            generate_block: false,
             objc_extern_crate: false,
             block_extern_crate: false,
             enable_mangling: true,
diff --git a/src/options.rs b/src/options.rs
index f72f060..ce89c23 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -132,6 +132,9 @@
             Arg::with_name("objc-extern-crate")
                 .long("objc-extern-crate")
                 .help("Use extern crate instead of use for objc."),
+            Arg::with_name("generate-block")
+                .long("generate-block")
+                .help("Generate block signatures instead of void pointers."),
             Arg::with_name("block-extern-crate")
                 .long("block-extern-crate")
                 .help("Use extern crate instead of use for block."),
@@ -496,6 +499,10 @@
         builder = builder.objc_extern_crate(true);
     }
 
+    if matches.is_present("generate-block") {
+        builder = builder.generate_block(true);
+    }
+
     if matches.is_present("block-extern-crate") {
         builder = builder.block_extern_crate(true);
     }
diff --git a/tests/expectations/tests/blocks-signature.rs b/tests/expectations/tests/blocks-signature.rs
new file mode 100644
index 0000000..69dbbed
--- /dev/null
+++ b/tests/expectations/tests/blocks-signature.rs
@@ -0,0 +1,24 @@
+/* automatically generated by rust-bindgen */
+
+#![allow(
+    dead_code,
+    non_snake_case,
+    non_camel_case_types,
+    non_upper_case_globals
+)]
+#![cfg(target_os = "macos")]
+
+extern crate block;
+extern "C" {
+    #[link_name = "\u{1}_Z8atexit_bU13block_pointerFvvE"]
+    pub fn atexit_b(arg1: _bindgen_ty_id_20);
+}
+pub type dispatch_data_t = *mut ::std::os::raw::c_void;
+pub type dispatch_data_applier_t = _bindgen_ty_id_27;
+extern "C" {
+    #[link_name = "\u{1}_Z19dispatch_data_applyPvU13block_pointerFbS_yPKvyE"]
+    pub fn dispatch_data_apply(data: dispatch_data_t, applier: dispatch_data_applier_t) -> bool;
+}
+pub type _bindgen_ty_id_20 = *const ::block::Block<(), ()>;
+pub type _bindgen_ty_id_27 =
+    *const ::block::Block<(dispatch_data_t, usize, *const ::std::os::raw::c_void, usize), bool>;
diff --git a/tests/expectations/tests/blocks.rs b/tests/expectations/tests/blocks.rs
index e5f0b16..70b616b 100644
--- a/tests/expectations/tests/blocks.rs
+++ b/tests/expectations/tests/blocks.rs
@@ -8,17 +8,13 @@
 )]
 #![cfg(target_os = "macos")]
 
-extern crate block;
 extern "C" {
     #[link_name = "\u{1}_Z8atexit_bU13block_pointerFvvE"]
-    pub fn atexit_b(arg1: _bindgen_ty_id_19);
+    pub fn atexit_b(arg1: *mut ::std::os::raw::c_void);
 }
 pub type dispatch_data_t = *mut ::std::os::raw::c_void;
-pub type dispatch_data_applier_t = _bindgen_ty_id_26;
+pub type dispatch_data_applier_t = *mut ::std::os::raw::c_void;
 extern "C" {
     #[link_name = "\u{1}_Z19dispatch_data_applyPvU13block_pointerFbS_yPKvyE"]
     pub fn dispatch_data_apply(data: dispatch_data_t, applier: dispatch_data_applier_t) -> bool;
 }
-pub type _bindgen_ty_id_19 = *const ::block::Block<(), ()>;
-pub type _bindgen_ty_id_26 =
-    *const ::block::Block<(dispatch_data_t, usize, *const ::std::os::raw::c_void, usize), bool>;
diff --git a/tests/headers/blocks-signature.hpp b/tests/headers/blocks-signature.hpp
new file mode 100644
index 0000000..eaa7252
--- /dev/null
+++ b/tests/headers/blocks-signature.hpp
@@ -0,0 +1,4 @@
+// bindgen-flags: --generate-block --block-extern-crate -- -fblocks
+// bindgen-osx-only
+
+#include "blocks.hpp"