• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Intermediate representation for C/C++ functions and methods.
2 
3 use super::comp::MethodKind;
4 use super::context::{BindgenContext, TypeId};
5 use super::dot::DotAttributes;
6 use super::item::Item;
7 use super::traversal::{EdgeKind, Trace, Tracer};
8 use super::ty::TypeKind;
9 use crate::callbacks::{ItemInfo, ItemKind};
10 use crate::clang::{self, Attribute};
11 use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
12 use clang_sys::{self, CXCallingConv};
13 
14 use quote::TokenStreamExt;
15 use std::io;
16 use std::str::FromStr;
17 
18 const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
19 
20 /// What kind of a function are we looking at?
21 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
22 pub(crate) enum FunctionKind {
23     /// A plain, free function.
24     Function,
25     /// A method of some kind.
26     Method(MethodKind),
27 }
28 
29 impl FunctionKind {
30     /// Given a clang cursor, return the kind of function it represents, or
31     /// `None` otherwise.
from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind>32     pub(crate) fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
33         // FIXME(emilio): Deduplicate logic with `ir::comp`.
34         Some(match cursor.kind() {
35             clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,
36             clang_sys::CXCursor_Constructor => {
37                 FunctionKind::Method(MethodKind::Constructor)
38             }
39             clang_sys::CXCursor_Destructor => {
40                 FunctionKind::Method(if cursor.method_is_virtual() {
41                     MethodKind::VirtualDestructor {
42                         pure_virtual: cursor.method_is_pure_virtual(),
43                     }
44                 } else {
45                     MethodKind::Destructor
46                 })
47             }
48             clang_sys::CXCursor_CXXMethod => {
49                 if cursor.method_is_virtual() {
50                     FunctionKind::Method(MethodKind::Virtual {
51                         pure_virtual: cursor.method_is_pure_virtual(),
52                     })
53                 } else if cursor.method_is_static() {
54                     FunctionKind::Method(MethodKind::Static)
55                 } else {
56                     FunctionKind::Method(MethodKind::Normal)
57                 }
58             }
59             _ => return None,
60         })
61     }
62 }
63 
64 /// The style of linkage
65 #[derive(Debug, Clone, Copy)]
66 pub(crate) enum Linkage {
67     /// Externally visible and can be linked against
68     External,
69     /// Not exposed externally. 'static inline' functions will have this kind of linkage
70     Internal,
71 }
72 
73 /// A function declaration, with a signature, arguments, and argument names.
74 ///
75 /// The argument names vector must be the same length as the ones in the
76 /// signature.
77 #[derive(Debug)]
78 pub(crate) struct Function {
79     /// The name of this function.
80     name: String,
81 
82     /// The mangled name, that is, the symbol.
83     mangled_name: Option<String>,
84 
85     /// The link name. If specified, overwrite mangled_name.
86     link_name: Option<String>,
87 
88     /// The ID pointing to the current function signature.
89     signature: TypeId,
90 
91     /// The kind of function this is.
92     kind: FunctionKind,
93 
94     /// The linkage of the function.
95     linkage: Linkage,
96 }
97 
98 impl Function {
99     /// Construct a new function.
new( name: String, mangled_name: Option<String>, link_name: Option<String>, signature: TypeId, kind: FunctionKind, linkage: Linkage, ) -> Self100     pub(crate) fn new(
101         name: String,
102         mangled_name: Option<String>,
103         link_name: Option<String>,
104         signature: TypeId,
105         kind: FunctionKind,
106         linkage: Linkage,
107     ) -> Self {
108         Function {
109             name,
110             mangled_name,
111             link_name,
112             signature,
113             kind,
114             linkage,
115         }
116     }
117 
118     /// Get this function's name.
name(&self) -> &str119     pub(crate) fn name(&self) -> &str {
120         &self.name
121     }
122 
123     /// Get this function's name.
mangled_name(&self) -> Option<&str>124     pub(crate) fn mangled_name(&self) -> Option<&str> {
125         self.mangled_name.as_deref()
126     }
127 
128     /// Get this function's link name.
link_name(&self) -> Option<&str>129     pub fn link_name(&self) -> Option<&str> {
130         self.link_name.as_deref()
131     }
132 
133     /// Get this function's signature type.
signature(&self) -> TypeId134     pub(crate) fn signature(&self) -> TypeId {
135         self.signature
136     }
137 
138     /// Get this function's kind.
kind(&self) -> FunctionKind139     pub(crate) fn kind(&self) -> FunctionKind {
140         self.kind
141     }
142 
143     /// Get this function's linkage.
linkage(&self) -> Linkage144     pub(crate) fn linkage(&self) -> Linkage {
145         self.linkage
146     }
147 }
148 
149 impl DotAttributes for Function {
dot_attributes<W>( &self, _ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,150     fn dot_attributes<W>(
151         &self,
152         _ctx: &BindgenContext,
153         out: &mut W,
154     ) -> io::Result<()>
155     where
156         W: io::Write,
157     {
158         if let Some(ref mangled) = self.mangled_name {
159             let mangled: String =
160                 mangled.chars().flat_map(|c| c.escape_default()).collect();
161             writeln!(
162                 out,
163                 "<tr><td>mangled name</td><td>{}</td></tr>",
164                 mangled
165             )?;
166         }
167 
168         Ok(())
169     }
170 }
171 
172 /// A valid rust ABI.
173 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
174 pub enum Abi {
175     /// The default C ABI.
176     C,
177     /// The "stdcall" ABI.
178     Stdcall,
179     /// The "efiapi" ABI.
180     EfiApi,
181     /// The "fastcall" ABI.
182     Fastcall,
183     /// The "thiscall" ABI.
184     ThisCall,
185     /// The "vectorcall" ABI.
186     Vectorcall,
187     /// The "aapcs" ABI.
188     Aapcs,
189     /// The "win64" ABI.
190     Win64,
191     /// The "C-unwind" ABI.
192     CUnwind,
193     /// The "system" ABI.
194     System,
195 }
196 
197 impl FromStr for Abi {
198     type Err = String;
199 
from_str(s: &str) -> Result<Self, Self::Err>200     fn from_str(s: &str) -> Result<Self, Self::Err> {
201         match s {
202             "C" => Ok(Self::C),
203             "stdcall" => Ok(Self::Stdcall),
204             "efiapi" => Ok(Self::EfiApi),
205             "fastcall" => Ok(Self::Fastcall),
206             "thiscall" => Ok(Self::ThisCall),
207             "vectorcall" => Ok(Self::Vectorcall),
208             "aapcs" => Ok(Self::Aapcs),
209             "win64" => Ok(Self::Win64),
210             "C-unwind" => Ok(Self::CUnwind),
211             "system" => Ok(Self::System),
212             _ => Err(format!("Invalid or unknown ABI {:?}", s)),
213         }
214     }
215 }
216 
217 impl std::fmt::Display for Abi {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result218     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219         let s = match *self {
220             Self::C => "C",
221             Self::Stdcall => "stdcall",
222             Self::EfiApi => "efiapi",
223             Self::Fastcall => "fastcall",
224             Self::ThisCall => "thiscall",
225             Self::Vectorcall => "vectorcall",
226             Self::Aapcs => "aapcs",
227             Self::Win64 => "win64",
228             Self::CUnwind => "C-unwind",
229             Abi::System => "system",
230         };
231 
232         s.fmt(f)
233     }
234 }
235 
236 impl quote::ToTokens for Abi {
to_tokens(&self, tokens: &mut proc_macro2::TokenStream)237     fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
238         let abi = self.to_string();
239         tokens.append_all(quote! { #abi });
240     }
241 }
242 
243 /// An ABI extracted from a clang cursor.
244 #[derive(Debug, Copy, Clone)]
245 pub(crate) enum ClangAbi {
246     /// An ABI known by Rust.
247     Known(Abi),
248     /// An unknown or invalid ABI.
249     Unknown(CXCallingConv),
250 }
251 
252 impl ClangAbi {
253     /// Returns whether this Abi is known or not.
is_unknown(&self) -> bool254     fn is_unknown(&self) -> bool {
255         matches!(*self, ClangAbi::Unknown(..))
256     }
257 }
258 
259 impl quote::ToTokens for ClangAbi {
to_tokens(&self, tokens: &mut proc_macro2::TokenStream)260     fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
261         match *self {
262             Self::Known(abi) => abi.to_tokens(tokens),
263             Self::Unknown(cc) => panic!(
264                 "Cannot turn unknown calling convention to tokens: {:?}",
265                 cc
266             ),
267         }
268     }
269 }
270 
271 /// A function signature.
272 #[derive(Debug)]
273 pub(crate) struct FunctionSig {
274     /// The name of this function signature.
275     name: String,
276 
277     /// The return type of the function.
278     return_type: TypeId,
279 
280     /// The type of the arguments, optionally with the name of the argument when
281     /// declared.
282     argument_types: Vec<(Option<String>, TypeId)>,
283 
284     /// Whether this function is variadic.
285     is_variadic: bool,
286     is_divergent: bool,
287 
288     /// Whether this function's return value must be used.
289     must_use: bool,
290 
291     /// The ABI of this function.
292     abi: ClangAbi,
293 }
294 
get_abi(cc: CXCallingConv) -> ClangAbi295 fn get_abi(cc: CXCallingConv) -> ClangAbi {
296     use clang_sys::*;
297     match cc {
298         CXCallingConv_Default => ClangAbi::Known(Abi::C),
299         CXCallingConv_C => ClangAbi::Known(Abi::C),
300         CXCallingConv_X86StdCall => ClangAbi::Known(Abi::Stdcall),
301         CXCallingConv_X86FastCall => ClangAbi::Known(Abi::Fastcall),
302         CXCallingConv_X86ThisCall => ClangAbi::Known(Abi::ThisCall),
303         CXCallingConv_X86VectorCall => ClangAbi::Known(Abi::Vectorcall),
304         CXCallingConv_AAPCS => ClangAbi::Known(Abi::Aapcs),
305         CXCallingConv_X86_64Win64 => ClangAbi::Known(Abi::Win64),
306         other => ClangAbi::Unknown(other),
307     }
308 }
309 
310 /// Get the mangled name for the cursor's referent.
cursor_mangling( ctx: &BindgenContext, cursor: &clang::Cursor, ) -> Option<String>311 pub(crate) fn cursor_mangling(
312     ctx: &BindgenContext,
313     cursor: &clang::Cursor,
314 ) -> Option<String> {
315     if !ctx.options().enable_mangling {
316         return None;
317     }
318 
319     // We early return here because libclang may crash in some case
320     // if we pass in a variable inside a partial specialized template.
321     // See rust-lang/rust-bindgen#67, and rust-lang/rust-bindgen#462.
322     if cursor.is_in_non_fully_specialized_template() {
323         return None;
324     }
325 
326     let is_destructor = cursor.kind() == clang_sys::CXCursor_Destructor;
327     if let Ok(mut manglings) = cursor.cxx_manglings() {
328         while let Some(m) = manglings.pop() {
329             // Only generate the destructor group 1, see below.
330             if is_destructor && !m.ends_with("D1Ev") {
331                 continue;
332             }
333 
334             return Some(m);
335         }
336     }
337 
338     let mut mangling = cursor.mangling();
339     if mangling.is_empty() {
340         return None;
341     }
342 
343     if is_destructor {
344         // With old (3.8-) libclang versions, and the Itanium ABI, clang returns
345         // the "destructor group 0" symbol, which means that it'll try to free
346         // memory, which definitely isn't what we want.
347         //
348         // Explicitly force the destructor group 1 symbol.
349         //
350         // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special
351         // for the reference, and http://stackoverflow.com/a/6614369/1091587 for
352         // a more friendly explanation.
353         //
354         // We don't need to do this for constructors since clang seems to always
355         // have returned the C1 constructor.
356         //
357         // FIXME(emilio): Can a legit symbol in other ABIs end with this string?
358         // I don't think so, but if it can this would become a linker error
359         // anyway, not an invalid free at runtime.
360         //
361         // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with
362         // time.
363         if mangling.ends_with("D0Ev") {
364             let new_len = mangling.len() - 4;
365             mangling.truncate(new_len);
366             mangling.push_str("D1Ev");
367         }
368     }
369 
370     Some(mangling)
371 }
372 
args_from_ty_and_cursor( ty: &clang::Type, cursor: &clang::Cursor, ctx: &mut BindgenContext, ) -> Vec<(Option<String>, TypeId)>373 fn args_from_ty_and_cursor(
374     ty: &clang::Type,
375     cursor: &clang::Cursor,
376     ctx: &mut BindgenContext,
377 ) -> Vec<(Option<String>, TypeId)> {
378     let cursor_args = cursor.args().unwrap_or_default().into_iter();
379     let type_args = ty.args().unwrap_or_default().into_iter();
380 
381     // Argument types can be found in either the cursor or the type, but argument names may only be
382     // found on the cursor. We often have access to both a type and a cursor for each argument, but
383     // in some cases we may only have one.
384     //
385     // Prefer using the type as the source of truth for the argument's type, but fall back to
386     // inspecting the cursor (this happens for Objective C interfaces).
387     //
388     // Prefer using the cursor for the argument's type, but fall back to using the parent's cursor
389     // (this happens for function pointer return types).
390     cursor_args
391         .map(Some)
392         .chain(std::iter::repeat(None))
393         .zip(type_args.map(Some).chain(std::iter::repeat(None)))
394         .take_while(|(cur, ty)| cur.is_some() || ty.is_some())
395         .map(|(arg_cur, arg_ty)| {
396             let name = arg_cur.map(|a| a.spelling()).and_then(|name| {
397                 if name.is_empty() {
398                     None
399                 } else {
400                     Some(name)
401                 }
402             });
403 
404             let cursor = arg_cur.unwrap_or(*cursor);
405             let ty = arg_ty.unwrap_or_else(|| cursor.cur_type());
406             (name, Item::from_ty_or_ref(ty, cursor, None, ctx))
407         })
408         .collect()
409 }
410 
411 impl FunctionSig {
412     /// Get the function name.
name(&self) -> &str413     pub(crate) fn name(&self) -> &str {
414         &self.name
415     }
416 
417     /// Construct a new function signature from the given Clang type.
from_ty( ty: &clang::Type, cursor: &clang::Cursor, ctx: &mut BindgenContext, ) -> Result<Self, ParseError>418     pub(crate) fn from_ty(
419         ty: &clang::Type,
420         cursor: &clang::Cursor,
421         ctx: &mut BindgenContext,
422     ) -> Result<Self, ParseError> {
423         use clang_sys::*;
424         debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
425 
426         // Skip function templates
427         let kind = cursor.kind();
428         if kind == CXCursor_FunctionTemplate {
429             return Err(ParseError::Continue);
430         }
431 
432         let spelling = cursor.spelling();
433 
434         // Don't parse operatorxx functions in C++
435         let is_operator = |spelling: &str| {
436             spelling.starts_with("operator") &&
437                 !clang::is_valid_identifier(spelling)
438         };
439         if is_operator(&spelling) {
440             return Err(ParseError::Continue);
441         }
442 
443         // Constructors of non-type template parameter classes for some reason
444         // include the template parameter in their name. Just skip them, since
445         // we don't handle well non-type template parameters anyway.
446         if (kind == CXCursor_Constructor || kind == CXCursor_Destructor) &&
447             spelling.contains('<')
448         {
449             return Err(ParseError::Continue);
450         }
451 
452         let cursor = if cursor.is_valid() {
453             *cursor
454         } else {
455             ty.declaration()
456         };
457 
458         let mut args = match kind {
459             CXCursor_FunctionDecl |
460             CXCursor_Constructor |
461             CXCursor_CXXMethod |
462             CXCursor_ObjCInstanceMethodDecl |
463             CXCursor_ObjCClassMethodDecl => {
464                 args_from_ty_and_cursor(ty, &cursor, ctx)
465             }
466             _ => {
467                 // For non-CXCursor_FunctionDecl, visiting the cursor's children
468                 // is the only reliable way to get parameter names.
469                 let mut args = vec![];
470                 cursor.visit(|c| {
471                     if c.kind() == CXCursor_ParmDecl {
472                         let ty =
473                             Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
474                         let name = c.spelling();
475                         let name =
476                             if name.is_empty() { None } else { Some(name) };
477                         args.push((name, ty));
478                     }
479                     CXChildVisit_Continue
480                 });
481 
482                 if args.is_empty() {
483                     // FIXME(emilio): Sometimes libclang doesn't expose the
484                     // right AST for functions tagged as stdcall and such...
485                     //
486                     // https://bugs.llvm.org/show_bug.cgi?id=45919
487                     args_from_ty_and_cursor(ty, &cursor, ctx)
488                 } else {
489                     args
490                 }
491             }
492         };
493 
494         let (must_use, mut is_divergent) =
495             if ctx.options().enable_function_attribute_detection {
496                 let [must_use, no_return, no_return_cpp] = cursor.has_attrs(&[
497                     Attribute::MUST_USE,
498                     Attribute::NO_RETURN,
499                     Attribute::NO_RETURN_CPP,
500                 ]);
501                 (must_use, no_return || no_return_cpp)
502             } else {
503                 Default::default()
504             };
505 
506         // This looks easy to break but the clang parser keeps the type spelling clean even if
507         // other attributes are added.
508         is_divergent =
509             is_divergent || ty.spelling().contains("__attribute__((noreturn))");
510 
511         let is_method = kind == CXCursor_CXXMethod;
512         let is_constructor = kind == CXCursor_Constructor;
513         let is_destructor = kind == CXCursor_Destructor;
514         if (is_constructor || is_destructor || is_method) &&
515             cursor.lexical_parent() != cursor.semantic_parent()
516         {
517             // Only parse constructors once.
518             return Err(ParseError::Continue);
519         }
520 
521         if is_method || is_constructor || is_destructor {
522             let is_const = is_method && cursor.method_is_const();
523             let is_virtual = is_method && cursor.method_is_virtual();
524             let is_static = is_method && cursor.method_is_static();
525             if !is_static && !is_virtual {
526                 let parent = cursor.semantic_parent();
527                 let class = Item::parse(parent, None, ctx)
528                     .expect("Expected to parse the class");
529                 // The `class` most likely is not finished parsing yet, so use
530                 // the unchecked variant.
531                 let class = class.as_type_id_unchecked();
532 
533                 let class = if is_const {
534                     let const_class_id = ctx.next_item_id();
535                     ctx.build_const_wrapper(
536                         const_class_id,
537                         class,
538                         None,
539                         &parent.cur_type(),
540                     )
541                 } else {
542                     class
543                 };
544 
545                 let ptr =
546                     Item::builtin_type(TypeKind::Pointer(class), false, ctx);
547                 args.insert(0, (Some("this".into()), ptr));
548             } else if is_virtual {
549                 let void = Item::builtin_type(TypeKind::Void, false, ctx);
550                 let ptr =
551                     Item::builtin_type(TypeKind::Pointer(void), false, ctx);
552                 args.insert(0, (Some("this".into()), ptr));
553             }
554         }
555 
556         let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl ||
557             kind == CXCursor_ObjCClassMethodDecl
558         {
559             ty.ret_type()
560                 .or_else(|| cursor.ret_type())
561                 .ok_or(ParseError::Continue)?
562         } else {
563             ty.ret_type().ok_or(ParseError::Continue)?
564         };
565 
566         let ret = if is_constructor && ctx.is_target_wasm32() {
567             // Constructors in Clang wasm32 target return a pointer to the object
568             // being constructed.
569             let void = Item::builtin_type(TypeKind::Void, false, ctx);
570             Item::builtin_type(TypeKind::Pointer(void), false, ctx)
571         } else {
572             Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx)
573         };
574 
575         // Clang plays with us at "find the calling convention", see #549 and
576         // co. This seems to be a better fix than that commit.
577         let mut call_conv = ty.call_conv();
578         if let Some(ty) = cursor.cur_type().canonical_type().pointee_type() {
579             let cursor_call_conv = ty.call_conv();
580             if cursor_call_conv != CXCallingConv_Invalid {
581                 call_conv = cursor_call_conv;
582             }
583         }
584 
585         let abi = get_abi(call_conv);
586 
587         if abi.is_unknown() {
588             warn!("Unknown calling convention: {:?}", call_conv);
589         }
590 
591         Ok(Self {
592             name: spelling,
593             return_type: ret,
594             argument_types: args,
595             is_variadic: ty.is_variadic(),
596             is_divergent,
597             must_use,
598             abi,
599         })
600     }
601 
602     /// Get this function signature's return type.
return_type(&self) -> TypeId603     pub(crate) fn return_type(&self) -> TypeId {
604         self.return_type
605     }
606 
607     /// Get this function signature's argument (name, type) pairs.
argument_types(&self) -> &[(Option<String>, TypeId)]608     pub(crate) fn argument_types(&self) -> &[(Option<String>, TypeId)] {
609         &self.argument_types
610     }
611 
612     /// Get this function signature's ABI.
abi( &self, ctx: &BindgenContext, name: Option<&str>, ) -> crate::codegen::error::Result<ClangAbi>613     pub(crate) fn abi(
614         &self,
615         ctx: &BindgenContext,
616         name: Option<&str>,
617     ) -> crate::codegen::error::Result<ClangAbi> {
618         // FIXME (pvdrz): Try to do this check lazily instead. Maybe store the ABI inside `ctx`
619         // instead?.
620         let abi = if let Some(name) = name {
621             if let Some((abi, _)) = ctx
622                 .options()
623                 .abi_overrides
624                 .iter()
625                 .find(|(_, regex_set)| regex_set.matches(name))
626             {
627                 ClangAbi::Known(*abi)
628             } else {
629                 self.abi
630             }
631         } else if let Some((abi, _)) = ctx
632             .options()
633             .abi_overrides
634             .iter()
635             .find(|(_, regex_set)| regex_set.matches(&self.name))
636         {
637             ClangAbi::Known(*abi)
638         } else {
639             self.abi
640         };
641 
642         match abi {
643             ClangAbi::Known(Abi::ThisCall)
644                 if !ctx.options().rust_features().thiscall_abi =>
645             {
646                 Err(crate::codegen::error::Error::UnsupportedAbi("thiscall"))
647             }
648             ClangAbi::Known(Abi::Vectorcall)
649                 if !ctx.options().rust_features().vectorcall_abi =>
650             {
651                 Err(crate::codegen::error::Error::UnsupportedAbi("vectorcall"))
652             }
653             ClangAbi::Known(Abi::CUnwind)
654                 if !ctx.options().rust_features().c_unwind_abi =>
655             {
656                 Err(crate::codegen::error::Error::UnsupportedAbi("C-unwind"))
657             }
658             ClangAbi::Known(Abi::EfiApi)
659                 if !ctx.options().rust_features().abi_efiapi =>
660             {
661                 Err(crate::codegen::error::Error::UnsupportedAbi("efiapi"))
662             }
663             ClangAbi::Known(Abi::Win64) if self.is_variadic() => {
664                 Err(crate::codegen::error::Error::UnsupportedAbi("Win64"))
665             }
666             abi => Ok(abi),
667         }
668     }
669 
670     /// Is this function signature variadic?
is_variadic(&self) -> bool671     pub(crate) fn is_variadic(&self) -> bool {
672         // Clang reports some functions as variadic when they *might* be
673         // variadic. We do the argument check because rust doesn't codegen well
674         // variadic functions without an initial argument.
675         self.is_variadic && !self.argument_types.is_empty()
676     }
677 
678     /// Must this function's return value be used?
must_use(&self) -> bool679     pub(crate) fn must_use(&self) -> bool {
680         self.must_use
681     }
682 
683     /// Are function pointers with this signature able to derive Rust traits?
684     /// Rust only supports deriving traits for function pointers with a limited
685     /// number of parameters and a couple ABIs.
686     ///
687     /// For more details, see:
688     ///
689     /// * <https://github.com/rust-lang/rust-bindgen/issues/547>,
690     /// * <https://github.com/rust-lang/rust/issues/38848>,
691     /// * and <https://github.com/rust-lang/rust/issues/40158>
function_pointers_can_derive(&self) -> bool692     pub(crate) fn function_pointers_can_derive(&self) -> bool {
693         if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
694             return false;
695         }
696 
697         matches!(self.abi, ClangAbi::Known(Abi::C) | ClangAbi::Unknown(..))
698     }
699 
700     /// Whether this function has attributes marking it as divergent.
is_divergent(&self) -> bool701     pub(crate) fn is_divergent(&self) -> bool {
702         self.is_divergent
703     }
704 }
705 
706 impl ClangSubItemParser for Function {
parse( cursor: clang::Cursor, context: &mut BindgenContext, ) -> Result<ParseResult<Self>, ParseError>707     fn parse(
708         cursor: clang::Cursor,
709         context: &mut BindgenContext,
710     ) -> Result<ParseResult<Self>, ParseError> {
711         use clang_sys::*;
712 
713         let kind = match FunctionKind::from_cursor(&cursor) {
714             None => return Err(ParseError::Continue),
715             Some(k) => k,
716         };
717 
718         debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
719         let visibility = cursor.visibility();
720         if visibility != CXVisibility_Default {
721             return Err(ParseError::Continue);
722         }
723 
724         if cursor.access_specifier() == CX_CXXPrivate {
725             return Err(ParseError::Continue);
726         }
727 
728         let linkage = cursor.linkage();
729         let linkage = match linkage {
730             CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External,
731             CXLinkage_Internal => Linkage::Internal,
732             _ => return Err(ParseError::Continue),
733         };
734 
735         if cursor.is_inlined_function() ||
736             cursor
737                 .definition()
738                 .map_or(false, |x| x.is_inlined_function())
739         {
740             if !context.options().generate_inline_functions &&
741                 !context.options().wrap_static_fns
742             {
743                 return Err(ParseError::Continue);
744             }
745 
746             if cursor.is_deleted_function() {
747                 return Err(ParseError::Continue);
748             }
749 
750             // We cannot handle `inline` functions that are not `static`.
751             if context.options().wrap_static_fns &&
752                 cursor.is_inlined_function() &&
753                 matches!(linkage, Linkage::External)
754             {
755                 return Err(ParseError::Continue);
756             }
757         }
758 
759         // Grab the signature using Item::from_ty.
760         let sig = Item::from_ty(&cursor.cur_type(), cursor, None, context)?;
761 
762         let mut name = cursor.spelling();
763         assert!(!name.is_empty(), "Empty function name?");
764 
765         if cursor.kind() == CXCursor_Destructor {
766             // Remove the leading `~`. The alternative to this is special-casing
767             // code-generation for destructor functions, which seems less than
768             // ideal.
769             if name.starts_with('~') {
770                 name.remove(0);
771             }
772 
773             // Add a suffix to avoid colliding with constructors. This would be
774             // technically fine (since we handle duplicated functions/methods),
775             // but seems easy enough to handle it here.
776             name.push_str("_destructor");
777         }
778         if let Some(nm) = context.options().last_callback(|callbacks| {
779             callbacks.generated_name_override(ItemInfo {
780                 name: name.as_str(),
781                 kind: ItemKind::Function,
782             })
783         }) {
784             name = nm;
785         }
786         assert!(!name.is_empty(), "Empty function name.");
787 
788         let mangled_name = cursor_mangling(context, &cursor);
789 
790         let link_name = context.options().last_callback(|callbacks| {
791             callbacks.generated_link_name_override(ItemInfo {
792                 name: name.as_str(),
793                 kind: ItemKind::Function,
794             })
795         });
796 
797         let function = Self::new(
798             name.clone(),
799             mangled_name,
800             link_name,
801             sig,
802             kind,
803             linkage,
804         );
805 
806         Ok(ParseResult::New(function, Some(cursor)))
807     }
808 }
809 
810 impl Trace for FunctionSig {
811     type Extra = ();
812 
trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &()) where T: Tracer,813     fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
814     where
815         T: Tracer,
816     {
817         tracer.visit_kind(self.return_type().into(), EdgeKind::FunctionReturn);
818 
819         for &(_, ty) in self.argument_types() {
820             tracer.visit_kind(ty.into(), EdgeKind::FunctionParameter);
821         }
822     }
823 }
824