autocxx_bindgen/ir/
function.rs

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