diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index bfa69583a0657..a8eff7f0d6e66 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -897,35 +897,48 @@ pub fn build_session_options(binary: ~str, return sopts; } -pub fn build_session(sopts: @session::Options, demitter: @diagnostic::Emitter) +pub fn build_session(sopts: @session::Options, + local_crate_source_file: Option, + demitter: @diagnostic::Emitter) -> Session { let codemap = @codemap::CodeMap::new(); let diagnostic_handler = diagnostic::mk_handler(Some(demitter)); let span_diagnostic_handler = diagnostic::mk_span_handler(diagnostic_handler, codemap); - build_session_(sopts, codemap, demitter, span_diagnostic_handler) + + build_session_(sopts, local_crate_source_file, codemap, demitter, span_diagnostic_handler) } pub fn build_session_(sopts: @session::Options, - cm: @codemap::CodeMap, + local_crate_source_file: Option, + codemap: @codemap::CodeMap, demitter: @diagnostic::Emitter, span_diagnostic_handler: @diagnostic::SpanHandler) -> Session { let target_cfg = build_target_config(sopts, demitter); - let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, - cm); + let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, codemap); let cstore = @CStore::new(token::get_ident_interner()); let filesearch = @filesearch::FileSearch::new( &sopts.maybe_sysroot, sopts.target_triple, sopts.addl_lib_search_paths); + + // Make the path absolute, if necessary + let local_crate_source_file = local_crate_source_file.map(|path| + if path.is_absolute() { + path.clone() + } else { + os::getcwd().join(path.clone()) + } + ); + @Session_ { targ_cfg: target_cfg, opts: sopts, cstore: cstore, parse_sess: p_s, - codemap: cm, + codemap: codemap, // For a library crate, this is always none entry_fn: RefCell::new(None), entry_type: Cell::new(None), @@ -933,6 +946,7 @@ pub fn build_session_(sopts: @session::Options, span_diagnostic: span_diagnostic_handler, filesearch: filesearch, building_library: Cell::new(false), + local_crate_source_file: local_crate_source_file, working_dir: os::getcwd(), lints: RefCell::new(HashMap::new()), node_id: Cell::new(1), @@ -1164,13 +1178,8 @@ mod test { Ok(m) => m, Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg()) }; - let sessopts = build_session_options( - ~"rustc", - matches, - @diagnostic::DefaultEmitter as @diagnostic::Emitter); - let sess = build_session(sessopts, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); + let sessopts = build_session_options(~"rustc", matches, @diagnostic::DefaultEmitter); + let sess = build_session(sessopts, None, @diagnostic::DefaultEmitter); let cfg = build_configuration(sess); assert!((attr::contains_name(cfg, "test"))); } @@ -1187,13 +1196,8 @@ mod test { f.to_err_msg()); } }; - let sessopts = build_session_options( - ~"rustc", - matches, - @diagnostic::DefaultEmitter as @diagnostic::Emitter); - let sess = build_session(sessopts, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); + let sessopts = build_session_options(~"rustc", matches, @diagnostic::DefaultEmitter); + let sess = build_session(sessopts, None, @diagnostic::DefaultEmitter); let cfg = build_configuration(sess); let mut test_items = cfg.iter().filter(|m| "test" == m.name()); assert!(test_items.next().is_some()); diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 38fa85fe8089a..b70ca03977f42 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -211,6 +211,9 @@ pub struct Session_ { macro_registrar_fn: RefCell>, filesearch: @filesearch::FileSearch, building_library: Cell, + // The name of the root source file of the crate, in the local file system. The path is always + // expected to be absolute. `None` means that there is no source file. + local_crate_source_file: Option, working_dir: Path, lints: RefCell>, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 86e82dec9e6e9..9056d6e5d4ff6 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -230,22 +230,22 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { version(binary); return; } - let input = match matches.free.len() { + let (input, input_file_path) = match matches.free.len() { 0u => d::early_error(demitter, "no input filename given"), 1u => { let ifile = matches.free[0].as_slice(); if "-" == ifile { let src = str::from_utf8_owned(io::stdin().read_to_end()).unwrap(); - d::StrInput(src.to_managed()) + (d::StrInput(src.to_managed()), None) } else { - d::FileInput(Path::new(ifile)) + (d::FileInput(Path::new(ifile)), Some(Path::new(ifile))) } } _ => d::early_error(demitter, "multiple input filenames provided") }; let sopts = d::build_session_options(binary, matches, demitter); - let sess = d::build_session(sopts, demitter); + let sess = d::build_session(sopts, input_file_path, demitter); let odir = matches.opt_str("out-dir").map(|o| Path::new(o)); let ofile = matches.opt_str("o").map(|o| Path::new(o)); let cfg = d::build_configuration(sess); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 9744c395b7c19..ceb5e4d91e42d 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2741,7 +2741,7 @@ pub fn trans_crate(sess: session::Session, let link_meta = link::build_link_meta(sess, crate.attrs, output, &mut symbol_hasher); - // Append ".rc" to crate name as LLVM module identifier. + // Append ".rs" to crate name as LLVM module identifier. // // LLVM code generator emits a ".file filename" directive // for ELF backends. Value of the "filename" is set as the @@ -2749,7 +2749,7 @@ pub fn trans_crate(sess: session::Session, // crashes if the module identifer is same as other symbols // such as a function name in the module. // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 - let llmod_id = link_meta.crateid.name.clone() + ".rc"; + let llmod_id = link_meta.crateid.name.clone() + ".rs"; let ccx = @CrateContext::new(sess, llmod_id, diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 527308be0fffa..11e69867abbb4 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -165,7 +165,7 @@ impl CrateContext { let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod); let dbg_cx = if sess.opts.debuginfo { - Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned())) + Some(debuginfo::CrateDebugContext::new(llmod)) } else { None }; diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 4c5ed91e5f747..dbbb02144d129 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -142,7 +142,7 @@ use middle::ty; use middle::pat_util; use util::ppaux; -use std::c_str::ToCStr; +use std::c_str::{CString, ToCStr}; use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::hashmap::HashSet; @@ -173,7 +173,6 @@ static DW_ATE_unsigned_char: c_uint = 0x08; /// A context object for maintaining all state needed by the debuginfo module. pub struct CrateDebugContext { - priv crate_file: ~str, priv llcontext: ContextRef, priv builder: DIBuilderRef, priv current_debug_location: Cell, @@ -186,13 +185,12 @@ pub struct CrateDebugContext { } impl CrateDebugContext { - pub fn new(llmod: ModuleRef, crate: ~str) -> CrateDebugContext { + pub fn new(llmod: ModuleRef) -> CrateDebugContext { debug!("CrateDebugContext::new"); let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) }; // DIBuilder inherits context from the module, so we'd better use the same one let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; return CrateDebugContext { - crate_file: crate, llcontext: llcontext, builder: builder, current_debug_location: Cell::new(UnknownLocation), @@ -929,26 +927,49 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { }; } -fn compile_unit_metadata(cx: @CrateContext) { - let dcx = debug_context(cx); - let crate_name: &str = dcx.crate_file; - - debug!("compile_unit_metadata: {:?}", crate_name); +fn compile_unit_metadata(cx: &CrateContext) { + let work_dir = &cx.sess.working_dir; + let compile_unit_name = match cx.sess.local_crate_source_file { + None => fallback_path(cx), + Some(ref abs_path) => { + if abs_path.is_relative() { + cx.sess.warn("debuginfo: Invalid path to crate's local root source file!"); + fallback_path(cx) + } else { + match abs_path.path_relative_from(work_dir) { + Some(ref p) if p.is_relative() => { + // prepend "./" if necessary + let dotdot = bytes!(".."); + let prefix = &[dotdot[0], ::std::path::SEP_BYTE]; + let mut path_bytes = p.as_vec().to_owned(); + + if path_bytes.slice_to(2) != prefix && + path_bytes.slice_to(2) != dotdot { + path_bytes.insert(0, prefix[0]); + path_bytes.insert(1, prefix[1]); + } + + path_bytes.to_c_str() + } + _ => fallback_path(cx) + } + } + } + }; - // FIXME (#9639): This needs to handle non-utf8 paths - let work_dir = cx.sess.working_dir.as_str().unwrap(); + debug!("compile_unit_metadata: {:?}", compile_unit_name); let producer = format!("rustc version {}", env!("CFG_VERSION")); - crate_name.with_c_str(|crate_name| { - work_dir.with_c_str(|work_dir| { + compile_unit_name.with_ref(|compile_unit_name| { + work_dir.as_vec().with_c_str(|work_dir| { producer.with_c_str(|producer| { "".with_c_str(|flags| { "".with_c_str(|split_name| { unsafe { llvm::LLVMDIBuilderCreateCompileUnit( - dcx.builder, + debug_context(cx).builder, DW_LANG_RUST, - crate_name, + compile_unit_name, work_dir, producer, cx.sess.opts.optimize != session::No, @@ -961,6 +982,10 @@ fn compile_unit_metadata(cx: @CrateContext) { }) }) }); + + fn fallback_path(cx: &CrateContext) -> CString { + cx.link_meta.crateid.name.to_c_str() + } } fn declare_local(bcx: &Block, diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index dc8e090596d0c..6ac4c5ff395ce 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -52,7 +52,7 @@ fn setup_env(test_name: &str, source_string: &str) -> Env { let matches = getopts(~[~"-Z", ~"verbose"], optgroups()).get(); let diag = diagnostic::collect(messages); let sessopts = build_session_options(~"rustc", &matches, diag); - let sess = build_session(sessopts, diag); + let sess = build_session(sessopts, None, diag); let cfg = build_configuration(sess, ~"whatever", str_input(~"")); let dm = HashMap(); let amap = HashMap(); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8501a01d34bcf..e4260e367a879 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -64,9 +64,9 @@ fn get_ast_and_resolve(cpath: &Path, syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm); let sess = driver::driver::build_session_(sessopts, + Some(cpath.clone()), parsesess.cm, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter, + @diagnostic::DefaultEmitter, span_diagnostic_handler); let mut cfg = build_configuration(sess); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4d8df829a9448..9271af9d575ea 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -34,7 +34,8 @@ use visit_ast::RustdocVisitor; pub fn run(input: &str, matches: &getopts::Matches) -> int { let parsesess = parse::new_parse_sess(None); - let input = driver::FileInput(Path::new(input)); + let input_path = Path::new(input); + let input = driver::FileInput(input_path.clone()); let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice())); let libs = @RefCell::new(libs.move_iter().collect()); @@ -52,9 +53,9 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int { diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm); let sess = driver::build_session_(sessopts, + Some(input_path), parsesess.cm, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter, + @diagnostic::DefaultEmitter, span_diagnostic_handler); let cfg = driver::build_configuration(sess); @@ -113,9 +114,9 @@ fn runtest(test: &str, cratename: &str, libs: HashSet) { diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm); let sess = driver::build_session_(sessopts, + None, parsesess.cm, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter, + @diagnostic::DefaultEmitter, span_diagnostic_handler); let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir"); diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index e5e494e9b5f0c..14936cee4f03d 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -114,8 +114,8 @@ impl<'a> PkgScript<'a> { }; let input = driver::FileInput(script.clone()); let sess = driver::build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); + Some(script.clone()), + @diagnostic::DefaultEmitter); let cfg = driver::build_configuration(sess); let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); let loader = &mut Loader::new(sess); diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index bf8ec1e738cab..ea69a25ddc42d 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -1770,11 +1770,8 @@ fn test_linker_build() { let matches = getopts([], optgroups()); let options = build_session_options(~"rustpkg", matches.as_ref().unwrap(), - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); - let sess = build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); + @diagnostic::DefaultEmitter); + let sess = build_session(options, None, @diagnostic::DefaultEmitter); let test_sys = test_sysroot(); // FIXME (#9639): This needs to handle non-utf8 paths let cc = get_cc_prog(sess); diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 57fcf564c5db2..1f8962fbd3af0 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -264,6 +264,7 @@ pub fn compile_input(context: &BuildContext, debug!("About to build session..."); let sess = driver::build_session(options, + Some(in_file.clone()), @diagnostic::DefaultEmitter as @diagnostic::Emitter); diff --git a/src/test/debug-info/issue11600.rs b/src/test/debug-info/issue11600.rs new file mode 100644 index 0000000000000..425aff8d44172 --- /dev/null +++ b/src/test/debug-info/issue11600.rs @@ -0,0 +1,27 @@ +fn main() { + let args : ~[~str] = ::std::os::args(); + ::std::io::println(args[0]); +} + + +// xfail-android: FIXME(#10381) + +// This test case checks whether compile unit names are set correctly, so that the correct default +// source file can be found. + +// compile-flags:-Z extra-debug-info +// debugger:list +// check:1[...]fn main() { +// check:2[...]let args : ~[~str] = ::std::os::args(); +// check:3[...]::std::io::println(args[0]); +// check:4[...]} + +// Copyright 2013 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.