Auto merge of #686 - emilio:bump, r=fitzgen

Breaking version bump.

After all the huge work @fitzgen has been doing diagnosing stylo issues, we seem ready to try again!

Also, a lot of issues have been fixed lately.
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 39b115f..697c140 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2805,7 +2805,8 @@
 
 fn objc_method_codegen(ctx: &BindgenContext,
                        method: &ObjCMethod,
-                       class_name: Option<&str>)
+                       class_name: Option<&str>,
+                       prefix: &str)
                        -> (ast::ImplItem, ast::TraitItem) {
     let signature = method.signature();
     let fn_args = utils::fnsig_arguments(ctx, signature);
@@ -2864,9 +2865,11 @@
 
     let attrs = vec![];
 
+    let method_name = format!("{}{}", prefix, method.rust_name());
+
     let impl_item = ast::ImplItem {
         id: ast::DUMMY_NODE_ID,
-        ident: ctx.rust_ident(method.rust_name()),
+        ident: ctx.rust_ident(&method_name),
         vis: ast::Visibility::Inherited, // Public,
         attrs: attrs.clone(),
         node: ast::ImplItemKind::Method(sig.clone(), P(block)),
@@ -2876,7 +2879,7 @@
 
     let trait_item = ast::TraitItem {
         id: ast::DUMMY_NODE_ID,
-        ident: ctx.rust_ident(method.rust_name()),
+        ident: ctx.rust_ident(&method_name),
         attrs: attrs,
         node: ast::TraitItemKind::Method(sig, None),
         span: ctx.span(),
@@ -2898,14 +2901,23 @@
 
         for method in self.methods() {
             let (impl_item, trait_item) =
-                objc_method_codegen(ctx, method, None);
+                objc_method_codegen(ctx, method, None, "");
             impl_items.push(impl_item);
             trait_items.push(trait_item)
         }
 
+        let instance_method_names : Vec<_> = self.methods().iter().map( { |m| m.rust_name() } ).collect();
+
         for class_method in self.class_methods() {
+
+            let ambiquity = instance_method_names.contains(&class_method.rust_name());
+            let prefix = if ambiquity {
+                    "class_"
+                } else {
+                    ""
+                };
             let (impl_item, trait_item) =
-                objc_method_codegen(ctx, class_method, Some(self.name()));
+                objc_method_codegen(ctx, class_method, Some(self.name()), prefix);
             impl_items.push(impl_item);
             trait_items.push(trait_item)
         }
@@ -2982,13 +2994,13 @@
                                result: &mut Vec<P<ast::Item>>) {
         let use_objc = if ctx.options().objc_extern_crate {
             quote_item!(ctx.ext_cx(),
-                use objc;
+                #[macro_use]
+                extern crate objc;
             )
                 .unwrap()
         } else {
             quote_item!(ctx.ext_cx(),
-                #[macro_use]
-                extern crate objc;
+                use objc;
             )
                 .unwrap()
         };
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 23503b0..0168973 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -284,7 +284,9 @@
 
         let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
                              cursor.kind() == CXCursor_ObjCClassMethodDecl {
-            try!(cursor.ret_type().ok_or(ParseError::Continue))
+            try!(ty.ret_type()
+                   .or_else(|| cursor.ret_type())
+                   .ok_or(ParseError::Continue))
         } else {
             try!(ty.ret_type().ok_or(ParseError::Continue))
         };
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index c3f2657..a9054e9 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -836,6 +836,24 @@
             _ => {}
         }
 
+        // Objective C template type parameter
+        // FIXME: This is probably wrong, we are attempting to find the
+        //        objc template params, which seem to manifest as a typedef.
+        //        We are rewriting them as id to suppress multiple conflicting
+        //        typedefs at root level
+        if ty_kind == CXType_Typedef {
+            let is_template_type_param = ty.declaration().kind() == CXCursor_TemplateTypeParameter;
+            let is_canonical_objcpointer = canonical_ty.kind() == CXType_ObjCObjectPointer;
+
+            // We have found a template type for objc interface
+            if is_canonical_objcpointer && is_template_type_param {
+                // Objective-C generics are just ids with fancy name.
+                // To keep it simple, just name them ids
+                name = "id".to_owned();
+            }
+
+        }
+
         if location.kind() == CXCursor_ClassTemplatePartialSpecialization {
             // Sorry! (Not sorry)
             warn!("Found a partial template specialization; bindgen does not \
diff --git a/src/options.rs b/src/options.rs
index ca54dbc..bbf9c0d 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -341,6 +341,10 @@
         builder = builder.whitelist_recursively(false);
     }
 
+    if matches.is_present("objc-extern-crate") {
+        builder = builder.objc_extern_crate(true);
+    }
+
     if let Some(opaque_types) = matches.values_of("opaque-type") {
         for ty in opaque_types {
             builder = builder.opaque_type(ty);
diff --git a/tests/expectations/tests/objc_method_clash.rs b/tests/expectations/tests/objc_method_clash.rs
new file mode 100644
index 0000000..07dedc4
--- /dev/null
+++ b/tests/expectations/tests/objc_method_clash.rs
@@ -0,0 +1,22 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+#![cfg(target_os="macos")]
+
+#[macro_use]
+extern crate objc;
+#[allow(non_camel_case_types)]
+pub type id = *mut objc::runtime::Object;
+pub trait Foo {
+    unsafe fn foo(self);
+    unsafe fn class_foo();
+}
+impl Foo for id {
+    unsafe fn foo(self) { msg_send!(self , foo) }
+    unsafe fn class_foo() {
+        msg_send!(objc :: runtime :: Class :: get ( "Foo" ) . expect (
+                  "Couldn\'t find Foo" ) , foo)
+    }
+}
diff --git a/tests/expectations/tests/objc_property_fnptr.rs b/tests/expectations/tests/objc_property_fnptr.rs
new file mode 100644
index 0000000..044f25d
--- /dev/null
+++ b/tests/expectations/tests/objc_property_fnptr.rs
@@ -0,0 +1,35 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+#![cfg(target_os="macos")]
+
+#[macro_use]
+extern crate objc;
+#[allow(non_camel_case_types)]
+pub type id = *mut objc::runtime::Object;
+pub trait Foo {
+    unsafe fn func(self)
+    -> ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>;
+    unsafe fn setFunc_(self,
+                       func:
+                           ::std::option::Option<unsafe extern "C" fn()
+                                                     ->
+                                                         ::std::os::raw::c_int>);
+}
+impl Foo for id {
+    unsafe fn func(self)
+     ->
+         ::std::option::Option<unsafe extern "C" fn()
+                                   -> ::std::os::raw::c_int> {
+        msg_send!(self , func)
+    }
+    unsafe fn setFunc_(self,
+                       func:
+                           ::std::option::Option<unsafe extern "C" fn()
+                                                     ->
+                                                         ::std::os::raw::c_int>) {
+        msg_send!(self , setFunc:func )
+    }
+}
diff --git a/tests/expectations/tests/objc_template.rs b/tests/expectations/tests/objc_template.rs
new file mode 100644
index 0000000..e5a874c
--- /dev/null
+++ b/tests/expectations/tests/objc_template.rs
@@ -0,0 +1,18 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+#![cfg(target_os="macos")]
+
+#[macro_use]
+extern crate objc;
+#[allow(non_camel_case_types)]
+pub type id = *mut objc::runtime::Object;
+pub trait Foo {
+    unsafe fn get(self)
+    -> id;
+}
+impl Foo for id {
+    unsafe fn get(self) -> id { msg_send!(self , get) }
+}
diff --git a/tests/headers/objc_method_clash.h b/tests/headers/objc_method_clash.h
new file mode 100644
index 0000000..a56e39d
--- /dev/null
+++ b/tests/headers/objc_method_clash.h
@@ -0,0 +1,7 @@
+// bindgen-flags: --objc-extern-crate -- -x objective-c
+// bindgen-osx-only
+
+@interface Foo
++ (void)foo;
+- (void)foo;
+@end
diff --git a/tests/headers/objc_property_fnptr.h b/tests/headers/objc_property_fnptr.h
new file mode 100644
index 0000000..8312ba4
--- /dev/null
+++ b/tests/headers/objc_property_fnptr.h
@@ -0,0 +1,8 @@
+// bindgen-flags: --objc-extern-crate -- -x objective-c
+// bindgen-osx-only
+
+@interface Foo
+// FIXME: We are not generating valid code for this
+//        but at least we should not die
+@property int (*func)(char, short, float);
+@end
diff --git a/tests/headers/objc_template.h b/tests/headers/objc_template.h
new file mode 100644
index 0000000..62398eb
--- /dev/null
+++ b/tests/headers/objc_template.h
@@ -0,0 +1,6 @@
+// bindgen-flags: --objc-extern-crate -- -x objective-c
+// bindgen-osx-only
+
+@interface Foo<__covariant ObjectType>
+- (ObjectType)get;
+@end