Skip to content

Commit

Permalink
allowing the entry point name to be something other than main
Browse files Browse the repository at this point in the history
add build tests
  • Loading branch information
ILyoan authored and brson committed Jan 14, 2013
1 parent 0e84907 commit b7cefd0
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 14 deletions.
9 changes: 4 additions & 5 deletions src/librustc/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use syntax::codemap::span;
use syntax::fold;
use syntax::print::pprust;
use syntax::{ast, ast_util};
use syntax::attr::attrs_contains_name;

export modify_for_testing;

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

// FIXME (#2403): This is sloppy. Instead we should have some mechanism to
// indicate to the translation pass which function we want to be main.
fn nomain(cx: test_ctxt, item: @ast::item) -> Option<@ast::item> {
match item.node {
ast::item_fn(*) => {
if item.ident == cx.sess.ident_of(~"main")
&& !cx.sess.building_library {
if attrs_contains_name(item.attrs, ~"main")
&& !cx.sess.building_library {
option::None
} else { option::Some(item) }
}
Expand Down Expand Up @@ -498,7 +497,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item {
let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
let item: ast::item =
{ident: cx.sess.ident_of(~"main"),
attrs: ~[],
attrs: ~[attr::mk_attr(attr::mk_word_item(~"main"))],
id: cx.sess.next_node_id(),
node: item_,
vis: ast::public,
Expand Down
56 changes: 48 additions & 8 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ use syntax::ast_util::{def_id_of_def, dummy_sp, local_def};
use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
use syntax::ast_util::{Privacy, Public, Private, visibility_to_privacy};
use syntax::ast_util::has_legacy_export_attr;
use syntax::attr::{attr_metas, contains_name};
use syntax::attr::{attr_metas, contains_name, attrs_contains_name};
use syntax::parse::token::ident_interner;
use syntax::parse::token::special_idents;
use syntax::print::pprust::{pat_to_str, path_to_str};
Expand Down Expand Up @@ -857,6 +857,9 @@ fn Resolver(session: Session, lang_items: LanguageItems,

namespaces: ~[ TypeNS, ValueNS ],

attr_main_fn: None,
main_fns: ~[],

def_map: HashMap(),
export_map2: HashMap(),
trait_map: @HashMap(),
Expand Down Expand Up @@ -916,6 +919,11 @@ struct Resolver {
// The four namespaces.
namespaces: ~[Namespace],

// The function that has attribute named 'main'
mut attr_main_fn: Option<(node_id, span)>,
// The functions named 'main'
mut main_fns: ~[Option<(node_id, span)>],

def_map: DefMap,
export_map2: ExportMap2,
trait_map: TraitMap,
Expand All @@ -937,6 +945,7 @@ impl Resolver {
self.resolve_crate();
self.session.abort_if_errors();

self.check_duplicate_main();
self.check_for_unused_imports_if_necessary();
}

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

if !self.session.building_library &&
is_none(&self.session.main_fn) &&
item.ident == special_idents::main {
self.main_fns.push(Some((item.id, item.span)));
}

self.session.main_fn = Some((item.id, item.span));
if attrs_contains_name(item.attrs, ~"main") {
if self.attr_main_fn.is_none() {
self.attr_main_fn = Some((item.id, item.span));
} else {
self.session.span_err(
item.span,
~"multiple 'main' functions");
}
}
}

self.resolve_function(OpaqueFunctionRibKind,
Expand Down Expand Up @@ -5353,6 +5369,30 @@ impl Resolver {
self.def_map.insert(node_id, def);
}

//
// main function checking
//
// be sure that there is only one main function
//
fn check_duplicate_main() {
if self.attr_main_fn.is_none() {
if self.main_fns.len() >= 1u {
let mut i = 1u;
while i < self.main_fns.len() {
let (_, dup_main_span) =
option::unwrap(self.main_fns[i]);
self.session.span_err(
dup_main_span,
~"multiple 'main' functions");
i += 1;
}
self.session.main_fn = self.main_fns[0];
}
} else {
self.session.main_fn = self.attr_main_fn;
}
}

//
// Unused import checking
//
Expand Down
10 changes: 9 additions & 1 deletion src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2153,13 +2153,21 @@ fn register_fn_fuller(ccx: @crate_ctxt,
ccx.item_symbols.insert(node_id, ps);

// FIXME #4404 android JNI hacks
let is_main = is_main_name(path) && (!ccx.sess.building_library ||
let is_main = is_main_fn(&ccx.sess, node_id) &&
(!ccx.sess.building_library ||
(ccx.sess.building_library &&
ccx.sess.targ_cfg.os == session::os_android));
if is_main { create_main_wrapper(ccx, sp, llfn); }
llfn
}

fn is_main_fn(sess: &Session, node_id: ast::node_id) -> bool {
match sess.main_fn {
Some((main_id, _)) => node_id == main_id,
None => false
}
}

// Create a _rust_main(args: ~[str]) function which will be called from the
// runtime rust_start function
fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
Expand Down
17 changes: 17 additions & 0 deletions src/test/compile-fail/multiple-main-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[main]
fn bar() {
}

#[main]
fn foo() { //~ ERROR multiple 'main' functions
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/multiple-main-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[main]
fn main1() {
}

mod foo {
#[main]
fn main2() { //~ ERROR multiple 'main' functions
}
}
17 changes: 17 additions & 0 deletions src/test/run-pass/attr-main-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
fail
}

#[main]
fn foo() {
}
13 changes: 13 additions & 0 deletions src/test/run-pass/attr-main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[main]
fn foo() {
}

0 comments on commit b7cefd0

Please sign in to comment.