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