Auto merge of #518 - pornel:typedefstruct, r=emilio

typedef struct {} name

Fixes #427

It looks like clang is doing the hard work of getting the right name from the typedef, but it falls back to arbitrary pretty-printed descriptions if it can't find a typedef. I couldn't find an API to check whether the name comes from a typedef, so I just filter out non-ident-like spellings.
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index ec168f0..332ad23 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -311,19 +311,21 @@
         match self.kind {
             TypeKind::Named => {
                 let name = self.name().expect("Unnamed named type?");
-                let mut chars = name.chars();
-                let first = chars.next().unwrap();
-                let mut remaining = chars;
-
-                let valid = (first.is_alphabetic() || first == '_') &&
-                            remaining.all(|c| c.is_alphanumeric() || c == '_');
-
-                !valid
+                !Self::is_valid_identifier(&name)
             }
             _ => false,
         }
     }
 
+    /// Checks whether the name looks like an identifier,
+    /// i.e. is alphanumeric (including '_') and does not start with a digit.
+    pub fn is_valid_identifier(name: &str) -> bool {
+        let mut chars = name.chars();
+        let first_valid = chars.next().map(|c| c.is_alphabetic() || c == '_').unwrap_or(false);
+
+        first_valid && chars.all(|c| c.is_alphanumeric() || c == '_')
+    }
+
     /// See safe_canonical_type.
     pub fn canonical_type<'tr>(&'tr self,
                                ctx: &'tr BindgenContext)
@@ -454,7 +456,6 @@
 }
 
 #[test]
-#[should_panic]
 fn is_invalid_named_type_empty_name() {
     let ty = Type::new(Some("".into()), None, TypeKind::Named, false);
     assert!(ty.is_invalid_named_type())
@@ -1074,12 +1075,30 @@
             }
             CXType_Enum => {
                 let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
+
+                if name.is_empty() {
+                    let pretty_name = ty.spelling();
+                    if Self::is_valid_identifier(&pretty_name) {
+                        name = pretty_name;
+                    }
+                }
+
                 TypeKind::Enum(enum_)
             }
             CXType_Record => {
                 let complex =
                     CompInfo::from_ty(potential_id, ty, location, ctx)
                         .expect("Not a complex type?");
+
+                if name.is_empty() {
+                    // The pretty-printed name may contain typedefed name,
+                    // but may also be "struct (anonymous at .h:1)"
+                    let pretty_name = ty.spelling();
+                    if Self::is_valid_identifier(&pretty_name) {
+                        name = pretty_name;
+                    }
+                }
+
                 TypeKind::Comp(complex)
             }
             // FIXME: We stub vectors as arrays since in 99% of the cases the
diff --git a/tests/expectations/tests/anon_enum.rs b/tests/expectations/tests/anon_enum.rs
index 07ea481..71abc77 100644
--- a/tests/expectations/tests/anon_enum.rs
+++ b/tests/expectations/tests/anon_enum.rs
@@ -34,9 +34,6 @@
 impl Clone for Test {
     fn clone(&self) -> Self { *self }
 }
