Skip to content

Commit 2a59ab8

Browse files
committed
rustc: Specify lint checks via crate attributes
A crate attribute like `#[lint(no_ctypes)]` can now be used to turn off ctypes checking. Issue #1543
1 parent 4d757b9 commit 2a59ab8

File tree

3 files changed

+101
-13
lines changed

3 files changed

+101
-13
lines changed

src/comp/driver/driver.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
204204
time(time_passes, "kind checking",
205205
bind kind::check_crate(ty_cx, method_map, last_uses, crate));
206206

207-
vec::iter(sess.opts.lint_opts) {|lopt|
208-
alt lopt {
209-
ctypes {
210-
time(time_passes, "ctypes usage checking",
211-
bind lint::check_ctypes(ty_cx, crate))
212-
}
213-
}
214-
}
207+
lint::check_crate(ty_cx, crate, sess.opts.lint_opts, time_passes);
215208

216209
if upto == cu_no_trans { ret {crate: crate, tcx: some(ty_cx), src: src}; }
217210
let outputs = option::get(outputs);
@@ -390,8 +383,8 @@ fn build_session_options(match: getopts::match,
390383
let parse_only = opt_present(match, "parse-only");
391384
let no_trans = opt_present(match, "no-trans");
392385
let lint_opts = [];
393-
if !opt_present(match, "no-lint-ctypes") {
394-
lint_opts += [lint::ctypes];
386+
if opt_present(match, "no-lint-ctypes") {
387+
lint_opts += [(lint::ctypes, false)];
395388
}
396389

397390
let output_type =

src/comp/driver/session.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ type options =
3434
debuginfo: bool,
3535
extra_debuginfo: bool,
3636
verify: bool,
37-
lint_opts: [lint::option],
37+
lint_opts: [(lint::option, bool)],
3838
save_temps: bool,
3939
stats: bool,
4040
time_passes: bool,

src/comp/middle/lint.rs

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,98 @@
11
import driver::session::session;
22
import middle::ty::ctxt;
33
import syntax::{ast, visit};
4-
5-
type crate_ctxt = {tcx: ty::ctxt};
4+
import front::attr;
5+
import std::io;
6+
import io::writer_util;
67

78
enum option {
89
ctypes,
910
}
1011

12+
impl opt_ for option {
13+
fn desc() -> str {
14+
"lint: " + alt self {
15+
ctypes { "ctypes usage checking" }
16+
}
17+
}
18+
fn run(tcx: ty::ctxt, crate: @ast::crate, time_pass: bool) {
19+
let checker = alt self {
20+
ctypes {
21+
bind check_ctypes(tcx, crate)
22+
}
23+
};
24+
time(time_pass, self.desc(), checker);
25+
}
26+
}
27+
28+
// FIXME: Copied from driver.rs, to work around a bug(#1566)
29+
fn time(do_it: bool, what: str, thunk: block()) {
30+
if !do_it{ ret thunk(); }
31+
let start = std::time::precise_time_s();
32+
thunk();
33+
let end = std::time::precise_time_s();
34+
io::stdout().write_str(#fmt("time: %3.3f s\t%s\n",
35+
end - start, what));
36+
}
37+
38+
// Merge lint options specified by crate attributes and rustc command
39+
// line. Precedence: cmdline > attribute > default
40+
fn merge_opts(attrs: [ast::attribute], cmd_opts: [(option, bool)]) ->
41+
[(option, bool)] {
42+
fn str_to_option(name: str) -> (option, bool) {
43+
ret alt name {
44+
"ctypes" { (ctypes, true) }
45+
"no_ctypes" { (ctypes, false) }
46+
}
47+
}
48+
49+
fn meta_to_option(meta: @ast::meta_item) -> (option, bool) {
50+
ret alt meta.node {
51+
ast::meta_word(name) {
52+
str_to_option(name)
53+
}
54+
};
55+
}
56+
57+
fn default() -> [(option, bool)] {
58+
[(ctypes, true)]
59+
}
60+
61+
fn contains(xs: [(option, bool)], x: option) -> bool {
62+
for (o, _) in xs {
63+
if o == x { ret true; }
64+
}
65+
ret false;
66+
}
67+
68+
let result = cmd_opts;
69+
70+
let lint_metas =
71+
attr::attr_metas(attr::find_attrs_by_name(attrs, "lint"));
72+
73+
vec::iter(lint_metas) {|mi|
74+
alt mi.node {
75+
ast::meta_list(_, list) {
76+
vec::iter(list) {|e|
77+
let (o, v) = meta_to_option(e);
78+
if !contains(cmd_opts, o) {
79+
result += [(o, v)];
80+
}
81+
}
82+
}
83+
_ { }
84+
}
85+
};
86+
87+
for (o, v) in default() {
88+
if !contains(result, o) {
89+
result += [(o, v)];
90+
}
91+
}
92+
93+
ret result;
94+
}
95+
1196
fn check_ctypes(tcx: ty::ctxt, crate: @ast::crate) {
1297
fn check_native_fn(tcx: ty::ctxt, decl: ast::fn_decl) {
1398
let tys = vec::map(decl.inputs) {|a| a.ty };
@@ -52,6 +137,16 @@ fn check_ctypes(tcx: ty::ctxt, crate: @ast::crate) {
52137
});
53138
visit::visit_crate(*crate, (), visit);
54139
}
140+
141+
fn check_crate(tcx: ty::ctxt, crate: @ast::crate,
142+
opts: [(option, bool)], time: bool) {
143+
let lint_opts = lint::merge_opts(crate.node.attrs, opts);
144+
for (lopt, switch) in lint_opts {
145+
if switch == true {
146+
lopt.run(tcx, crate, time);
147+
}
148+
}
149+
}
55150
//
56151
// Local Variables:
57152
// mode: rust

0 commit comments

Comments
 (0)