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