summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs4
-rw-r--r--src/ir/context.rs87
-rw-r--r--src/lib.rs15
-rw-r--r--src/options.rs7
-rw-r--r--tests/expectations/tests/do-not-derive-copy.rs28
-rw-r--r--tests/headers/do-not-derive-copy.hpp5
6 files changed, 108 insertions, 38 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index f47787af..4697ba21 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1493,7 +1493,9 @@ impl CodeGenerator for CompInfo {
needs_default_impl = ctx.options().derive_default;
}
- if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
+ if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() &&
+ ctx.options().derive_copy
+ {
derives.push("Copy");
if used_template_params.is_some() {
// FIXME: This requires extra logic if you have a big array in a
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 3bb8b5d9..cfbb3766 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -321,55 +321,69 @@ where
}
}
+/// Returns the effective target, and whether it was explicitly specified on the
+/// clang flags.
+fn find_effective_target(clang_args: &[String]) -> (String, bool) {
+ use std::env;
+
+ for opt in clang_args {
+ if opt.starts_with("--target=") {
+ let mut split = opt.split('=');
+ split.next();
+ return (split.next().unwrap().to_owned(), true);
+ }
+ }
+
+ // If we're running from a build script, try to find the cargo target.
+ if let Ok(t) = env::var("TARGET") {
+ return (t, false)
+ }
+
+ const HOST_TARGET: &'static str =
+ include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
+ (HOST_TARGET.to_owned(), false)
+}
+
impl<'ctx> BindgenContext<'ctx> {
/// Construct the context for the given `options`.
pub fn new(options: BindgenOptions) -> Self {
use clang_sys;
+ // TODO(emilio): Use the CXTargetInfo here when available.
+ //
+ // see: https://reviews.llvm.org/D32389
+ let (effective_target, explicit_target) =
+ find_effective_target(&options.clang_args);
+
let index = clang::Index::new(false, true);
let parse_options =
clang_sys::CXTranslationUnit_DetailedPreprocessingRecord;
- let translation_unit = clang::TranslationUnit::parse(
- &index,
- "",
- &options.clang_args,
- &options.input_unsaved_files,
- parse_options,
- ).expect("TranslationUnit::parse failed");
- // TODO(emilio): Use the CXTargetInfo here when available.
- //
- // see: https://reviews.llvm.org/D32389
- let mut effective_target = None;
- for opt in &options.clang_args {
- if opt.starts_with("--target=") {
- let mut split = opt.split('=');
- split.next();
- effective_target = Some(split.next().unwrap().to_owned());
- break;
- }
- }
-
- if effective_target.is_none() {
- use std::env;
- // If we're running from a build script, try to find the cargo
- // target.
- effective_target = env::var("TARGET").ok();
- }
+ let translation_unit = {
+ let clang_args = if explicit_target {
+ Cow::Borrowed(&options.clang_args)
+ } else {
+ let mut args = Vec::with_capacity(options.clang_args.len() + 1);
+ args.push(format!("--target={}", effective_target));
+ args.extend_from_slice(&options.clang_args);
+ Cow::Owned(args)
+ };
- if effective_target.is_none() {
- const HOST_TARGET: &'static str =
- include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
- effective_target = Some(HOST_TARGET.to_owned());
- }
+ clang::TranslationUnit::parse(
+ &index,
+ "",
+ &clang_args,
+ &options.input_unsaved_files,
+ parse_options,
+ ).expect("TranslationUnit::parse failed")
+ };
- // Mac os, iOS and Win32 need __ for mangled symbols but rust will automatically
- // prepend the extra _.
+ // Mac os, iOS and Win32 need __ for mangled symbols but rust will
+ // automatically prepend the extra _.
//
- // We need to make sure that we don't include __ because rust will turn into
- // ___.
- let effective_target = effective_target.unwrap();
+ // We need to make sure that we don't include __ because rust will turn
+ // into ___.
let needs_mangling_hack = effective_target.contains("darwin") ||
effective_target.contains("ios") ||
effective_target == "i686-pc-win32";
@@ -882,7 +896,6 @@ impl<'ctx> BindgenContext<'ctx> {
use syntax::codemap::{ExpnInfo, MacroBang, NameAndSpan};
use syntax::ext::base;
use syntax::parse;
- use std::mem;
let cfg = ExpansionConfig::default("xxx".to_owned());
let sess = parse::ParseSess::new();
diff --git a/src/lib.rs b/src/lib.rs
index af50f0e9..91b7d8d4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -253,6 +253,10 @@ impl Builder {
output_vector.push("--no-layout-tests".into());
}
+ if !self.options.derive_copy {
+ output_vector.push("--no-derive-copy".into());
+ }
+
if !self.options.derive_debug {
output_vector.push("--no-derive-debug".into());
}
@@ -735,6 +739,12 @@ impl Builder {
self
}
+ /// Set whether `Copy` should be derived by default.
+ pub fn derive_copy(mut self, doit: bool) -> Self {
+ self.options.derive_copy = doit;
+ self
+ }
+
/// Set whether `Debug` should be derived by default.
pub fn derive_debug(mut self, doit: bool) -> Self {
self.options.derive_debug = doit;
@@ -1104,6 +1114,10 @@ pub struct BindgenOptions {
/// True if we should generate layout tests for generated structures.
pub layout_tests: bool,
+ /// True if we should derive Copy trait implementations for C/C++ structures
+ /// and types.
+ pub derive_copy: bool,
+
/// True if we should derive Debug trait implementations for C/C++ structures
/// and types.
pub derive_debug: bool,
@@ -1269,6 +1283,7 @@ impl Default for BindgenOptions {
emit_ir: false,
emit_ir_graphviz: None,
layout_tests: true,
+ derive_copy: true,
derive_debug: true,
impl_debug: false,
derive_default: false,
diff --git a/src/options.rs b/src/options.rs
index c6f5c010..aaf31953 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -61,6 +61,9 @@ where
Arg::with_name("no-layout-tests")
.long("no-layout-tests")
.help("Avoid generating layout tests for any type."),
+ Arg::with_name("no-derive-copy")
+ .long("no-derive-copy")
+ .help("Avoid deriving Copy on any type."),
Arg::with_name("no-derive-debug")
.long("no-derive-debug")
.help("Avoid deriving Debug on any type."),
@@ -311,6 +314,10 @@ where
builder = builder.layout_tests(false);
}
+ if matches.is_present("no-derive-copy") {
+ builder = builder.derive_copy(false);
+ }
+
if matches.is_present("no-derive-debug") {
builder = builder.derive_debug(false);
}
diff --git a/tests/expectations/tests/do-not-derive-copy.rs b/tests/expectations/tests/do-not-derive-copy.rs
new file mode 100644
index 00000000..114b73e3
--- /dev/null
+++ b/tests/expectations/tests/do-not-derive-copy.rs
@@ -0,0 +1,28 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct WouldBeCopyButWeAreNotDerivingCopy {
+ pub x: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_WouldBeCopyButWeAreNotDerivingCopy() {
+ assert_eq!(::std::mem::size_of::<WouldBeCopyButWeAreNotDerivingCopy>() ,
+ 4usize , concat ! (
+ "Size of: " , stringify ! ( WouldBeCopyButWeAreNotDerivingCopy
+ ) ));
+ assert_eq! (::std::mem::align_of::<WouldBeCopyButWeAreNotDerivingCopy>() ,
+ 4usize , concat ! (
+ "Alignment of " , stringify ! (
+ WouldBeCopyButWeAreNotDerivingCopy ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const WouldBeCopyButWeAreNotDerivingCopy ) ) .
+ x as * const _ as usize } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! (
+ WouldBeCopyButWeAreNotDerivingCopy ) , "::" , stringify ! ( x
+ ) ));
+}
diff --git a/tests/headers/do-not-derive-copy.hpp b/tests/headers/do-not-derive-copy.hpp
new file mode 100644
index 00000000..18c26135
--- /dev/null
+++ b/tests/headers/do-not-derive-copy.hpp
@@ -0,0 +1,5 @@
+// bindgen-flags: --no-derive-copy
+
+class WouldBeCopyButWeAreNotDerivingCopy {
+ int x;
+};