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