blob: 54f5a9fbcd7477a6aa482a99556e126557ce33f6 [file] [log] [blame]
Alex Crichton8e5f0cd2015-09-09 22:46:19 -07001extern crate gcc;
2extern crate syntex_syntax as syntax;
3
Alex Crichton310d6232015-09-10 10:56:31 -07004use std::collections::HashSet;
Alex Crichton8e5f0cd2015-09-09 22:46:19 -07005use std::env;
6use std::fs::File;
7use std::io::BufWriter;
8use std::io::prelude::*;
9use std::path::{Path, PathBuf};
10
11use syntax::ast;
Alex Crichtona9adfbf2015-09-09 23:21:27 -070012use syntax::diagnostic::SpanHandler;
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070013use syntax::parse::token::InternedString;
Alex Crichtona9adfbf2015-09-09 23:21:27 -070014use syntax::attr::{self, ReprAttr};
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070015use syntax::parse::{self, ParseSess};
16use syntax::visit::{self, Visitor};
17
Alex Crichton310d6232015-09-10 10:56:31 -070018macro_rules! t {
19 ($e:expr) => (match $e {
20 Ok(e) => e,
21 Err(e) => panic!("{} failed with {}", stringify!($e), e),
22 })
23}
24
Alex Crichtona9adfbf2015-09-09 23:21:27 -070025struct TestGenerator<'a> {
Alex Crichton310d6232015-09-10 10:56:31 -070026 target: String,
Alex Crichton8e5f0cd2015-09-09 22:46:19 -070027 rust: Box<Write>,
28 c: Box<Write>,
Alex Crichtona9adfbf2015-09-09 23:21:27 -070029 sh: &'a SpanHandler,
Alex Crichton310d6232015-09-10 10:56:31 -070030 structs: HashSet<String>,
31}
32
33struct StructFinder {
34 structs: HashSet<String>,
35}
36
37impl<'a> TestGenerator<'a> {
Alex Crichton0df7c102015-09-10 16:35:37 -070038 fn defines(&self) -> Vec<&'static str> {
39 let mut ret = Vec::new();
40 if self.target.contains("unknown-linux") {
41 ret.push("_GNU_SOURCE");
42 }
Alex Crichtonac2bd852015-09-10 17:21:20 -070043 if self.target.contains("msvc") {
44 ret.push("alignof __alignof");
45 }
Alex Crichton0df7c102015-09-10 16:35:37 -070046 return ret
47 }
48
Alex Crichton310d6232015-09-10 10:56:31 -070049 fn headers(&self) -> Vec<&'static str> {
Alex Crichtonac2bd852015-09-10 17:21:20 -070050 let mut base = Vec::new();
51
Alex Crichtonac2bd852015-09-10 17:21:20 -070052 base.extend(&[
Alex Crichton0df7c102015-09-10 16:35:37 -070053 "errno.h",
54 "fcntl.h",
Alex Crichton0df7c102015-09-10 16:35:37 -070055 "limits.h",
Alex Crichton310d6232015-09-10 10:56:31 -070056 "stddef.h",
57 "stdint.h",
Alex Crichton0df7c102015-09-10 16:35:37 -070058 "stdio.h",
59 "stdlib.h",
Alex Crichton310d6232015-09-10 10:56:31 -070060 "sys/stat.h",
Alex Crichton310d6232015-09-10 10:56:31 -070061 "sys/types.h",
Alex Crichton310d6232015-09-10 10:56:31 -070062 "time.h",
Alex Crichton310d6232015-09-10 10:56:31 -070063 "wchar.h",
Alex Crichtonac2bd852015-09-10 17:21:20 -070064 ]);
Alex Crichton310d6232015-09-10 10:56:31 -070065
66 if self.target.contains("apple-darwin") {
Alex Crichtone8606192015-09-10 20:19:44 -070067 base.push("mach-o/dyld.h");
Alex Crichton310d6232015-09-10 10:56:31 -070068 base.push("mach/mach_time.h");
69 }
Alex Crichtonac2bd852015-09-10 17:21:20 -070070
Alex Crichton310d6232015-09-10 10:56:31 -070071 if self.target.contains("unknown-linux") {
72 base.push("linux/if_packet.h");
73 base.push("net/ethernet.h");
74 }
75
Alex Crichtonac2bd852015-09-10 17:21:20 -070076 if self.target.contains("windows") {
Alex Crichton13a6f2d2015-09-10 18:10:58 -070077 base.push("winsock2.h");
78 base.push("ws2ipdef.h");
79 base.push("windows.h");
80 base.push("sys/utime.h");
Alex Crichtonac2bd852015-09-10 17:21:20 -070081 } else {
Alex Crichton22378822015-09-10 19:59:23 -070082 base.push("ctype.h");
83 base.push("dirent.h");
Alex Crichtonac2bd852015-09-10 17:21:20 -070084 base.push("glob.h");
85 base.push("ifaddrs.h");
86 base.push("net/if.h");
87 base.push("netdb.h");
88 base.push("netinet/in.h");
89 base.push("netinet/ip.h");
90 base.push("netinet/tcp.h");
91 base.push("pthread.h");
92 base.push("signal.h");
93 base.push("stdalign.h");
Alex Crichtone8606192015-09-10 20:19:44 -070094 base.push("string.h");
Alex Crichton22378822015-09-10 19:59:23 -070095 base.push("sys/file.h");
96 base.push("sys/ioctl.h");
Alex Crichtonac2bd852015-09-10 17:21:20 -070097 base.push("sys/mman.h");
98 base.push("sys/resource.h");
99 base.push("sys/socket.h");
Alex Crichtone8606192015-09-10 20:19:44 -0700100 base.push("sys/sysctl.h");
Alex Crichtonac2bd852015-09-10 17:21:20 -0700101 base.push("sys/time.h");
102 base.push("sys/un.h");
Alex Crichton22378822015-09-10 19:59:23 -0700103 base.push("sys/wait.h");
Alex Crichtonac2bd852015-09-10 17:21:20 -0700104 base.push("unistd.h");
Alex Crichton22378822015-09-10 19:59:23 -0700105 base.push("utime.h");
Alex Crichtonac2bd852015-09-10 17:21:20 -0700106 }
107
Alex Crichton310d6232015-09-10 10:56:31 -0700108 return base
109 }
110
111 fn rust2c(&self, ty: &str) -> String {
Alex Crichton13a6f2d2015-09-10 18:10:58 -0700112 let windows = self.target.contains("windows");
Alex Crichton310d6232015-09-10 10:56:31 -0700113 match ty {
114 t if t.starts_with("c_") => {
115 match &ty[2..].replace("long", " long")[..] {
116 s if s.starts_with("u") => format!("unsigned {}", &s[1..]),
117 "short" => format!("short"),
118 s if s.starts_with("s") => format!("signed {}", &s[1..]),
119 s => s.to_string(),
120 }
121 }
122 "ip6_mreq" => "struct ipv6_mreq".to_string(),
Alex Crichton22378822015-09-10 19:59:23 -0700123 "glob_t" |
124 "FILE" |
125 "DIR" |
126 "fpos_t" => ty.to_string(),
Alex Crichton310d6232015-09-10 10:56:31 -0700127 t if t.starts_with("pthread") => t.to_string(),
128
Alex Crichton13a6f2d2015-09-10 18:10:58 -0700129 t if self.structs.contains(t) => {
130 if windows && ty.chars().next().unwrap().is_uppercase() {
131 t.to_string()
132 } else if windows && t == "stat" {
133 "struct __stat64".to_string()
134 } else {
135 format!("struct {}", t)
136 }
137 }
Alex Crichton310d6232015-09-10 10:56:31 -0700138
Alex Crichton13a6f2d2015-09-10 18:10:58 -0700139 "time64_t" if windows => "__time64_t".to_string(),
140 "ssize_t" if windows => "SSIZE_T".to_string(),
Alex Crichton310d6232015-09-10 10:56:31 -0700141 t => t.to_string(),
142 }
143 }
144
145 fn rust2cfield(&self, struct_: &str, field: &str) -> String {
146 match field {
147 s if s.ends_with("_nsec") && struct_ == "stat" => {
148 if self.target.contains("apple-darwin") {
149 s.replace("_nsec", "spec.tv_nsec")
150 } else {
151 s.replace("e_nsec", ".tv_nsec")
152 }
153 }
154 s => s.to_string(),
155 }
156 }
157
158 fn cfg_list(&self) -> Vec<(&'static str, Option<&'static str>)> {
159 let mut ret = Vec::new();
160 let (arch, target_pointer_width) = if self.target.starts_with("x86_64") {
161 ("x86_64", "64")
162 } else if self.target.starts_with("i686") {
163 ("x86", "32")
164 } else {
165 panic!("unknown arch/pointer width: {}", self.target)
166 };
167 let (os, family, env) = if self.target.contains("unknown-linux") {
168 ("linux", "unix", "gnu")
169 } else if self.target.contains("apple-darwin") {
170 ("macos", "unix", "")
Alex Crichtonac2bd852015-09-10 17:21:20 -0700171 } else if self.target.contains("windows-msvc") {
172 ("windows", "windows", "msvc")
173 } else if self.target.contains("windows-gnu") {
174 ("windows", "windows", "gnu")
Alex Crichton310d6232015-09-10 10:56:31 -0700175 } else {
176 panic!("unknown os/family width: {}", self.target)
177 };
178
179 ret.push((family, None));
180 ret.push(("target_os", Some(os)));
181 ret.push(("target_family", Some(family)));
182 ret.push(("target_arch", Some(arch)));
183 // skip endianness
184 ret.push(("target_pointer_width", Some(target_pointer_width)));
185 ret.push(("target_env", Some(env)));
186
187 return ret
188 }
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700189}
190
191fn main() {
Alex Crichton310d6232015-09-10 10:56:31 -0700192 // Prep the test generator
193 let target = t!(env::var("TARGET"));
194 let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
195 let rust_out = BufWriter::new(t!(File::create(out.join("all.rs"))));
196 let c_out = BufWriter::new(t!(File::create(out.join("all.c"))));
Alex Crichton16083062015-09-09 22:59:24 -0700197 let sess = ParseSess::new();
Alex Crichton310d6232015-09-10 10:56:31 -0700198 let mut tg = TestGenerator {
199 target: target,
200 rust: Box::new(rust_out),
201 c: Box::new(c_out),
202 sh: &sess.span_diagnostic,
203 structs: HashSet::new(),
204 };
205
206 // Parse the libc crate
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700207 let src = Path::new("../src/lib.rs");
208 let cfg = Vec::new();
209 let mut krate = parse::parse_crate_from_file(src, cfg, &sess);
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700210
Alex Crichton310d6232015-09-10 10:56:31 -0700211 // Strip the crate down to just what's configured for our target
212 for (k, v) in tg.cfg_list() {
213 let s = InternedString::new;
214 krate.config.push(match v {
215 Some(v) => attr::mk_name_value_item_str(s(k), s(v)),
216 None => attr::mk_word_item(s(k)),
217 });
218 }
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700219 let mut gated_cfgs = Vec::new();
220 let krate = syntax::config::strip_unconfigured_items(&sess.span_diagnostic,
221 krate,
222 &mut gated_cfgs);
223
Alex Crichton310d6232015-09-10 10:56:31 -0700224 // Probe the crate to find all structs (used to convert type names to names
225 // in C).
226 let mut structs = StructFinder {
227 structs: HashSet::new(),
228 };
229 visit::walk_crate(&mut structs, &krate);
230 tg.structs = structs.structs;
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700231
Alex Crichton0df7c102015-09-10 16:35:37 -0700232 // Prep the C file by emitting header stuff
233 for define in tg.defines() {
234 t!(writeln!(tg.c, "#define {}", define));
235 }
Alex Crichton310d6232015-09-10 10:56:31 -0700236 for header in tg.headers() {
237 t!(writeln!(tg.c, "#include <{}>", header));
Alex Crichton16083062015-09-09 22:59:24 -0700238 }
Alex Crichton0df7c102015-09-10 16:35:37 -0700239
240 // Walk the crate, emitting test cases for everything found
Alex Crichton310d6232015-09-10 10:56:31 -0700241 visit::walk_crate(&mut tg, &krate);
Alex Crichton16083062015-09-09 22:59:24 -0700242
Alex Crichton310d6232015-09-10 10:56:31 -0700243 // Compile our C shim to be linked into tests
Alex Crichtonac2bd852015-09-10 17:21:20 -0700244 let mut cfg = gcc::Config::new();
245 cfg.file(out.join("all.c"));
246
247 if tg.target.contains("msvc") {
Alex Crichton13a6f2d2015-09-10 18:10:58 -0700248 cfg.flag("/W3").flag("/Wall").flag("/WX")
249 .flag("/wd4820") // weird warning about adding padding?
250 .flag("/wd4100"); // don't warn about unused parameters
Alex Crichtonac2bd852015-09-10 17:21:20 -0700251 } else {
Alex Crichtonb01a8cc2015-09-10 17:37:22 -0700252 cfg.flag("-Wall").flag("-Wextra").flag("-Werror")
Alex Crichton5f624a52015-09-10 17:39:21 -0700253 .flag("-Wno-unused-parameter");
Alex Crichtonac2bd852015-09-10 17:21:20 -0700254 }
255
256 drop(tg);
257 cfg.compile("liball.a");
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700258}
259
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700260impl<'a> TestGenerator<'a> {
261 fn test_type(&mut self, ty: &str) {
Alex Crichton310d6232015-09-10 10:56:31 -0700262 match ty {
263 "sighandler_t" => return,
264 _ => {}
265 }
Alex Crichton22378822015-09-10 19:59:23 -0700266 let c = self.rust_ty_to_c_ty(ty);
Alex Crichton310d6232015-09-10 10:56:31 -0700267 self.test_size_align(ty, &c);
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700268 }
Alex Crichton16083062015-09-09 22:59:24 -0700269
Alex Crichton3e5155b2015-09-09 23:46:19 -0700270 fn test_struct(&mut self, ty: &str, s: &ast::StructDef) {
Alex Crichton22378822015-09-10 19:59:23 -0700271 let cty = self.rust_ty_to_c_ty(ty);
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700272 self.test_size_align(ty, &cty);
Alex Crichton3e5155b2015-09-09 23:46:19 -0700273
Alex Crichton310d6232015-09-10 10:56:31 -0700274 t!(writeln!(self.rust, r#"
Alex Crichton3e5155b2015-09-09 23:46:19 -0700275 #[test]
276 fn field_offset_size_{ty}() {{
Alex Crichton310d6232015-09-10 10:56:31 -0700277 "#, ty = ty));
Alex Crichton3e5155b2015-09-09 23:46:19 -0700278 for field in s.fields.iter() {
279 let name = match field.node.kind {
280 ast::NamedField(name, ast::Public) => name,
281 ast::NamedField(_, ast::Inherited) => continue,
282 ast::UnnamedField(..) => panic!("no tuple structs in FFI"),
283 };
284
Alex Crichton310d6232015-09-10 10:56:31 -0700285 let cfield = self.rust2cfield(ty, &name.to_string());
Alex Crichton3e5155b2015-09-09 23:46:19 -0700286
Alex Crichton310d6232015-09-10 10:56:31 -0700287 t!(writeln!(self.c, r#"
Alex Crichton671376b2015-09-10 17:39:03 -0700288 uint64_t __test_offset_{ty}_{rust_field}(void) {{
Alex Crichton3e5155b2015-09-09 23:46:19 -0700289 return offsetof({cty}, {c_field});
290 }}
Alex Crichton671376b2015-09-10 17:39:03 -0700291 uint64_t __test_size_{ty}_{rust_field}(void) {{
Alex Crichton3e5155b2015-09-09 23:46:19 -0700292 {cty}* foo = NULL;
293 return sizeof(foo->{c_field});
294 }}
Alex Crichton310d6232015-09-10 10:56:31 -0700295 "#, ty = ty, cty = cty, rust_field = name, c_field = cfield));
296 t!(writeln!(self.rust, r#"
Alex Crichton3e5155b2015-09-09 23:46:19 -0700297 extern {{
298 fn __test_offset_{ty}_{field}() -> u64;
299 fn __test_size_{ty}_{field}() -> u64;
300 }}
301 unsafe {{
302 let foo = 0 as *const {ty};
303 same(offset_of!({ty}, {field}),
304 __test_offset_{ty}_{field}(),
305 "field offset {field} of {ty}");
306 same(mem::size_of_val(&(*foo).{field}) as u64,
307 __test_size_{ty}_{field}(),
308 "field size {field} of {ty}");
309 }}
Alex Crichton310d6232015-09-10 10:56:31 -0700310 "#, ty = ty, field = name));
Alex Crichton3e5155b2015-09-09 23:46:19 -0700311 }
Alex Crichton310d6232015-09-10 10:56:31 -0700312 t!(writeln!(self.rust, r#"
Alex Crichton3e5155b2015-09-09 23:46:19 -0700313 }}
Alex Crichton310d6232015-09-10 10:56:31 -0700314 "#));
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700315 }
316
317 fn test_size_align(&mut self, rust: &str, c: &str) {
Alex Crichton310d6232015-09-10 10:56:31 -0700318 t!(writeln!(self.c, r#"
Alex Crichton671376b2015-09-10 17:39:03 -0700319 uint64_t __test_size_{ty}(void) {{ return sizeof({cty}); }}
320 uint64_t __test_align_{ty}(void) {{ return alignof({cty}); }}
Alex Crichton310d6232015-09-10 10:56:31 -0700321 "#, ty = rust, cty = c));
322 t!(writeln!(self.rust, r#"
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700323 #[test]
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700324 fn size_align_{ty}() {{
Alex Crichton16083062015-09-09 22:59:24 -0700325 extern {{
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700326 fn __test_size_{ty}() -> u64;
327 fn __test_align_{ty}() -> u64;
Alex Crichton16083062015-09-09 22:59:24 -0700328 }}
329 unsafe {{
Alex Crichton3e5155b2015-09-09 23:46:19 -0700330 same(mem::size_of::<{ty}>() as u64,
331 __test_size_{ty}(), "size");
Alex Crichtonc8b895c2015-09-10 13:24:15 -0700332 same(align::<{ty}>() as u64,
Alex Crichton3e5155b2015-09-09 23:46:19 -0700333 __test_align_{ty}(), "align");
Alex Crichton16083062015-09-09 22:59:24 -0700334 }}
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700335 }}
Alex Crichton310d6232015-09-10 10:56:31 -0700336 "#, ty = rust));
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700337 }
338
Alex Crichton22378822015-09-10 19:59:23 -0700339 fn rust_ty_to_c_ty(&self, mut rust_ty: &str) -> String {
340 let mut cty = self.rust2c(&rust_ty.replace("*mut ", "")
341 .replace("*const ", ""));
342 while rust_ty.starts_with("*") {
343 if rust_ty.starts_with("*const") {
344 cty = format!("const {}*", cty);
345 rust_ty = &rust_ty[7..];
346 } else {
347 cty = format!("{}*", cty);
348 rust_ty = &rust_ty[5..];
349 }
350 }
351 return cty
352 }
353
Alex Crichton0df7c102015-09-10 16:35:37 -0700354 fn test_const(&mut self, name: &str, rust_ty: &str) {
Alex Crichton22378822015-09-10 19:59:23 -0700355 let cty = self.rust_ty_to_c_ty(rust_ty);
Alex Crichton0df7c102015-09-10 16:35:37 -0700356 let cast = if name == "SIG_IGN" {"(size_t)"} else {""};
357 t!(writeln!(self.c, r#"
Alex Crichton13a6f2d2015-09-10 18:10:58 -0700358 int __test_const_{name}({cty} *outptr) {{
359 *outptr = {cast}({name});
360 return 1;
Alex Crichtone7afdd82015-09-10 17:15:20 -0700361 }}
Alex Crichton0df7c102015-09-10 16:35:37 -0700362 "#, name = name, cast = cast, cty = cty));
363 t!(writeln!(self.rust, r#"
364 #[test]
365 fn const_{name}() {{
366 extern {{
Alex Crichtone7afdd82015-09-10 17:15:20 -0700367 fn __test_const_{name}(out: *mut {ty}) -> c_int;
Alex Crichton0df7c102015-09-10 16:35:37 -0700368 }}
369 unsafe {{
Alex Crichtone7afdd82015-09-10 17:15:20 -0700370 let mut o = mem::zeroed();
371 if __test_const_{name}(&mut o) == 0 {{
372 panic!("not defined");
373 }} else {{
374 same({name}, o, "value");
375 }}
Alex Crichton0df7c102015-09-10 16:35:37 -0700376 }}
377 }}
378 "#, ty = rust_ty, name = name));
379 }
380
Alex Crichton22378822015-09-10 19:59:23 -0700381 fn test_extern_fn(&mut self, name: &str, args: &[String], ret: &str,
382 variadic: bool) {
383 match name {
384 // manually verified
385 "execv" |
386 "execve" |
387 "execvp" |
388 "glob" |
389 "getrlimit" |
390 "setrlimit" |
Alex Crichtone8606192015-09-10 20:19:44 -0700391 "signal" |
Alex Crichton22378822015-09-10 19:59:23 -0700392 "getopt" => return,
393 _ => {}
394 }
395 let args = if args.len() == 0 && !variadic {
396 "void".to_string()
397 } else {
398 args.iter().map(|a| self.rust_ty_to_c_ty(a)).collect::<Vec<_>>()
399 .connect(", ") + if variadic {", ..."} else {""}
400 };
401 let cret = self.rust_ty_to_c_ty(ret);
402 t!(writeln!(self.c, r#"
403 {ret} (*__test_fn_{name}(void))({args}) {{
404 return {name};
405 }}
406 "#, name = name, args = args, ret = cret));
407 t!(writeln!(self.rust, r#"
408 #[test]
409 fn fn_{name}() {{
410 extern {{
411 fn __test_fn_{name}() -> size_t;
412 }}
413 unsafe {{
414 same({name} as usize,
415 __test_fn_{name}() as usize, "function pointer");
416 }}
417 }}
418 "#, name = name));
419 }
420
421 fn assert_no_generics(&self, _i: ast::Ident, generics: &ast::Generics) {
422 assert!(generics.lifetimes.len() == 0);
423 assert!(generics.ty_params.len() == 0);
424 assert!(generics.where_clause.predicates.len() == 0);
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700425 }
Alex Crichton0df7c102015-09-10 16:35:37 -0700426
427 fn ty2name(&self, ty: &ast::Ty) -> String {
428 match ty.node {
429 ast::TyPath(_, ref path) => {
430 path.segments.last().unwrap().identifier.to_string()
431 }
432 ast::TyPtr(ref t) => {
433 format!("*{} {}", match t.mutbl {
434 ast::MutImmutable => "const",
435 ast::MutMutable => "mut",
436 }, self.ty2name(&t.ty))
437 }
Alex Crichton22378822015-09-10 19:59:23 -0700438 ast::TyBareFn(ref t) => {
439 assert!(t.lifetimes.len() == 0);
440 let (ret, mut args, variadic) = self.decl2rust(&t.decl);
441 assert!(!variadic);
442 if args.len() == 0 {
443 args.push("void".to_string());
444 }
445 format!("{}(*)({})", ret, args.connect(", "))
446 }
Alex Crichton0df7c102015-09-10 16:35:37 -0700447 _ => panic!("unknown ty {:?}", ty),
448 }
449 }
Alex Crichton22378822015-09-10 19:59:23 -0700450
451 fn decl2rust(&self, decl: &ast::FnDecl) -> (String, Vec<String>, bool) {
452 let args = decl.inputs.iter().map(|arg| {
453 self.ty2name(&arg.ty)
454 }).collect::<Vec<_>>();
455 let ret = match decl.output {
456 ast::NoReturn(..) |
457 ast::DefaultReturn(..) => "void".to_string(),
458 ast::Return(ref t) => self.ty2name(t),
459 };
460 (ret, args, decl.variadic)
461 }
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700462}
463
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700464impl<'a, 'v> Visitor<'v> for TestGenerator<'a> {
Alex Crichton22378822015-09-10 19:59:23 -0700465 fn visit_item(&mut self, i: &'v ast::Item) {
466 match i.node {
467 ast::ItemTy(_, ref generics) => {
468 self.assert_no_generics(i.ident, generics);
469 self.test_type(&i.ident.to_string());
470 }
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700471
Alex Crichton22378822015-09-10 19:59:23 -0700472 ast::ItemStruct(ref s, ref generics) => {
473 self.assert_no_generics(i.ident, generics);
474 let is_c = i.attrs.iter().any(|a| {
Alex Crichtona9adfbf2015-09-09 23:21:27 -0700475 attr::find_repr_attrs(self.sh, a).iter().any(|a| {
476 *a == ReprAttr::ReprExtern
477 })
Alex Crichton22378822015-09-10 19:59:23 -0700478 });
479 if !is_c {
480 panic!("{} is not marked #[repr(C)]", i.ident);
481 }
482 self.test_struct(&i.ident.to_string(), s);
483 }
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700484
Alex Crichton22378822015-09-10 19:59:23 -0700485 ast::ItemConst(ref ty, _) => {
486 let ty = self.ty2name(ty);
487 self.test_const(&i.ident.to_string(), &ty);
488 }
Alex Crichton0df7c102015-09-10 16:35:37 -0700489
Alex Crichton22378822015-09-10 19:59:23 -0700490 _ => {}
491 }
492 visit::walk_item(self, i)
493 }
494
495 fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
496 match i.node {
497 ast::ForeignItemFn(ref decl, ref generics) => {
498 self.assert_no_generics(i.ident, generics);
499 let (ret, args, variadic) = self.decl2rust(decl);
500 self.test_extern_fn(&i.ident.to_string(), &args, &ret,
501 variadic);
502 }
503 ast::ForeignItemStatic(_, _) => {
504 }
505 }
506 visit::walk_foreign_item(self, i)
507 }
Alex Crichton8e5f0cd2015-09-09 22:46:19 -0700508}
Alex Crichton310d6232015-09-10 10:56:31 -0700509
510impl<'v> Visitor<'v> for StructFinder {
Alex Crichton22378822015-09-10 19:59:23 -0700511 fn visit_item(&mut self, i: &'v ast::Item) {
512 match i.node {
513 ast::ItemStruct(..) => {
514 self.structs.insert(i.ident.to_string());
515 }
516 ast::ItemEnum(..) => {
517 self.structs.insert(i.ident.to_string());
518 }
Alex Crichton310d6232015-09-10 10:56:31 -0700519
Alex Crichton22378822015-09-10 19:59:23 -0700520 _ => {}
521 }
522 visit::walk_item(self, i)
523 }
Alex Crichton310d6232015-09-10 10:56:31 -0700524}