-pub const Foo: _bindgen_ty_1 = _bindgen_ty_1::Foo;
-pub const Bar: _bindgen_ty_1 = _bindgen_ty_1::Bar;
 #[repr(u32)]
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum _bindgen_ty_1 { Foo = 0, Bar = 1, }
-pub use self::_bindgen_ty_1 as Baz;
+pub enum Baz { Foo = 0, Bar = 1, }
diff --git a/tests/expectations/tests/bitfield_method_mangling.rs b/tests/expectations/tests/bitfield_method_mangling.rs
index 0ab5fce..0a6c9fd 100644
--- a/tests/expectations/tests/bitfield_method_mangling.rs
+++ b/tests/expectations/tests/bitfield_method_mangling.rs
@@ -6,20 +6,23 @@
 
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
-pub struct _bindgen_ty_1 {
+pub struct mach_msg_type_descriptor_t {
     pub _bitfield_1: u32,
 }
 #[test]
-fn bindgen_test_layout__bindgen_ty_1() {
-    assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 4usize , concat ! (
-               "Size of: " , stringify ! ( _bindgen_ty_1 ) ));
-    assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 4usize , concat ! (
-                "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+fn bindgen_test_layout_mach_msg_type_descriptor_t() {
+    assert_eq!(::std::mem::size_of::<mach_msg_type_descriptor_t>() , 4usize ,
+               concat ! (
+               "Size of: " , stringify ! ( mach_msg_type_descriptor_t ) ));
+    assert_eq! (::std::mem::align_of::<mach_msg_type_descriptor_t>() , 4usize
+                , concat ! (
+                "Alignment of " , stringify ! ( mach_msg_type_descriptor_t )
+                ));
 }
-impl Clone for _bindgen_ty_1 {
+impl Clone for mach_msg_type_descriptor_t {
     fn clone(&self) -> Self { *self }
 }
-impl _bindgen_ty_1 {
+impl mach_msg_type_descriptor_t {
     #[inline]
     pub fn pad3(&self) -> ::std::os::raw::c_uint {
         unsafe {
@@ -48,4 +51,3 @@
             ((val as u32 as u32) << 24u32) & (4278190080usize as u32);
     }
 }
-pub type mach_msg_type_descriptor_t = _bindgen_ty_1;
diff --git a/tests/expectations/tests/issue-410.rs b/tests/expectations/tests/issue-410.rs
index 2fe0f99..3c6cd28 100644
--- a/tests/expectations/tests/issue-410.rs
+++ b/tests/expectations/tests/issue-410.rs
@@ -38,6 +38,5 @@
         }
     }
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-    pub enum _bindgen_ty_1 { }
-    pub use self::super::root::_bindgen_ty_1 as JSWhyMagic;
+    pub enum JSWhyMagic { }
 }
diff --git a/tests/expectations/tests/layout_array.rs b/tests/expectations/tests/layout_array.rs
index c28d3ec..2cc8578 100644
--- a/tests/expectations/tests/layout_array.rs
+++ b/tests/expectations/tests/layout_array.rs
@@ -117,26 +117,25 @@
  */
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
-pub struct _bindgen_ty_1 {
+pub struct rte_spinlock_t {
     /**< lock status 0 = unlocked, 1 = locked */
     pub locked: ::std::os::raw::c_int,
 }
 #[test]
-fn bindgen_test_layout__bindgen_ty_1() {
-    assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 4usize , concat ! (
-               "Size of: " , stringify ! ( _bindgen_ty_1 ) ));
-    assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 4usize , concat ! (
-                "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+fn bindgen_test_layout_rte_spinlock_t() {
+    assert_eq!(::std::mem::size_of::<rte_spinlock_t>() , 4usize , concat ! (
+               "Size of: " , stringify ! ( rte_spinlock_t ) ));
+    assert_eq! (::std::mem::align_of::<rte_spinlock_t>() , 4usize , concat ! (
+                "Alignment of " , stringify ! ( rte_spinlock_t ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) . locked as * const _
+                & ( * ( 0 as * const rte_spinlock_t ) ) . locked as * const _
                 as usize } , 0usize , concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
+                "Alignment of field: " , stringify ! ( rte_spinlock_t ) , "::"
                 , stringify ! ( locked ) ));
 }
-impl Clone for _bindgen_ty_1 {
+impl Clone for rte_spinlock_t {
     fn clone(&self) -> Self { *self }
 }
-pub type rte_spinlock_t = _bindgen_ty_1;
 /**
  * Structure storing the table of registered ops structs, each of which contain
  * the function pointers for the mempool ops functions.
diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs
index 189b50a..5732831 100644
--- a/tests/expectations/tests/layout_mbuf.rs
+++ b/tests/expectations/tests/layout_mbuf.rs
@@ -39,26 +39,25 @@
  */
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
-pub struct _bindgen_ty_1 {
+pub struct rte_atomic16_t {
     /**< An internal counter value. */
     pub cnt: i16,
 }
 #[test]
-fn bindgen_test_layout__bindgen_ty_1() {
-    assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 2usize , concat ! (
-               "Size of: " , stringify ! ( _bindgen_ty_1 ) ));
-    assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 2usize , concat ! (
-                "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+fn bindgen_test_layout_rte_atomic16_t() {
+    assert_eq!(::std::mem::size_of::<rte_atomic16_t>() , 2usize , concat ! (
+               "Size of: " , stringify ! ( rte_atomic16_t ) ));
+    assert_eq! (::std::mem::align_of::<rte_atomic16_t>() , 2usize , concat ! (
+                "Alignment of " , stringify ! ( rte_atomic16_t ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) . cnt as * const _ as
+                & ( * ( 0 as * const rte_atomic16_t ) ) . cnt as * const _ as
                 usize } , 0usize , concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
+                "Alignment of field: " , stringify ! ( rte_atomic16_t ) , "::"
                 , stringify ! ( cnt ) ));
 }
-impl Clone for _bindgen_ty_1 {
+impl Clone for rte_atomic16_t {
     fn clone(&self) -> Self { *self }
 }
-pub type rte_atomic16_t = _bindgen_ty_1;
 /**
  * The generic rte_mbuf, containing a packet mbuf.
  */
diff --git a/tests/expectations/tests/struct_typedef.rs b/tests/expectations/tests/struct_typedef.rs
new file mode 100644
index 0000000..63811bd
--- /dev/null
+++ b/tests/expectations/tests/struct_typedef.rs
@@ -0,0 +1,61 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct typedef_named_struct {
+    pub has_name: bool,
+}
+#[test]
+fn bindgen_test_layout_typedef_named_struct() {
+    assert_eq!(::std::mem::size_of::<typedef_named_struct>() , 1usize , concat
+               ! ( "Size of: " , stringify ! ( typedef_named_struct ) ));
+    assert_eq! (::std::mem::align_of::<typedef_named_struct>() , 1usize ,
+                concat ! (
+                "Alignment of " , stringify ! ( typedef_named_struct ) ));
+    assert_eq! (unsafe {
+                & ( * ( 0 as * const typedef_named_struct ) ) . has_name as *
+                const _ as usize } , 0usize , concat ! (
+                "Alignment of field: " , stringify ! ( typedef_named_struct )
+                , "::" , stringify ! ( has_name ) ));
+}
+impl Clone for typedef_named_struct {
+    fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct _bindgen_ty_1 {
+    pub no_name: *mut ::std::os::raw::c_void,
+}
+#[test]
+fn bindgen_test_layout__bindgen_ty_1() {
+    assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 8usize , concat ! (
+               "Size of: " , stringify ! ( _bindgen_ty_1 ) ));
+    assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 8usize , concat ! (
+                "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+    assert_eq! (unsafe {
+                & ( * ( 0 as * const _bindgen_ty_1 ) ) . no_name as * const _
+                as usize } , 0usize , concat ! (
+                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
+                , stringify ! ( no_name ) ));
+}
+impl Clone for _bindgen_ty_1 {
+    fn clone(&self) -> Self { *self }
+}
+impl Default for _bindgen_ty_1 {
+    fn default() -> Self { unsafe { ::std::mem::zeroed() } }
+}
+pub type struct_ptr_t = *mut _bindgen_ty_1;
+pub type struct_ptr_ptr_t = *mut *mut _bindgen_ty_1;
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum typedef_named_enum { ENUM_HAS_NAME = 1, }
+pub const ENUM_IS_ANON: _bindgen_ty_2 = _bindgen_ty_2::ENUM_IS_ANON;
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum _bindgen_ty_2 { ENUM_IS_ANON = 0, }
+pub type enum_ptr_t = *mut _bindgen_ty_2;
+pub type enum_ptr_ptr_t = *mut *mut _bindgen_ty_2;
diff --git a/tests/expectations/tests/struct_typedef_ns.rs b/tests/expectations/tests/struct_typedef_ns.rs
new file mode 100644
index 0000000..d7ada7f
--- /dev/null
+++ b/tests/expectations/tests/struct_typedef_ns.rs
@@ -0,0 +1,79 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+pub mod root {
+    #[allow(unused_imports)]
+    use self::super::root;
+    pub mod whatever {
+        #[allow(unused_imports)]
+        use self::super::super::root;
+        #[repr(C)]
+        #[derive(Debug, Default, Copy)]
+        pub struct _bindgen_ty_1 {
+            pub foo: ::std::os::raw::c_int,
+        }
+        #[test]
+        fn bindgen_test_layout__bindgen_ty_1() {
+            assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 4usize ,
+                       concat ! ( "Size of: " , stringify ! ( _bindgen_ty_1 )
+                       ));
+            assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 4usize ,
+                        concat ! (
+                        "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+            assert_eq! (unsafe {
+                        & ( * ( 0 as * const _bindgen_ty_1 ) ) . foo as *
+                        const _ as usize } , 0usize , concat ! (
+                        "Alignment of field: " , stringify ! ( _bindgen_ty_1 )
+                        , "::" , stringify ! ( foo ) ));
+        }
+        impl Clone for _bindgen_ty_1 {
+            fn clone(&self) -> Self { *self }
+        }
+        pub type typedef_struct = root::whatever::_bindgen_ty_1;
+        pub const whatever_BAR: root::whatever::_bindgen_ty_2 =
+            _bindgen_ty_2::BAR;
+        #[repr(u32)]
+        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+        pub enum _bindgen_ty_2 { BAR = 1, }
+        pub use self::super::super::root::whatever::_bindgen_ty_2 as
+                typedef_enum;
+    }
+    pub mod _bindgen_mod_id_12 {
+        #[allow(unused_imports)]
+        use self::super::super::root;
+        #[repr(C)]
+        #[derive(Debug, Default, Copy)]
+        pub struct _bindgen_ty_1 {
+            pub foo: ::std::os::raw::c_int,
+        }
+        #[test]
+        fn bindgen_test_layout__bindgen_ty_1() {
+            assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 4usize ,
+                       concat ! ( "Size of: " , stringify ! ( _bindgen_ty_1 )
+                       ));
+            assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 4usize ,
+                        concat ! (
+                        "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+            assert_eq! (unsafe {
+                        & ( * ( 0 as * const _bindgen_ty_1 ) ) . foo as *
+                        const _ as usize } , 0usize , concat ! (
+                        "Alignment of field: " , stringify ! ( _bindgen_ty_1 )
+                        , "::" , stringify ! ( foo ) ));
+        }
+        impl Clone for _bindgen_ty_1 {
+            fn clone(&self) -> Self { *self }
+        }
+        pub type typedef_struct = root::_bindgen_mod_id_12::_bindgen_ty_1;
+        pub const _bindgen_mod_id_12_BAR:
+                  root::_bindgen_mod_id_12::_bindgen_ty_2 =
+            _bindgen_ty_2::BAR;
+        #[repr(u32)]
+        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+        pub enum _bindgen_ty_2 { BAR = 1, }
+        pub use self::super::super::root::_bindgen_mod_id_12::_bindgen_ty_2 as
+                typedef_enum;
+    }
+}
diff --git a/tests/expectations/tests/union_fields.rs b/tests/expectations/tests/union_fields.rs
index 823a0b8..8c8ef7d 100644
--- a/tests/expectations/tests/union_fields.rs
+++ b/tests/expectations/tests/union_fields.rs
@@ -30,35 +30,34 @@
 }
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
-pub struct _bindgen_ty_1 {
+pub struct nsStyleUnion {
     pub mInt: __BindgenUnionField<::std::os::raw::c_int>,
     pub mFloat: __BindgenUnionField<f32>,
     pub mPointer: __BindgenUnionField<*mut ::std::os::raw::c_void>,
     pub bindgen_union_field: u64,
 }
 #[test]
-fn bindgen_test_layout__bindgen_ty_1() {
-    assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 8usize , concat ! (
-               "Size of: " , stringify ! ( _bindgen_ty_1 ) ));
-    assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 8usize , concat ! (
-                "Alignment of " , stringify ! ( _bindgen_ty_1 ) ));
+fn bindgen_test_layout_nsStyleUnion() {
+    assert_eq!(::std::mem::size_of::<nsStyleUnion>() , 8usize , concat ! (
+               "Size of: " , stringify ! ( nsStyleUnion ) ));
+    assert_eq! (::std::mem::align_of::<nsStyleUnion>() , 8usize , concat ! (
+                "Alignment of " , stringify ! ( nsStyleUnion ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) . mInt as * const _ as
+                & ( * ( 0 as * const nsStyleUnion ) ) . mInt as * const _ as
                 usize } , 0usize , concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
-                , stringify ! ( mInt ) ));
+                "Alignment of field: " , stringify ! ( nsStyleUnion ) , "::" ,
+                stringify ! ( mInt ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) . mFloat as * const _
-                as usize } , 0usize , concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
-                , stringify ! ( mFloat ) ));
+                & ( * ( 0 as * const nsStyleUnion ) ) . mFloat as * const _ as
+                usize } , 0usize , concat ! (
+                "Alignment of field: " , stringify ! ( nsStyleUnion ) , "::" ,
+                stringify ! ( mFloat ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) . mPointer as * const _
+                & ( * ( 0 as * const nsStyleUnion ) ) . mPointer as * const _
                 as usize } , 0usize , concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
