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 ir::derive::{CanTriviallyDeriveDebug, CanTriviallyDeriveHash,
12                  CanTriviallyDerivePartialEqOrPartialOrd, CanDerive};
13 use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
14 use quote;
15 use quote::TokenStreamExt;
16 use proc_macro2;
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 => FunctionKind::Method(
36                 MethodKind::Constructor,
37             ),
38             clang_sys::CXCursor_Destructor => FunctionKind::Method(
39                 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 
144 impl DotAttributes for Function {
dot_attributes<W>( &self, _ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,145     fn dot_attributes<W>(
146         &self,
147         _ctx: &BindgenContext,
148         out: &mut W,
149     ) -> io::Result<()>
150     where
151         W: io::Write,
152     {
153         if let Some(ref mangled) = self.mangled_name {
154             let mangled: String =
155                 mangled.chars().flat_map(|c| c.escape_default()).collect();
156             writeln!(
157                 out,
158                 "<tr><td>mangled name</td><td>{}</td></tr>",
159                 mangled
160             )?;
161         }
162 
163         Ok(())
164     }
165 }
166 
167 /// An ABI extracted from a clang cursor.
168 #[derive(Debug, Copy, Clone)]
169 pub enum Abi {
170     /// The default C ABI.
171     C,
172     /// The "stdcall" ABI.
173     Stdcall,
174     /// The "fastcall" ABI.
175     Fastcall,
176     /// The "thiscall" ABI.
177     ThisCall,
178     /// The "aapcs" ABI.
179     Aapcs,
180     /// The "win64" ABI.
181     Win64,
182     /// An unknown or invalid ABI.
183     Unknown(CXCallingConv),
184 }
185 
186 impl Abi {
187     /// Returns whether this Abi is known or not.
is_unknown(&self) -> bool188     fn is_unknown(&self) -> bool {
189         match *self {
190             Abi::Unknown(..) => true,
191             _ => false,
192         }
193     }
194 }
195 
196 impl quote::ToTokens for Abi {
to_tokens(&self, tokens: &mut proc_macro2::TokenStream)197     fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
198         tokens.append_all(match *self {
199             Abi::C => quote! { "C" },
200             Abi::Stdcall => quote! { "stdcall" },
201             Abi::Fastcall => quote! { "fastcall" },
202             Abi::ThisCall => quote! { "thiscall" },
203             Abi::Aapcs => quote! { "aapcs" },
204             Abi::Win64 => quote! { "win64" },
205             Abi::Unknown(cc) => panic!(
206                 "Cannot turn unknown calling convention to tokens: {:?}",
207                 cc
208             ),
209         });
210     }
211 }
212 
213 /// A function signature.
214 #[derive(Debug)]
215 pub struct FunctionSig {
216     /// The return type of the function.
217     return_type: TypeId,
218 
219     /// The type of the arguments, optionally with the name of the argument when
220     /// declared.
221     argument_types: Vec<(Option<String>, TypeId)>,
222 
223     /// Whether this function is variadic.
224     is_variadic: bool,
225 
226     /// Whether this function's return value must be used.
227     must_use: bool,
228 
229     /// The ABI of this function.
230     abi: Abi,
231 }
232 
get_abi(cc: CXCallingConv) -> Abi233 fn get_abi(cc: CXCallingConv) -> Abi {
234     use clang_sys::*;
235     match cc {
236         CXCallingConv_Default => Abi::C,
237         CXCallingConv_C => Abi::C,
238         CXCallingConv_X86StdCall => Abi::Stdcall,
239         CXCallingConv_X86FastCall => Abi::Fastcall,
240         CXCallingConv_X86ThisCall => Abi::ThisCall,
241         CXCallingConv_AAPCS => Abi::Aapcs,
242         CXCallingConv_X86_64Win64 => Abi::Win64,
243         other => Abi::Unknown(other),
244     }
245 }
246 
247 /// Get the mangled name for the cursor's referent.
cursor_mangling( ctx: &BindgenContext, cursor: &clang::Cursor, ) -> Option<String>248 pub fn cursor_mangling(
249     ctx: &BindgenContext,
250     cursor: &clang::Cursor,
251 ) -> Option<String> {
252     use clang_sys;
253 
254     if !ctx.options().enable_mangling {
255         return None;
256     }
257 
258     // We early return here because libclang may crash in some case
259     // if we pass in a variable inside a partial specialized template.
260     // See rust-lang-nursery/rust-bindgen#67, and rust-lang-nursery/rust-bindgen#462.
261     if cursor.is_in_non_fully_specialized_template() {
262         return None;
263     }
264 
265     let is_destructor = cursor.kind() == clang_sys::CXCursor_Destructor;
266     if let Ok(mut manglings) = cursor.cxx_manglings() {
267         while let Some(m) = manglings.pop() {
268             // Only generate the destructor group 1, see below.
269             if is_destructor && !m.ends_with("D1Ev") {
270                 continue;
271             }
272 
273             return Some(m);
274         }
275     }
276 
277     let mut mangling = cursor.mangling();
278     if mangling.is_empty() {
279         return None;
280     }
281 
282     if is_destructor {
283         // With old (3.8-) libclang versions, and the Itanium ABI, clang returns
284         // the "destructor group 0" symbol, which means that it'll try to free
285         // memory, which definitely isn't what we want.
286         //
287         // Explicitly force the destructor group 1 symbol.
288         //
289         // See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special
290         // for the reference, and http://stackoverflow.com/a/6614369/1091587 for
291         // a more friendly explanation.
292         //
293         // We don't need to do this for constructors since clang seems to always
294         // have returned the C1 constructor.
295         //
296         // FIXME(emilio): Can a legit symbol in other ABIs end with this string?
297         // I don't think so, but if it can this would become a linker error
298         // anyway, not an invalid free at runtime.
299         //
300         // TODO(emilio, #611): Use cpp_demangle if this becomes nastier with
301         // time.
302         if mangling.ends_with("D0Ev") {
303             let new_len = mangling.len() - 4;
304             mangling.truncate(new_len);
305             mangling.push_str("D1Ev");
306         }
307     }
308 
309     Some(mangling)
310 }
311 
args_from_ty_and_cursor( ty: &clang::Type, cursor: &clang::Cursor, ctx: &mut BindgenContext, ) -> Vec<(Option<String>, TypeId)>312 fn args_from_ty_and_cursor(
313     ty: &clang::Type,
314     cursor: &clang::Cursor,
315     ctx: &mut BindgenContext,
316 ) -> Vec<(Option<String>, TypeId)> {
317     match (cursor.args(), ty.args()) {
318         (Some(cursor_args), Some(ty_args)) => {
319             ty_args.iter().enumerate().map(|(i, ty)| {
320                 let name = cursor_args.get(i)
321                     .map(|c| c.spelling())
322                     .and_then(|name| if name.is_empty() { None } else { Some(name) });
323                 (name, Item::from_ty_or_ref(*ty, *cursor, None, ctx))
324             }).collect()
325         }
326         (Some(cursor_args), None) => {
327             cursor_args.iter().map(|cursor| {
328                 let name = cursor.spelling();
329                 let name = if name.is_empty() { None } else { Some(name) };
330                 (name, Item::from_ty_or_ref(cursor.cur_type(), *cursor, None, ctx))
331             }).collect()
332         }
333         _ => panic!()
334     }
335 }
336 
337 impl FunctionSig {
338     /// Construct a new function signature.
new( return_type: TypeId, argument_types: Vec<(Option<String>, TypeId)>, is_variadic: bool, must_use: bool, abi: Abi, ) -> Self339     pub fn new(
340         return_type: TypeId,
341         argument_types: Vec<(Option<String>, TypeId)>,
342         is_variadic: bool,
343         must_use: bool,
344         abi: Abi,
345     ) -> Self {
346         FunctionSig {
347             return_type,
348             argument_types,
349             is_variadic,
350             must_use,
351             abi: abi,
352         }
353     }
354 
355     /// Construct a new function signature from the given Clang type.
from_ty( ty: &clang::Type, cursor: &clang::Cursor, ctx: &mut BindgenContext, ) -> Result<Self, ParseError>356     pub fn from_ty(
357         ty: &clang::Type,
358         cursor: &clang::Cursor,
359         ctx: &mut BindgenContext,
360     ) -> Result<Self, ParseError> {
361         use clang_sys::*;
362         debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
363 
364         // Skip function templates
365         let kind = cursor.kind();
366         if kind == CXCursor_FunctionTemplate {
367             return Err(ParseError::Continue);
368         }
369 
370         // Don't parse operatorxx functions in C++
371         let spelling = cursor.spelling();
372         if spelling.starts_with("operator") {
373             return Err(ParseError::Continue);
374         }
375 
376         // Constructors of non-type template parameter classes for some reason
377         // include the template parameter in their name. Just skip them, since
378         // we don't handle well non-type template parameters anyway.
379         if (kind == CXCursor_Constructor || kind == CXCursor_Destructor) &&
380             spelling.contains('<')
381         {
382             return Err(ParseError::Continue);
383         }
384 
385         let cursor = if cursor.is_valid() {
386             *cursor
387         } else {
388             ty.declaration()
389         };
390 
391         let mut args = match kind {
392             CXCursor_FunctionDecl |
393             CXCursor_Constructor |
394             CXCursor_CXXMethod |
395             CXCursor_ObjCInstanceMethodDecl |
396             CXCursor_ObjCClassMethodDecl => {
397                 args_from_ty_and_cursor(&ty, &cursor, ctx)
398             },
399             _ => {
400                 // For non-CXCursor_FunctionDecl, visiting the cursor's children
401                 // is the only reliable way to get parameter names.
402                 let mut args = vec![];
403                 cursor.visit(|c| {
404                     if c.kind() == CXCursor_ParmDecl {
405                         let ty =
406                             Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
407                         let name = c.spelling();
408                         let name =
409                             if name.is_empty() { None } else { Some(name) };
410                         args.push((name, ty));
411                     }
412                     CXChildVisit_Continue
413                 });
414                 args
415             }
416         };
417 
418         let must_use =
419             ctx.options().enable_function_attribute_detection &&
420             cursor.has_simple_attr("warn_unused_result");
421         let is_method = kind == CXCursor_CXXMethod;
422         let is_constructor = kind == CXCursor_Constructor;
423         let is_destructor = kind == CXCursor_Destructor;
424         if (is_constructor || is_destructor || is_method) &&
425             cursor.lexical_parent() != cursor.semantic_parent()
426         {
427             // Only parse constructors once.
428             return Err(ParseError::Continue);
429         }
430 
431         if is_method || is_constructor || is_destructor {
432             let is_const = is_method && cursor.method_is_const();
433             let is_virtual = is_method && cursor.method_is_virtual();
434             let is_static = is_method && cursor.method_is_static();
435             if !is_static && !is_virtual {
436                 let parent = cursor.semantic_parent();
437                 let class = Item::parse(parent, None, ctx)
438                     .expect("Expected to parse the class");
439                 // The `class` most likely is not finished parsing yet, so use
440                 // the unchecked variant.
441                 let class = class.as_type_id_unchecked();
442 
443                 let class = if is_const {
444                     let const_class_id = ctx.next_item_id();
445                     ctx.build_const_wrapper(
446                         const_class_id,
447                         class,
448                         None,
449                         &parent.cur_type(),
450                     )
451                 } else {
452                     class
453                 };
454 
455                 let ptr =
456                     Item::builtin_type(TypeKind::Pointer(class), false, ctx);
457                 args.insert(0, (Some("this".into()), ptr));
458             } else if is_virtual {
459                 let void = Item::builtin_type(TypeKind::Void, false, ctx);
460                 let ptr =
461                     Item::builtin_type(TypeKind::Pointer(void), false, ctx);
462                 args.insert(0, (Some("this".into()), ptr));
463             }
464         }
465 
466         let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl ||
467             kind == CXCursor_ObjCClassMethodDecl
468         {
469             ty.ret_type().or_else(|| cursor.ret_type()).ok_or(
470                 ParseError::Continue,
471             )?
472         } else {
473             ty.ret_type().ok_or(ParseError::Continue)?
474         };
475         let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
476 
477         // Clang plays with us at "find the calling convention", see #549 and
478         // co. This seems to be a better fix than that commit.
479         let mut call_conv = ty.call_conv();
480         if let Some(ty) = cursor.cur_type().canonical_type().pointee_type() {
481             let cursor_call_conv = ty.call_conv();
482             if cursor_call_conv != CXCallingConv_Invalid {
483                 call_conv = cursor_call_conv;
484             }
485         }
486         let abi = get_abi(call_conv);
487 
488         if abi.is_unknown() {
489             warn!("Unknown calling convention: {:?}", call_conv);
490         }
491 
492         Ok(Self::new(ret.into(), args, ty.is_variadic(), must_use, abi))
493     }
494 
495     /// Get this function signature's return type.
return_type(&self) -> TypeId496     pub fn return_type(&self) -> TypeId {
497         self.return_type
498     }
499 
500     /// Get this function signature's argument (name, type) pairs.
argument_types(&self) -> &[(Option<String>, TypeId)]501     pub fn argument_types(&self) -> &[(Option<String>, TypeId)] {
502         &self.argument_types
503     }
504 
505     /// Get this function signature's ABI.
abi(&self) -> Abi506     pub fn abi(&self) -> Abi {
507         self.abi
508     }
509 
510     /// Is this function signature variadic?
is_variadic(&self) -> bool511     pub fn is_variadic(&self) -> bool {
512         // Clang reports some functions as variadic when they *might* be
513         // variadic. We do the argument check because rust doesn't codegen well
514         // variadic functions without an initial argument.
515         self.is_variadic && !self.argument_types.is_empty()
516     }
517 
518     /// Must this function's return value be used?
must_use(&self) -> bool519     pub fn must_use(&self) -> bool {
520         self.must_use
521     }
522 
523     /// Are function pointers with this signature able to derive Rust traits?
524     /// Rust only supports deriving traits for function pointers with a limited
525     /// number of parameters and a couple ABIs.
526     ///
527     /// For more details, see:
528     ///
529     /// * https://github.com/rust-lang-nursery/rust-bindgen/issues/547,
530     /// * https://github.com/rust-lang/rust/issues/38848,
531     /// * and https://github.com/rust-lang/rust/issues/40158
function_pointers_can_derive(&self) -> bool532     pub fn function_pointers_can_derive(&self) -> bool {
533         if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
534             return false;
535         }
536 
537         match self.abi {
538             Abi::C | Abi::Unknown(..) => true,
539             _ => false,
540         }
541     }
542 }
543 
544 impl ClangSubItemParser for Function {
parse( cursor: clang::Cursor, context: &mut BindgenContext, ) -> Result<ParseResult<Self>, ParseError>545     fn parse(
546         cursor: clang::Cursor,
547         context: &mut BindgenContext,
548     ) -> Result<ParseResult<Self>, ParseError> {
549         use clang_sys::*;
550 
551         let kind = match FunctionKind::from_cursor(&cursor) {
552             None => return Err(ParseError::Continue),
553             Some(k) => k,
554         };
555 
556         debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
557 
558         let visibility = cursor.visibility();
559         if visibility != CXVisibility_Default {
560             return Err(ParseError::Continue);
561         }
562 
563         if cursor.access_specifier() == CX_CXXPrivate {
564             return Err(ParseError::Continue);
565         }
566 
567         if !context.options().generate_inline_functions &&
568             cursor.is_inlined_function()
569         {
570             return Err(ParseError::Continue);
571         }
572 
573         let linkage = cursor.linkage();
574         let linkage = match linkage {
575             CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External,
576             CXLinkage_Internal => Linkage::Internal,
577             _ => return Err(ParseError::Continue)
578         };
579 
580         // Grab the signature using Item::from_ty.
581         let sig =
582             Item::from_ty(&cursor.cur_type(), cursor, None, context)?;
583 
584         let mut name = cursor.spelling();
585         assert!(!name.is_empty(), "Empty function name?");
586 
587         if cursor.kind() == CXCursor_Destructor {
588             // Remove the leading `~`. The alternative to this is special-casing
589             // code-generation for destructor functions, which seems less than
590             // ideal.
591             if name.starts_with('~') {
592                 name.remove(0);
593             }
594 
595             // Add a suffix to avoid colliding with constructors. This would be
596             // technically fine (since we handle duplicated functions/methods),
597             // but seems easy enough to handle it here.
598             name.push_str("_destructor");
599         }
600 
601         let mangled_name = cursor_mangling(context, &cursor);
602         let comment = cursor.raw_comment();
603 
604         let function = Self::new(name, mangled_name, sig, comment, kind, linkage);
605         Ok(ParseResult::New(function, Some(cursor)))
606     }
607 }
608 
609 impl Trace for FunctionSig {
610     type Extra = ();
611 
trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &()) where T: Tracer,612     fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
613     where
614         T: Tracer,
615     {
616         tracer.visit_kind(self.return_type().into(), EdgeKind::FunctionReturn);
617 
618         for &(_, ty) in self.argument_types() {
619             tracer.visit_kind(ty.into(), EdgeKind::FunctionParameter);
620         }
621     }
622 }
623 
624 impl CanTriviallyDeriveDebug for FunctionSig {
can_trivially_derive_debug(&self, _: &BindgenContext) -> bool625     fn can_trivially_derive_debug(&self, _: &BindgenContext) -> bool {
626         self.function_pointers_can_derive()
627     }
628 }
629 
630 impl CanTriviallyDeriveHash for FunctionSig {
can_trivially_derive_hash(&self, _: &BindgenContext) -> bool631     fn can_trivially_derive_hash(&self, _: &BindgenContext) -> bool {
632         self.function_pointers_can_derive()
633     }
634 }
635 
636 impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig {
can_trivially_derive_partialeq_or_partialord(&self, _: &BindgenContext) -> CanDerive637     fn can_trivially_derive_partialeq_or_partialord(&self, _: &BindgenContext) -> CanDerive {
638         if self.function_pointers_can_derive() {
639             CanDerive::Yes
640         } else {
641             CanDerive::No
642         }
643     }
644 }
645