Skip to content

Commit b7cefd0

Browse files
ILyoanbrson
authored andcommitted
allowing the entry point name to be something other than main
add build tests
1 parent 0e84907 commit b7cefd0

File tree

7 files changed

+127
-14
lines changed

7 files changed

+127
-14
lines changed

src/librustc/front/test.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use syntax::codemap::span;
2525
use syntax::fold;
2626
use syntax::print::pprust;
2727
use syntax::{ast, ast_util};
28+
use syntax::attr::attrs_contains_name;
2829

2930
export modify_for_testing;
3031

@@ -88,13 +89,11 @@ fn fold_mod(cx: test_ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod {
8889
// Remove any defined main function from the AST so it doesn't clash with
8990
// the one we're going to add. Only if compiling an executable.
9091

91-
// FIXME (#2403): This is sloppy. Instead we should have some mechanism to
92-
// indicate to the translation pass which function we want to be main.
9392
fn nomain(cx: test_ctxt, item: @ast::item) -> Option<@ast::item> {
9493
match item.node {
9594
ast::item_fn(*) => {
96-
if item.ident == cx.sess.ident_of(~"main")
97-
&& !cx.sess.building_library {
95+
if attrs_contains_name(item.attrs, ~"main")
96+
&& !cx.sess.building_library {
9897
option::None
9998
} else { option::Some(item) }
10099
}
@@ -498,7 +497,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
498497
let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
499498
let item: ast::item =
500499
{ident: cx.sess.ident_of(~"main"),
501-
attrs: ~[],
500+
attrs: ~[attr::mk_attr(attr::mk_word_item(~"main"))],
502501
id: cx.sess.next_node_id(),
503502
node: item_,
504503
vis: ast::public,

src/librustc/middle/resolve.rs

+48-8
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use syntax::ast_util::{def_id_of_def, dummy_sp, local_def};
5959
use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
6060
use syntax::ast_util::{Privacy, Public, Private, visibility_to_privacy};
6161
use syntax::ast_util::has_legacy_export_attr;
62-
use syntax::attr::{attr_metas, contains_name};
62+
use syntax::attr::{attr_metas, contains_name, attrs_contains_name};
6363
use syntax::parse::token::ident_interner;
6464
use syntax::parse::token::special_idents;
6565
use syntax::print::pprust::{pat_to_str, path_to_str};
@@ -857,6 +857,9 @@ fn Resolver(session: Session, lang_items: LanguageItems,
857857

858858
namespaces: ~[ TypeNS, ValueNS ],
859859

860+
attr_main_fn: None,
861+
main_fns: ~[],
862+
860863
def_map: HashMap(),
861864
export_map2: HashMap(),
862865
trait_map: @HashMap(),
@@ -916,6 +919,11 @@ struct Resolver {
916919
// The four namespaces.
917920
namespaces: ~[Namespace],
918921

922+
// The function that has attribute named 'main'
923+
mut attr_main_fn: Option<(node_id, span)>,
924+
// The functions named 'main'
925+
mut main_fns: ~[Option<(node_id, span)>],
926+
919927
def_map: DefMap,
920928
export_map2: ExportMap2,
921929
trait_map: TraitMap,
@@ -937,6 +945,7 @@ impl Resolver {
937945
self.resolve_crate();
938946
self.session.abort_if_errors();
939947

948+
self.check_duplicate_main();
940949
self.check_for_unused_imports_if_necessary();
941950
}
942951

@@ -3923,15 +3932,22 @@ impl Resolver {
39233932
item_fn(ref fn_decl, _, ref ty_params, ref block) => {
39243933
// If this is the main function, we must record it in the
39253934
// session.
3926-
//
3927-
// For speed, we put the string comparison last in this chain
3928-
// of conditionals.
3935+
if !self.session.building_library {
3936+
if self.attr_main_fn.is_none() &&
3937+
item.ident == special_idents::main {
39293938

3930-
if !self.session.building_library &&
3931-
is_none(&self.session.main_fn) &&
3932-
item.ident == special_idents::main {
3939+
self.main_fns.push(Some((item.id, item.span)));
3940+
}
39333941

3934-
self.session.main_fn = Some((item.id, item.span));
3942+
if attrs_contains_name(item.attrs, ~"main") {
3943+
if self.attr_main_fn.is_none() {
3944+
self.attr_main_fn = Some((item.id, item.span));
3945+
} else {
3946+
self.session.span_err(
3947+
item.span,
3948+
~"multiple 'main' functions");
3949+
}
3950+
}
39353951
}
39363952

39373953
self.resolve_function(OpaqueFunctionRibKind,
@@ -5353,6 +5369,30 @@ impl Resolver {
53535369
self.def_map.insert(node_id, def);
53545370
}
53555371

5372+
//
5373+
// main function checking
5374+
//
5375+
// be sure that there is only one main function
5376+
//
5377+
fn check_duplicate_main() {
5378+
if self.attr_main_fn.is_none() {
5379+
if self.main_fns.len() >= 1u {
5380+
let mut i = 1u;
5381+
while i < self.main_fns.len() {
5382+
let (_, dup_main_span) =
5383+
option::unwrap(self.main_fns[i]);
5384+
self.session.span_err(
5385+
dup_main_span,
5386+
~"multiple 'main' functions");
5387+
i += 1;
5388+
}
5389+
self.session.main_fn = self.main_fns[0];
5390+
}
5391+
} else {
5392+
self.session.main_fn = self.attr_main_fn;
5393+
}
5394+
}
5395+
53565396
//
53575397
// Unused import checking
53585398
//

src/librustc/middle/trans/base.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2153,13 +2153,21 @@ fn register_fn_fuller(ccx: @crate_ctxt,
21532153
ccx.item_symbols.insert(node_id, ps);
21542154

21552155
// FIXME #4404 android JNI hacks
2156-
let is_main = is_main_name(path) && (!ccx.sess.building_library ||
2156+
let is_main = is_main_fn(&ccx.sess, node_id) &&
2157+
(!ccx.sess.building_library ||
21572158
(ccx.sess.building_library &&
21582159
ccx.sess.targ_cfg.os == session::os_android));
21592160
if is_main { create_main_wrapper(ccx, sp, llfn); }
21602161
llfn
21612162
}
21622163

2164+
fn is_main_fn(sess: &Session, node_id: ast::node_id) -> bool {
2165+
match sess.main_fn {
2166+
Some((main_id, _)) => node_id == main_id,
2167+
None => false
2168+
}
2169+
}
2170+
21632171
// Create a _rust_main(args: ~[str]) function which will be called from the
21642172
// runtime rust_start function
21652173
fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[main]
12+
fn bar() {
13+
}
14+
15+
#[main]
16+
fn foo() { //~ ERROR multiple 'main' functions
17+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[main]
12+
fn main1() {
13+
}
14+
15+
mod foo {
16+
#[main]
17+
fn main2() { //~ ERROR multiple 'main' functions
18+
}
19+
}

src/test/run-pass/attr-main-2.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
fail
13+
}
14+
15+
#[main]
16+
fn foo() {
17+
}

src/test/run-pass/attr-main.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[main]
12+
fn foo() {
13+
}

0 commit comments

Comments
 (0)