-                , stringify ! ( mPointer ) ));
+                "Alignment of field: " , stringify ! ( nsStyleUnion ) , "::" ,
+                stringify ! ( mPointer ) ));
 }
-impl Clone for _bindgen_ty_1 {
+impl Clone for nsStyleUnion {
     fn clone(&self) -> Self { *self }
 }
-pub type nsStyleUnion = _bindgen_ty_1;
diff --git a/tests/expectations/tests/unknown_attr.rs b/tests/expectations/tests/unknown_attr.rs
index efb8610..2c50c36 100644
--- a/tests/expectations/tests/unknown_attr.rs
+++ b/tests/expectations/tests/unknown_attr.rs
@@ -6,30 +6,29 @@
 
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
-pub struct _bindgen_ty_1 {
+pub struct max_align_t {
     pub __clang_max_align_nonce1: ::std::os::raw::c_longlong,
     pub __bindgen_padding_0: u64,
     pub __clang_max_align_nonce2: f64,
     pub __bindgen_padding_1: u64,
 }
 #[test]
-fn bindgen_test_layout__bindgen_ty_1() {
-    assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 32usize , concat ! (
-               "Size of: " , stringify ! ( _bindgen_ty_1 ) ));
+fn bindgen_test_layout_max_align_t() {
+    assert_eq!(::std::mem::size_of::<max_align_t>() , 32usize , concat ! (
+               "Size of: " , stringify ! ( max_align_t ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) .
+                & ( * ( 0 as * const max_align_t ) ) .
                 __clang_max_align_nonce1 as * const _ as usize } , 0usize ,
                 concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
-                , stringify ! ( __clang_max_align_nonce1 ) ));
+                "Alignment of field: " , stringify ! ( max_align_t ) , "::" ,
+                stringify ! ( __clang_max_align_nonce1 ) ));
     assert_eq! (unsafe {
-                & ( * ( 0 as * const _bindgen_ty_1 ) ) .
+                & ( * ( 0 as * const max_align_t ) ) .
                 __clang_max_align_nonce2 as * const _ as usize } , 16usize ,
                 concat ! (
-                "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::"
-                , stringify ! ( __clang_max_align_nonce2 ) ));
+                "Alignment of field: " , stringify ! ( max_align_t ) , "::" ,
+                stringify ! ( __clang_max_align_nonce2 ) ));
 }
