bindgen/ir/
function.rs

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 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) = self.mangled_name {
159            let mangled: String =
160                mangled.chars().flat_map(|c| 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 = 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 = self.to_string();
235        tokens.append_all(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.to_tokens(tokens),
259            Self::Unknown(cc) => 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 | CXCallingConv_C => ClangAbi::Known(Abi::C),
294        CXCallingConv_X86StdCall => ClangAbi::Known(Abi::Stdcall),
295        CXCallingConv_X86FastCall => ClangAbi::Known(Abi::Fastcall),
296        CXCallingConv_X86ThisCall => ClangAbi::Known(Abi::ThisCall),
297        CXCallingConv_X86VectorCall | CXCallingConv_AArch64VectorCall => {
298            ClangAbi::Known(Abi::Vectorcall)
299        }
300        CXCallingConv_AAPCS => ClangAbi::Known(Abi::Aapcs),
301        CXCallingConv_X86_64Win64 => ClangAbi::Known(Abi::Win64),
302        other => 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) && !ctx.options().represent_cxx_operators {
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 &&
537                (!is_virtual ||
538                    ctx.options().use_specific_virtual_function_receiver)
539            {
540                let parent = cursor.semantic_parent();
541                let class = Item::parse(parent, None, ctx)
542                    .expect("Expected to parse the class");
543                // The `class` most likely is not finished parsing yet, so use
544                // the unchecked variant.
545                let class = class.as_type_id_unchecked();
546
547                let class = if is_const {
548                    let const_class_id = ctx.next_item_id();
549                    ctx.build_const_wrapper(
550                        const_class_id,
551                        class,
552                        None,
553                        &parent.cur_type(),
554                    )
555                } else {
556                    class
557                };
558
559                let ptr =
560                    Item::builtin_type(TypeKind::Pointer(class), false, ctx);
561                args.insert(0, (Some("this".into()), ptr));
562            } else if is_virtual {
563                let void = Item::builtin_type(TypeKind::Void, false, ctx);
564                let ptr =
565                    Item::builtin_type(TypeKind::Pointer(void), false, ctx);
566                args.insert(0, (Some("this".into()), ptr));
567            }
568        }
569
570        let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl ||
571            kind == CXCursor_ObjCClassMethodDecl
572        {
573            ty.ret_type()
574                .or_else(|| cursor.ret_type())
575                .ok_or(ParseError::Continue)?
576        } else {
577            ty.ret_type().ok_or(ParseError::Continue)?
578        };
579
580        let ret = if is_constructor && ctx.is_target_wasm32() {
581            // Constructors in Clang wasm32 target return a pointer to the object
582            // being constructed.
583            let void = Item::builtin_type(TypeKind::Void, false, ctx);
584            Item::builtin_type(TypeKind::Pointer(void), false, ctx)
585        } else {
586            Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx)
587        };
588
589        // Clang plays with us at "find the calling convention", see #549 and
590        // co. This seems to be a better fix than that commit.
591        let mut call_conv = ty.call_conv();
592        if let Some(ty) = cursor.cur_type().canonical_type().pointee_type() {
593            let cursor_call_conv = ty.call_conv();
594            if cursor_call_conv != CXCallingConv_Invalid {
595                call_conv = cursor_call_conv;
596            }
597        }
598
599        let abi = get_abi(call_conv);
600
601        if abi.is_unknown() {
602            warn!("Unknown calling convention: {call_conv:?}");
603        }
604
605        Ok(Self {
606            name: spelling,
607            return_type: ret,
608            argument_types: args,
609            is_variadic: ty.is_variadic(),
610            is_divergent,
611            must_use,
612            abi,
613        })
614    }
615
616    /// Get this function signature's return type.
617    pub(crate) fn return_type(&self) -> TypeId {
618        self.return_type
619    }
620
621    /// Get this function signature's argument (name, type) pairs.
622    pub(crate) fn argument_types(&self) -> &[(Option<String>, TypeId)] {
623        &self.argument_types
624    }
625
626    /// Get this function signature's ABI.
627    pub(crate) fn abi(
628        &self,
629        ctx: &BindgenContext,
630        name: Option<&str>,
631    ) -> crate::codegen::error::Result<ClangAbi> {
632        // FIXME (pvdrz): Try to do this check lazily instead. Maybe store the ABI inside `ctx`
633        // instead?.
634        let abi = if let Some(name) = name {
635            if let Some((abi, _)) = ctx
636                .options()
637                .abi_overrides
638                .iter()
639                .find(|(_, regex_set)| regex_set.matches(name))
640            {
641                ClangAbi::Known(*abi)
642            } else {
643                self.abi
644            }
645        } else if let Some((abi, _)) = ctx
646            .options()
647            .abi_overrides
648            .iter()
649            .find(|(_, regex_set)| regex_set.matches(&self.name))
650        {
651            ClangAbi::Known(*abi)
652        } else {
653            self.abi
654        };
655
656        match abi {
657            ClangAbi::Known(Abi::ThisCall)
658                if !ctx.options().rust_features().thiscall_abi =>
659            {
660                Err(crate::codegen::error::Error::UnsupportedAbi("thiscall"))
661            }
662            ClangAbi::Known(Abi::Vectorcall)
663                if !ctx.options().rust_features().vectorcall_abi =>
664            {
665                Err(crate::codegen::error::Error::UnsupportedAbi("vectorcall"))
666            }
667            ClangAbi::Known(Abi::CUnwind)
668                if !ctx.options().rust_features().c_unwind_abi =>
669            {
670                Err(crate::codegen::error::Error::UnsupportedAbi("C-unwind"))
671            }
672            ClangAbi::Known(Abi::EfiApi)
673                if !ctx.options().rust_features().abi_efiapi =>
674            {
675                Err(crate::codegen::error::Error::UnsupportedAbi("efiapi"))
676            }
677            ClangAbi::Known(Abi::Win64) if self.is_variadic() => {
678                Err(crate::codegen::error::Error::UnsupportedAbi("Win64"))
679            }
680            abi => Ok(abi),
681        }
682    }
683
684    /// Is this function signature variadic?
685    pub(crate) fn is_variadic(&self) -> bool {
686        // Clang reports some functions as variadic when they *might* be
687        // variadic. We do the argument check because rust doesn't codegen well
688        // variadic functions without an initial argument.
689        self.is_variadic && !self.argument_types.is_empty()
690    }
691
692    /// Must this function's return value be used?
693    pub(crate) fn must_use(&self) -> bool {
694        self.must_use
695    }
696
697    /// Are function pointers with this signature able to derive Rust traits?
698    /// Rust only supports deriving traits for function pointers with a limited
699    /// number of parameters and a couple ABIs.
700    ///
701    /// For more details, see:
702    ///
703    /// * <https://github.com/rust-lang/rust-bindgen/issues/547>,
704    /// * <https://github.com/rust-lang/rust/issues/38848>,
705    /// * and <https://github.com/rust-lang/rust/issues/40158>
706    pub(crate) fn function_pointers_can_derive(&self) -> bool {
707        if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
708            return false;
709        }
710
711        matches!(self.abi, ClangAbi::Known(Abi::C) | ClangAbi::Unknown(..))
712    }
713
714    /// Whether this function has attributes marking it as divergent.
715    pub(crate) fn is_divergent(&self) -> bool {
716        self.is_divergent
717    }
718}
719
720impl ClangSubItemParser for Function {
721    fn parse(
722        cursor: clang::Cursor,
723        context: &mut BindgenContext,
724    ) -> Result<ParseResult<Self>, ParseError> {
725        use clang_sys::*;
726
727        let kind = match FunctionKind::from_cursor(&cursor) {
728            None => return Err(ParseError::Continue),
729            Some(k) => k,
730        };
731
732        debug!("Function::parse({cursor:?}, {:?})", cursor.cur_type());
733        let visibility = cursor.visibility();
734        if visibility != CXVisibility_Default {
735            return Err(ParseError::Continue);
736        }
737        if cursor.access_specifier() == CX_CXXPrivate &&
738            !context.options().generate_private_functions
739        {
740            return Err(ParseError::Continue);
741        }
742
743        let linkage = cursor.linkage();
744        let linkage = match linkage {
745            CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External,
746            CXLinkage_Internal => Linkage::Internal,
747            _ => return Err(ParseError::Continue),
748        };
749
750        if cursor.is_inlined_function() ||
751            cursor.definition().is_some_and(|x| x.is_inlined_function())
752        {
753            if !context.options().generate_inline_functions &&
754                !context.options().wrap_static_fns
755            {
756                return Err(ParseError::Continue);
757            }
758
759            if cursor.is_deleted_function() &&
760                !context.options().generate_deleted_functions
761            {
762                return Err(ParseError::Continue);
763            }
764
765            // We cannot handle `inline` functions that are not `static`.
766            if context.options().wrap_static_fns &&
767                cursor.is_inlined_function() &&
768                matches!(linkage, Linkage::External)
769            {
770                return Err(ParseError::Continue);
771            }
772        }
773
774        // Grab the signature using Item::from_ty.
775        let sig = Item::from_ty(&cursor.cur_type(), cursor, None, context)?;
776
777        let mut name = cursor.spelling();
778        assert!(!name.is_empty(), "Empty function name?");
779
780        if cursor.kind() == CXCursor_Destructor {
781            // Remove the leading `~`. The alternative to this is special-casing
782            // code-generation for destructor functions, which seems less than
783            // ideal.
784            if name.starts_with('~') {
785                name.remove(0);
786            }
787
788            // Add a suffix to avoid colliding with constructors. This would be
789            // technically fine (since we handle duplicated functions/methods),
790            // but seems easy enough to handle it here.
791            name.push_str("_destructor");
792        }
793        if let Some(nm) = context.options().last_callback(|callbacks| {
794            callbacks.generated_name_override(ItemInfo {
795                name: name.as_str(),
796                kind: ItemKind::Function,
797            })
798        }) {
799            name = nm;
800        }
801        assert!(!name.is_empty(), "Empty function name.");
802
803        let mangled_name = cursor_mangling(context, &cursor);
804
805        let link_name = context.options().last_callback(|callbacks| {
806            callbacks.generated_link_name_override(ItemInfo {
807                name: name.as_str(),
808                kind: ItemKind::Function,
809            })
810        });
811
812        let function = Self::new(
813            name.clone(),
814            mangled_name,
815            link_name,
816            sig,
817            kind,
818            linkage,
819        );
820
821        Ok(ParseResult::New(function, Some(cursor)))
822    }
823}
824
825impl Trace for FunctionSig {
826    type Extra = ();
827
828    fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
829    where
830        T: Tracer,
831    {
832        tracer.visit_kind(self.return_type().into(), EdgeKind::FunctionReturn);
833
834        for &(_, ty) in self.argument_types() {
835            tracer.visit_kind(ty.into(), EdgeKind::FunctionParameter);
836        }
837    }
838}