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