-impl Clone for _bindgen_ty_1 {
+impl Clone for max_align_t {
     fn clone(&self) -> Self { *self }
 }
-pub type max_align_t = _bindgen_ty_1;
diff --git a/tests/headers/struct_typedef.h b/tests/headers/struct_typedef.h
new file mode 100644
index 0000000..fdce9a7
--- /dev/null
+++ b/tests/headers/struct_typedef.h
@@ -0,0 +1,15 @@
+typedef struct {
+    _Bool has_name;
+} typedef_named_struct;
+
+typedef struct {
+    void *no_name;
+} *struct_ptr_t, **struct_ptr_ptr_t;
+
+typedef enum {
+    ENUM_HAS_NAME=1
+} typedef_named_enum;
+
+typedef enum {
+    ENUM_IS_ANON
+} *enum_ptr_t, **enum_ptr_ptr_t;
diff --git a/tests/headers/struct_typedef_ns.hpp b/tests/headers/struct_typedef_ns.hpp
new file mode 100644
index 0000000..bc89eb2
--- /dev/null
+++ b/tests/headers/struct_typedef_ns.hpp
@@ -0,0 +1,21 @@
+// bindgen-flags: --enable-cxx-namespaces
+
+namespace whatever {
+    typedef struct {
+        int foo;
+    } typedef_struct;
+
+    typedef enum {
+        BAR=1
+    } typedef_enum;
+}
+
+namespace {
+    typedef struct {
+        int foo;
+    } typedef_struct;
+
+    typedef enum {
+        BAR=1
+    } typedef_enum;
+}