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