return sopts;
}
-pub fn build_session(sopts: @session::Options, demitter: @diagnostic::Emitter)
+pub fn build_session(sopts: @session::Options,
+ local_crate_source_file: Option<Path>,
+ 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<Path>,
+ 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),
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),
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")));
}
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());
macro_registrar_fn: RefCell<Option<ast::DefId>>,
filesearch: @filesearch::FileSearch,
building_library: Cell<bool>,
+ // 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<Path>,
working_dir: Path,
lints: RefCell<HashMap<ast::NodeId,
~[(lint::Lint, codemap::Span, ~str)]>>,
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);
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
};
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;
/// 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<DebugLocation>,
}
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),
};
}
-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,
})
})
});
+
+ fn fallback_path(cx: &CrateContext) -> CString {
+ cx.link_meta.crateid.name.to_c_str()
+ }
}
fn declare_local(bcx: &Block,
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();
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);
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());
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);
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");
};
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);
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);
debug!("About to build session...");
let sess = driver::build_session(options,
+ Some(in_file.clone()),
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
--- /dev/null
+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 <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.