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