Store passthrough attributes for diagnostic lint levels
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 9ad3d51..7f50dcb 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -39,7 +39,8 @@
     pub(crate) _more: (),
 }
 
-pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) {
+pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Vec<Attribute> {
+    let mut passthrough_attrs = Vec::new();
     for attr in attrs {
         if attr.path.is_ident("doc") {
             match parse_doc_attribute.parse2(attr.tokens.clone()) {
@@ -49,7 +50,10 @@
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("derive") {
             match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) {
@@ -59,7 +63,10 @@
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("repr") {
             match attr.parse_args_with(parse_repr_attribute) {
@@ -69,7 +76,10 @@
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("namespace") {
             match parse_namespace_attribute.parse2(attr.tokens.clone()) {
@@ -79,7 +89,10 @@
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("cxx_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
@@ -89,7 +102,10 @@
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("rust_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
@@ -99,7 +115,10 @@
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("allow")
             || attr.path.is_ident("warn")
@@ -107,10 +126,13 @@
             || attr.path.is_ident("forbid")
         {
             // https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes
+            passthrough_attrs.push(attr);
             continue;
         }
-        return cx.error(attr, "unsupported attribute");
+        cx.error(attr, "unsupported attribute");
+        break;
     }
+    passthrough_attrs
 }
 
 fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 624a64d..4504fe6 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -298,12 +298,14 @@
     fn eq(&self, other: &Var) -> bool {
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident,
             ty,
         } = self;
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident: ident2,
             ty: ty2,
@@ -316,6 +318,7 @@
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident,
             ty,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 092f403..c478d3c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -1,7 +1,7 @@
 // Functionality that is shared between the cxxbridge macro and the cmd.
 
 pub mod atom;
-mod attrs;
+pub mod attrs;
 pub mod check;
 pub mod derive;
 mod discriminant;
@@ -32,7 +32,7 @@
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
+use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::{Derive, Trait};
@@ -72,6 +72,7 @@
     pub lang: Lang,
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -84,6 +85,7 @@
 pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
@@ -94,6 +96,7 @@
 pub struct Enum {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
@@ -106,6 +109,7 @@
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
+    pub attrs: Vec<Attribute>,
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
@@ -115,6 +119,7 @@
 pub struct TypeAlias {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -151,6 +156,7 @@
 
 pub struct Var {
     pub doc: Doc,
+    pub attrs: Vec<Attribute>,
     pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
@@ -170,6 +176,7 @@
 
 pub struct Variant {
     pub doc: Doc,
+    pub attrs: Vec<Attribute>,
     pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1ea4db4..87f43b2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -57,15 +57,14 @@
 }
 
 fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> {
-    let attrs = mem::take(&mut item.attrs);
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        attrs,
+        mem::take(&mut item.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -100,7 +99,7 @@
     for field in named_fields.named {
         let ident = field.ident.unwrap();
         let mut doc = Doc::new();
-        attrs::parse(
+        let attrs = attrs::parse(
             cx,
             field.attrs,
             attrs::Parser {
@@ -123,6 +122,7 @@
         });
         fields.push(Var {
             doc,
+            attrs,
             visibility,
             ident,
             ty,
@@ -142,6 +142,7 @@
     Ok(Api::Struct(Struct {
         doc,
         derives,
+        attrs,
         visibility,
         struct_token,
         name,
@@ -157,7 +158,7 @@
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         item.attrs,
         attrs::Parser {
@@ -213,6 +214,7 @@
     Ok(Api::Enum(Enum {
         doc,
         derives,
+        attrs,
         enum_token,
         name,
         brace_token,
@@ -228,13 +230,12 @@
     mut variant: RustVariant,
     discriminants: &mut DiscriminantSet,
 ) -> Result<Variant> {
-    let attrs = mem::take(&mut variant.attrs);
     let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        attrs,
+        mem::take(&mut variant.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
@@ -266,6 +267,7 @@
 
     Ok(Variant {
         doc,
+        attrs,
         name,
         discriminant,
         expr,
@@ -403,7 +405,7 @@
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         foreign_type.attrs,
         attrs::Parser {
@@ -434,6 +436,7 @@
         lang,
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -451,14 +454,13 @@
     trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
-    let attrs = mem::take(&mut foreign_fn.attrs);
     let mut doc = Doc::new();
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        attrs,
+        mem::take(&mut foreign_fn.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             namespace: Some(&mut namespace),
@@ -542,9 +544,11 @@
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
                     let doc = Doc::new();
+                    let attrs = Vec::new();
                     let visibility = Token![pub](ident.span());
                     args.push_value(Var {
                         doc,
+                        attrs,
                         visibility,
                         ident,
                         ty,
@@ -591,6 +595,7 @@
     }(ExternFn {
         lang,
         doc,
+        attrs,
         name,
         sig: Signature {
             unsafety,
@@ -701,7 +706,7 @@
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         attrs,
         attrs::Parser {
@@ -725,6 +730,7 @@
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -783,7 +789,7 @@
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         attrs,
         attrs::Parser {
@@ -805,6 +811,7 @@
         lang,
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -1115,9 +1122,11 @@
                 None => format_ident!("arg{}", i),
             };
             let doc = Doc::new();
+            let attrs = Vec::new();
             let visibility = Token![pub](ident.span());
             Ok(Var {
                 doc,
+                attrs,
                 visibility,
                 ident,
                 ty,