1//! Intermediate representation for C/C++ functions and methods.
2
3use super::comp::MethodKind;
4use super::context::{BindgenContext, TypeId};
5use super::dot::DotAttributes;
6use super::item::Item;
7use super::traversal::{EdgeKind, Trace, Tracer};
8use super::ty::TypeKind;
9use crate::callbacks::{ItemInfo, ItemKind};
10use crate::clang::{self, ABIKind, Attribute};
11use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
12use clang_sys::{self, CXCallingConv};
13
14use quote::TokenStreamExt;
15use std::io;
16use std::str::FromStr;
17
18const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
19
20/// What kind of a function are we looking at?
21#[derive(Debug, Copy, Clone, PartialEq, Eq)]
22pub(crate) enum FunctionKind {
23 /// A plain, free function.
24 Function,
25 /// A method of some kind.
26 Method(MethodKind),
27}
28
29impl FunctionKind {
30 /// Given a clang cursor, return the kind of function it represents, or
31 /// `None` otherwise.
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)]
66pub(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)]
78pub(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
98impl Function {
99 /// Construct a new function.
100 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.
119 pub(crate) fn name(&self) -> &str {
120 &self.name
121 }
122
123 /// Get this function's name.
124 pub(crate) fn mangled_name(&self) -> Option<&str> {
125 self.mangled_name.as_deref()
126 }
127
128 /// Get this function's link name.
129 pub fn link_name(&self) -> Option<&str> {
130 self.link_name.as_deref()
131 }
132
133 /// Get this function's signature type.
134 pub(crate) fn signature(&self) -> TypeId {
135 self.signature
136 }
137
138 /// Get this function's kind.
139 pub(crate) fn kind(&self) -> FunctionKind {
140 self.kind
141 }
142
143 /// Get this function's linkage.
144 pub(crate) fn linkage(&self) -> Linkage {
145 self.linkage
146 }
147}
148
149impl DotAttributes for Function {
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: &String) = self.mangled_name {
159 let mangled: String =
160 mangled.chars().flat_map(|c: char| 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)]
174pub 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
197impl FromStr for Abi {
198 type Err = String;
199
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
217impl std::fmt::Display for Abi {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 let s: &str = 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
236impl quote::ToTokens for Abi {
237 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
238 let abi: String = self.to_string();
239 tokens.append_all(iter:quote! { #abi });
240 }
241}
242
243/// An ABI extracted from a clang cursor.
244#[derive(Debug, Copy, Clone)]
245pub(crate) enum ClangAbi {
246 /// An ABI known by Rust.
247 Known(Abi),
248 /// An unknown or invalid ABI.
249 Unknown(CXCallingConv),
250}
251
252impl ClangAbi {
253 /// Returns whether this Abi is known or not.
254 fn is_unknown(&self) -> bool {
255 matches!(*self, ClangAbi::Unknown(..))
256 }
257}
258
259impl quote::ToTokens for ClangAbi {
260 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
261 match *self {
262 Self::Known(abi: Abi) => abi.to_tokens(tokens),
263 Self::Unknown(cc: i32) => panic!(
264 "Cannot turn unknown calling convention to tokens: {:?}",
265 cc
266 ),
267 }
268 }
269}
270
271/// A function signature.
272#[derive(Debug)]
273pub(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
295fn 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 CXCallingConv_AArch64VectorCall => ClangAbi::Known(Abi::Vectorcall),
307 other: i32 => ClangAbi::Unknown(other),
308 }
309}
310
311/// Get the mangled name for the cursor's referent.
312pub(crate) fn cursor_mangling(
313 ctx: &BindgenContext,
314 cursor: &clang::Cursor,
315) -> Option<String> {
316 if !ctx.options().enable_mangling {
317 return None;
318 }
319
320 // We early return here because libclang may crash in some case
321 // if we pass in a variable inside a partial specialized template.
322 // See rust-lang/rust-bindgen#67, and rust-lang/rust-bindgen#462.
323 if cursor.is_in_non_fully_specialized_template() {
324 return None;
325 }
326
327 let is_itanium_abi = ctx.abi_kind() == ABIKind::GenericItanium;
328 let is_destructor = cursor.kind() == clang_sys::CXCursor_Destructor;
329 if let Ok(mut manglings) = cursor.cxx_manglings() {
330 while let Some(m) = manglings.pop() {
331 // Only generate the destructor group 1, see below.
332 if is_itanium_abi && is_destructor && !m.ends_with("D1Ev") {
333 continue;
334 }
335
336 return Some(m);
337 }
338 }
339
340 let mut mangling = cursor.mangling();
341 if mangling.is_empty() {
342 return None;
343 }
344
345 if is_itanium_abi && is_destructor {
346 // With old (3.8-) libclang versions, and the Itanium ABI, clang returns
347 // the "destructor group 0" symbol, which means that it'll try to free
348 // memory, which definitely isn't what we want.
349 //
350 // Explicitly force the destructor group 1 symbol.
351 //
352 // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special
353 // for the reference, and http://stackoverflow.com/a/6614369/1091587 for
354 // a more friendly explanation.
355 //
356 // We don't need to do this for constructors since clang seems to always
357 // have returned the C1 constructor.
358 //
359 // FIXME(emilio): Can a legit symbol in other ABIs end with this string?
360 // I don't think so, but if it can this would become a linker error
361 // anyway, not an invalid free at runtime.
362 //
363 // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with
364 // time.
365 if mangling.ends_with("D0Ev") {
366 let new_len = mangling.len() - 4;
367 mangling.truncate(new_len);
368 mangling.push_str("D1Ev");
369 }
370 }
371
372 Some(mangling)
373}
374
375fn args_from_ty_and_cursor(
376 ty: &clang::Type,
377 cursor: &clang::Cursor,
378 ctx: &mut BindgenContext,
379) -> Vec<(Option<String>, TypeId)> {
380 let cursor_args = cursor.args().unwrap_or_default().into_iter();
381 let type_args = ty.args().unwrap_or_default().into_iter();
382
383 // Argument types can be found in either the cursor or the type, but argument names may only be
384 // found on the cursor. We often have access to both a type and a cursor for each argument, but
385 // in some cases we may only have one.
386 //
387 // Prefer using the type as the source of truth for the argument's type, but fall back to
388 // inspecting the cursor (this happens for Objective C interfaces).
389 //
390 // Prefer using the cursor for the argument's type, but fall back to using the parent's cursor
391 // (this happens for function pointer return types).
392 cursor_args
393 .map(Some)
394 .chain(std::iter::repeat(None))
395 .zip(type_args.map(Some).chain(std::iter::repeat(None)))
396 .take_while(|(cur, ty)| cur.is_some() || ty.is_some())
397 .map(|(arg_cur, arg_ty)| {
398 let name = arg_cur.map(|a| a.spelling()).and_then(|name| {
399 if name.is_empty() {
400 None
401 } else {
402 Some(name)
403 }
404 });
405
406 let cursor = arg_cur.unwrap_or(*cursor);
407 let ty = arg_ty.unwrap_or_else(|| cursor.cur_type());
408 (name, Item::from_ty_or_ref(ty, cursor, None, ctx))
409 })
410 .collect()
411}
412
413impl FunctionSig {
414 /// Get the function name.
415 pub(crate) fn name(&self) -> &str {
416 &self.name
417 }
418
419 /// Construct a new function signature from the given Clang type.
420 pub(crate) fn from_ty(
421 ty: &clang::Type,
422 cursor: &clang::Cursor,
423 ctx: &mut BindgenContext,
424 ) -> Result<Self, ParseError> {
425 use clang_sys::*;
426 debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
427
428 // Skip function templates
429 let kind = cursor.kind();
430 if kind == CXCursor_FunctionTemplate {
431 return Err(ParseError::Continue);
432 }
433
434 let spelling = cursor.spelling();
435
436 // Don't parse operatorxx functions in C++
437 let is_operator = |spelling: &str| {
438 spelling.starts_with("operator") &&
439 !clang::is_valid_identifier(spelling)
440 };
441 if is_operator(&spelling) {
442 return Err(ParseError::Continue);
443 }
444
445 // Constructors of non-type template parameter classes for some reason
446 // include the template parameter in their name. Just skip them, since
447 // we don't handle well non-type template parameters anyway.
448 if (kind == CXCursor_Constructor || kind == CXCursor_Destructor) &&
449 spelling.contains('<')
450 {
451 return Err(ParseError::Continue);
452 }
453
454 let cursor = if cursor.is_valid() {
455 *cursor
456 } else {
457 ty.declaration()
458 };
459
460 let mut args = match kind {
461 CXCursor_FunctionDecl |
462 CXCursor_Constructor |
463 CXCursor_CXXMethod |
464 CXCursor_ObjCInstanceMethodDecl |
465 CXCursor_ObjCClassMethodDecl => {
466 args_from_ty_and_cursor(ty, &cursor, ctx)
467 }
468 _ => {
469 // For non-CXCursor_FunctionDecl, visiting the cursor's children
470 // is the only reliable way to get parameter names.
471 let mut args = vec![];
472 cursor.visit(|c| {
473 if c.kind() == CXCursor_ParmDecl {
474 let ty =
475 Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
476 let name = c.spelling();
477 let name =
478 if name.is_empty() { None } else { Some(name) };
479 args.push((name, ty));
480 }
481 CXChildVisit_Continue
482 });
483
484 if args.is_empty() {
485 // FIXME(emilio): Sometimes libclang doesn't expose the
486 // right AST for functions tagged as stdcall and such...
487 //
488 // https://bugs.llvm.org/show_bug.cgi?id=45919
489 args_from_ty_and_cursor(ty, &cursor, ctx)
490 } else {
491 args
492 }
493 }
494 };
495
496 let (must_use, mut is_divergent) =
497 if ctx.options().enable_function_attribute_detection {
498 let [must_use, no_return, no_return_cpp] = cursor.has_attrs(&[
499 Attribute::MUST_USE,
500 Attribute::NO_RETURN,
501 Attribute::NO_RETURN_CPP,
502 ]);
503 (must_use, no_return || no_return_cpp)
504 } else {
505 Default::default()
506 };
507
508 // Check if the type contains __attribute__((noreturn)) outside of parentheses. This is
509 // somewhat fragile, but it seems to be the only way to get at this information as of
510 // libclang 9.
511 let ty_spelling = ty.spelling();
512 let has_attribute_noreturn = ty_spelling
513 .match_indices("__attribute__((noreturn))")
514 .any(|(i, _)| {
515 let depth = ty_spelling[..i]
516 .bytes()
517 .filter_map(|ch| match ch {
518 b'(' => Some(1),
519 b')' => Some(-1),
520 _ => None,
521 })
522 .sum::<isize>();
523 depth == 0
524 });
525 is_divergent = is_divergent || has_attribute_noreturn;
526
527 let is_method = kind == CXCursor_CXXMethod;
528 let is_constructor = kind == CXCursor_Constructor;
529 let is_destructor = kind == CXCursor_Destructor;
530 if (is_constructor || is_destructor || is_method) &&
531 cursor.lexical_parent() != cursor.semantic_parent()
532 {
533 // Only parse constructors once.
534 return Err(ParseError::Continue);
535 }
536
537 if is_method || is_constructor || is_destructor {
538 let is_const = is_method && cursor.method_is_const();
539 let is_virtual = is_method && cursor.method_is_virtual();
540 let is_static = is_method && cursor.method_is_static();
541 if !is_static && !is_virtual {
542 let parent = cursor.semantic_parent();
543 let class = Item::parse(parent, None, ctx)
544 .expect("Expected to parse the class");
545 // The `class` most likely is not finished parsing yet, so use
546 // the unchecked variant.
547 let class = class.as_type_id_unchecked();
548
549 let class = if is_const {
550 let const_class_id = ctx.next_item_id();
551 ctx.build_const_wrapper(
552 const_class_id,
553 class,
554 None,
555 &parent.cur_type(),
556 )
557 } else {
558 class
559 };
560
561 let ptr =
562 Item::builtin_type(TypeKind::Pointer(class), false, ctx);
563 args.insert(0, (Some("this".into()), ptr));
564 } else if is_virtual {
565 let void = Item::builtin_type(TypeKind::Void, false, ctx);
566 let ptr =
567 Item::builtin_type(TypeKind::Pointer(void), false, ctx);
568 args.insert(0, (Some("this".into()), ptr));
569 }
570 }
571
572 let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl ||
573 kind == CXCursor_ObjCClassMethodDecl
574 {
575 ty.ret_type()
576 .or_else(|| cursor.ret_type())
577 .ok_or(ParseError::Continue)?
578 } else {
579 ty.ret_type().ok_or(ParseError::Continue)?
580 };
581
582 let ret = if is_constructor && ctx.is_target_wasm32() {
583 // Constructors in Clang wasm32 target return a pointer to the object
584 // being constructed.
585 let void = Item::builtin_type(TypeKind::Void, false, ctx);
586 Item::builtin_type(TypeKind::Pointer(void), false, ctx)
587 } else {
588 Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx)
589 };
590
591 // Clang plays with us at "find the calling convention", see #549 and
592 // co. This seems to be a better fix than that commit.
593 let mut call_conv = ty.call_conv();
594 if let Some(ty) = cursor.cur_type().canonical_type().pointee_type() {
595 let cursor_call_conv = ty.call_conv();
596 if cursor_call_conv != CXCallingConv_Invalid {
597 call_conv = cursor_call_conv;
598 }
599 }
600
601 let abi = get_abi(call_conv);
602
603 if abi.is_unknown() {
604 warn!("Unknown calling convention: {:?}", call_conv);
605 }
606
607 Ok(Self {
608 name: spelling,
609 return_type: ret,
610 argument_types: args,
611 is_variadic: ty.is_variadic(),
612 is_divergent,
613 must_use,
614 abi,
615 })
616 }
617
618 /// Get this function signature's return type.
619 pub(crate) fn return_type(&self) -> TypeId {
620 self.return_type
621 }
622
623 /// Get this function signature's argument (name, type) pairs.
624 pub(crate) fn argument_types(&self) -> &[(Option<String>, TypeId)] {
625 &self.argument_types
626 }
627
628 /// Get this function signature's ABI.
629 pub(crate) fn abi(
630 &self,
631 ctx: &BindgenContext,
632 name: Option<&str>,
633 ) -> crate::codegen::error::Result<ClangAbi> {
634 // FIXME (pvdrz): Try to do this check lazily instead. Maybe store the ABI inside `ctx`
635 // instead?.
636 let abi = if let Some(name) = name {
637 if let Some((abi, _)) = ctx
638 .options()
639 .abi_overrides
640 .iter()
641 .find(|(_, regex_set)| regex_set.matches(name))
642 {
643 ClangAbi::Known(*abi)
644 } else {
645 self.abi
646 }
647 } else if let Some((abi, _)) = ctx
648 .options()
649 .abi_overrides
650 .iter()
651 .find(|(_, regex_set)| regex_set.matches(&self.name))
652 {
653 ClangAbi::Known(*abi)
654 } else {
655 self.abi
656 };
657
658 match abi {
659 ClangAbi::Known(Abi::ThisCall)
660 if !ctx.options().rust_features().thiscall_abi =>
661 {
662 Err(crate::codegen::error::Error::UnsupportedAbi("thiscall"))
663 }
664 ClangAbi::Known(Abi::Vectorcall)
665 if !ctx.options().rust_features().vectorcall_abi =>
666 {
667 Err(crate::codegen::error::Error::UnsupportedAbi("vectorcall"))
668 }
669 ClangAbi::Known(Abi::CUnwind)
670 if !ctx.options().rust_features().c_unwind_abi =>
671 {
672 Err(crate::codegen::error::Error::UnsupportedAbi("C-unwind"))
673 }
674 ClangAbi::Known(Abi::EfiApi)
675 if !ctx.options().rust_features().abi_efiapi =>
676 {
677 Err(crate::codegen::error::Error::UnsupportedAbi("efiapi"))
678 }
679 ClangAbi::Known(Abi::Win64) if self.is_variadic() => {
680 Err(crate::codegen::error::Error::UnsupportedAbi("Win64"))
681 }
682 abi => Ok(abi),
683 }
684 }
685
686 /// Is this function signature variadic?
687 pub(crate) fn is_variadic(&self) -> bool {
688 // Clang reports some functions as variadic when they *might* be
689 // variadic. We do the argument check because rust doesn't codegen well
690 // variadic functions without an initial argument.
691 self.is_variadic && !self.argument_types.is_empty()
692 }
693
694 /// Must this function's return value be used?
695 pub(crate) fn must_use(&self) -> bool {
696 self.must_use
697 }
698
699 /// Are function pointers with this signature able to derive Rust traits?
700 /// Rust only supports deriving traits for function pointers with a limited
701 /// number of parameters and a couple ABIs.
702 ///
703 /// For more details, see:
704 ///
705 /// * <https://github.com/rust-lang/rust-bindgen/issues/547>,
706 /// * <https://github.com/rust-lang/rust/issues/38848>,
707 /// * and <https://github.com/rust-lang/rust/issues/40158>
708 pub(crate) fn function_pointers_can_derive(&self) -> bool {
709 if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
710 return false;
711 }
712
713 matches!(self.abi, ClangAbi::Known(Abi::C) | ClangAbi::Unknown(..))
714 }
715
716 /// Whether this function has attributes marking it as divergent.
717 pub(crate) fn is_divergent(&self) -> bool {
718 self.is_divergent
719 }
720}
721
722impl ClangSubItemParser for Function {
723 fn parse(
724 cursor: clang::Cursor,
725 context: &mut BindgenContext,
726 ) -> Result<ParseResult<Self>, ParseError> {
727 use clang_sys::*;
728
729 let kind = match FunctionKind::from_cursor(&cursor) {
730 None => return Err(ParseError::Continue),
731 Some(k) => k,
732 };
733
734 debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
735 let visibility = cursor.visibility();
736 if visibility != CXVisibility_Default {
737 return Err(ParseError::Continue);
738 }
739
740 if cursor.access_specifier() == CX_CXXPrivate {
741 return Err(ParseError::Continue);
742 }
743
744 let linkage = cursor.linkage();
745 let linkage = match linkage {
746 CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External,
747 CXLinkage_Internal => Linkage::Internal,
748 _ => return Err(ParseError::Continue),
749 };
750
751 if cursor.is_inlined_function() ||
752 cursor
753 .definition()
754 .map_or(false, |x| x.is_inlined_function())
755 {
756 if !context.options().generate_inline_functions &&
757 !context.options().wrap_static_fns
758 {
759 return Err(ParseError::Continue);
760 }
761
762 if cursor.is_deleted_function() {
763 return Err(ParseError::Continue);
764 }
765
766 // We cannot handle `inline` functions that are not `static`.
767 if context.options().wrap_static_fns &&
768 cursor.is_inlined_function() &&
769 matches!(linkage, Linkage::External)
770 {
771 return Err(ParseError::Continue);
772 }
773 }
774
775 // Grab the signature using Item::from_ty.
776 let sig = Item::from_ty(&cursor.cur_type(), cursor, None, context)?;
777
778 let mut name = cursor.spelling();
779 assert!(!name.is_empty(), "Empty function name?");
780
781 if cursor.kind() == CXCursor_Destructor {
782 // Remove the leading `~`. The alternative to this is special-casing
783 // code-generation for destructor functions, which seems less than
784 // ideal.
785 if name.starts_with('~') {
786 name.remove(0);
787 }
788
789 // Add a suffix to avoid colliding with constructors. This would be
790 // technically fine (since we handle duplicated functions/methods),
791 // but seems easy enough to handle it here.
792 name.push_str("_destructor");
793 }
794 if let Some(nm) = context.options().last_callback(|callbacks| {
795 callbacks.generated_name_override(ItemInfo {
796 name: name.as_str(),
797 kind: ItemKind::Function,
798 })
799 }) {
800 name = nm;
801 }
802 assert!(!name.is_empty(), "Empty function name.");
803
804 let mangled_name = cursor_mangling(context, &cursor);
805
806 let link_name = context.options().last_callback(|callbacks| {
807 callbacks.generated_link_name_override(ItemInfo {
808 name: name.as_str(),
809 kind: ItemKind::Function,
810 })
811 });
812
813 let function = Self::new(
814 name.clone(),
815 mangled_name,
816 link_name,
817 sig,
818 kind,
819 linkage,
820 );
821
822 Ok(ParseResult::New(function, Some(cursor)))
823 }
824}
825
826impl Trace for FunctionSig {
827 type Extra = ();
828
829 fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
830 where
831 T: Tracer,
832 {
833 tracer.visit_kind(self.return_type().into(), kind:EdgeKind::FunctionReturn);
834
835 for &(_, ty: TypeId) in self.argument_types() {
836 tracer.visit_kind(item:ty.into(), kind:EdgeKind::FunctionParameter);
837 }
838 }
839}
840