Support raw pointers in cxx::bridge.

This allows raw pointers to types to be passed into and out of
cxx::bridge extern "C++" APIs. As normal with raw pointers in Rust,
there are no safety or lifetime guarantees.

Passing a raw pointer into such an API requires that the
function be marked "unsafe".
diff --git a/syntax/check.rs b/syntax/check.rs
index 2098a1b..e4933d3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -8,6 +8,8 @@
 use quote::{quote, ToTokens};
 use std::fmt::Display;
 
+use super::Ptr;
+
 pub(crate) struct Check<'a> {
     apis: &'a [Api],
     types: &'a Types<'a>,
@@ -35,6 +37,7 @@
             Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
+            Type::Ptr(ty) => check_type_ptr(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
             Type::SliceRef(ty) => check_type_slice_ref(cx, ty),
@@ -221,7 +224,7 @@
     }
 
     match ty.inner {
-        Type::Fn(_) | Type::Void(_) => {}
+        Type::Fn(_) | Type::Void(_) | Type::Ptr(_) => {}
         Type::Ref(_) => {
             cx.error(ty, "C++ does not allow references to references");
             return;
@@ -232,6 +235,12 @@
     cx.error(ty, "unsupported reference type");
 }
 
+fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
+    if let Type::Ident(_) = ty.inner { return }
+
+    cx.error(ty, "unsupported pointer type");
+}
+
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = !is_unsized(cx, &ty.inner)
         || match &ty.inner {
@@ -555,6 +564,7 @@
         | Type::SharedPtr(_)
         | Type::WeakPtr(_)
         | Type::Ref(_)
+        | Type::Ptr(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
     }
@@ -628,6 +638,7 @@
         Type::SharedPtr(_) => "shared_ptr".to_owned(),
         Type::WeakPtr(_) => "weak_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
+        Type::Ptr(_) => "raw pointer".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::SliceRef(_) => "slice".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 3a0b3e0..954f39b 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -5,6 +5,8 @@
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+use super::Ptr;
+
 impl PartialEq for Include {
     fn eq(&self, other: &Include) -> bool {
         let Include {
@@ -47,6 +49,7 @@
             Type::SharedPtr(t) => t.hash(state),
             Type::WeakPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
+            Type::Ptr(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
             Type::CxxVector(t) => t.hash(state),
@@ -189,6 +192,42 @@
     }
 }
 
+impl Eq for Ptr {}
+
+impl PartialEq for Ptr {
+    fn eq(&self, other: &Ptr) -> bool {
+        let Ptr {
+            star: _,
+            mutable,
+            inner,
+            mutability: _,
+            constness: _,
+        } = self;
+        let Ptr {
+            star: _,
+            mutable: mutable2,
+            inner: inner2,
+            mutability: _,
+            constness: _,
+        } = other;
+        mutable == mutable2 && inner == inner2
+    }
+}
+
+impl Hash for Ptr {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Ptr {
+            star: _,
+            mutable,
+            inner,
+            mutability: _,
+            constness: _,
+        } = self;
+        mutable.hash(state);
+        inner.hash(state);
+    }
+}
+
 impl Eq for SliceRef {}
 
 impl PartialEq for SliceRef {
diff --git a/syntax/improper.rs b/syntax/improper.rs
index d672e7d..6a9b5ac 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -32,6 +32,7 @@
                 Definite(false)
             }
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+            Type::Ptr(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 30faccc..87e3454 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -204,6 +204,7 @@
     SharedPtr(Box<Ty1>),
     WeakPtr(Box<Ty1>),
     Ref(Box<Ref>),
+    Ptr(Box<Ptr>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
@@ -229,6 +230,14 @@
     pub mutability: Option<Token![mut]>,
 }
 
+pub struct Ptr {
+    pub star: Token![*],
+    pub mutable: bool,
+    pub inner: Type,
+    pub mutability: Option<Token![mut]>,
+    pub constness: Option<Token![const]>,
+}
+
 pub struct SliceRef {
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index fbb24e2..af03248 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -11,7 +11,7 @@
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use std::mem;
-use syn::parse::{ParseStream, Parser};
+use syn::{TypePtr, parse::{ParseStream, Parser}};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
@@ -21,6 +21,8 @@
     TypeReference, Variant as RustVariant, Visibility,
 };
 
+use super::Ptr;
+
 pub mod kw {
     syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
@@ -547,6 +549,7 @@
         ));
     }
 
+    let unsafety = foreign_fn.sig.unsafety;
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -583,6 +586,11 @@
                     let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     let name = pair(Namespace::default(), &ident, None, None);
+                    if let Type::Ptr(_) = &ty {
+                        if unsafety.is_none() {
+                            return Err(Error::new_spanned(arg, "pointer argument requires that the function be marked unsafe"));
+                        }
+                    }
                     args.push_value(Var {
                         doc,
                         attrs,
@@ -620,7 +628,6 @@
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
-    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
     let generics = generics.clone();
@@ -965,6 +972,7 @@
         },
         Type::Ident(_)
         | Type::Ref(_)
+        | Type::Ptr(_)
         | Type::Str(_)
         | Type::Fn(_)
         | Type::Void(_)
@@ -1033,6 +1041,7 @@
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
+        RustType::Ptr(ty) => parse_type_ptr(ty),
         RustType::Path(ty) => parse_type_path(ty),
         RustType::Array(ty) => parse_type_array(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
@@ -1084,6 +1093,26 @@
     })))
 }
 
+fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
+    let star = ty.star_token;
+    let mutable = ty.mutability.is_some();
+    let constness = ty.const_token;
+    let mutability = ty.mutability;
+    if !constness.is_some() && !mutable {
+        return Err(Error::new_spanned(ty, "pointer is neither const nor mut"));
+    }
+
+    let inner = parse_type(&ty.elem)?;
+    
+    Ok(Type::Ptr(Box::new(Ptr {
+        star,
+        mutable,
+        inner,
+        mutability,
+        constness,
+    })))
+}
+
 fn parse_type_path(ty: &TypePath) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
diff --git a/syntax/pod.rs b/syntax/pod.rs
index e1c4831..0bf152e 100644
--- a/syntax/pod.rs
+++ b/syntax/pod.rs
@@ -29,7 +29,7 @@
             | Type::WeakPtr(_)
             | Type::CxxVector(_)
             | Type::Void(_) => false,
-            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
+            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) | Type::Ptr(_) => true,
             Type::Array(array) => self.is_guaranteed_pod(&array.inner),
         }
     }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index bb04e16..d728ac0 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -7,6 +7,8 @@
 use quote::{quote_spanned, ToTokens};
 use syn::{token, Token};
 
+use super::Ptr;
+
 impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
@@ -27,6 +29,7 @@
             | Type::CxxVector(ty)
             | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Ptr(p) => p.to_tokens(tokens),
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
@@ -100,6 +103,22 @@
     }
 }
 
+impl ToTokens for Ptr {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let Ptr {
+            star,
+            mutable: _,
+            inner,
+            mutability,
+            constness,
+        } = self;
+        star.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        constness.to_tokens(tokens);
+        inner.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for SliceRef {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let SliceRef {
diff --git a/syntax/types.rs b/syntax/types.rs
index 7bf2baf..031dc08 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -51,6 +51,7 @@
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Ptr(p) => visit(all, &p.inner),
                 Type::Array(a) => visit(all, &a.inner),
                 Type::SliceRef(s) => visit(all, &s.inner),
                 Type::Fn(f) => {