From b7cefd0c962e8ad8a77de45ede39d615d0f78924 Mon Sep 17 00:00:00 2001 From: ILyoan Date: Fri, 11 Jan 2013 18:08:01 +0900 Subject: [PATCH] allowing the entry point name to be something other than main add build tests --- src/librustc/front/test.rs | 9 ++-- src/librustc/middle/resolve.rs | 56 ++++++++++++++++++++---- src/librustc/middle/trans/base.rs | 10 ++++- src/test/compile-fail/multiple-main-2.rs | 17 +++++++ src/test/compile-fail/multiple-main-3.rs | 19 ++++++++ src/test/run-pass/attr-main-2.rs | 17 +++++++ src/test/run-pass/attr-main.rs | 13 ++++++ 7 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 src/test/compile-fail/multiple-main-2.rs create mode 100644 src/test/compile-fail/multiple-main-3.rs create mode 100644 src/test/run-pass/attr-main-2.rs create mode 100644 src/test/run-pass/attr-main.rs diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 870a7d6c59377..0c4b9635a36b9 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -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; @@ -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) } } @@ -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, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index a7c579127f954..e5d3eb558b38b 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -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}; @@ -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(), @@ -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, @@ -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(); } @@ -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, @@ -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 // diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 40740be54cf5b..5a3046ac2486b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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) { diff --git a/src/test/compile-fail/multiple-main-2.rs b/src/test/compile-fail/multiple-main-2.rs new file mode 100644 index 0000000000000..723aefb91cb9c --- /dev/null +++ b/src/test/compile-fail/multiple-main-2.rs @@ -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 or the MIT license +// , 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 +} diff --git a/src/test/compile-fail/multiple-main-3.rs b/src/test/compile-fail/multiple-main-3.rs new file mode 100644 index 0000000000000..36da3e6e84a22 --- /dev/null +++ b/src/test/compile-fail/multiple-main-3.rs @@ -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 or the MIT license +// , 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 + } +} diff --git a/src/test/run-pass/attr-main-2.rs b/src/test/run-pass/attr-main-2.rs new file mode 100644 index 0000000000000..78fb9d3e39a33 --- /dev/null +++ b/src/test/run-pass/attr-main-2.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + fail +} + +#[main] +fn foo() { +} diff --git a/src/test/run-pass/attr-main.rs b/src/test/run-pass/attr-main.rs new file mode 100644 index 0000000000000..782240fd982d5 --- /dev/null +++ b/src/test/run-pass/attr-main.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[main] +fn foo() { +}