Auto merge of #35979 - Manishearth:rollup, r=Manishearth

Rollup of 6 pull requests

- Successful merges: #35238, #35867, #35885, #35916, #35947, #35955
- Failed merges:
This commit is contained in:
bors 2016-08-25 04:35:52 -07:00 committed by GitHub
commit 17a2be8c35
24 changed files with 640 additions and 267 deletions

View File

@ -752,25 +752,81 @@ pub struct InvalidSequence(());
impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
type Item = Result<char, InvalidSequence>;
#[inline]
fn next(&mut self) -> Option<Result<char, InvalidSequence>> {
self.0.next().map(|b| {
if b & 0x80 == 0 { Ok(b as char) } else {
let l = (!b).leading_zeros() as usize; // number of bytes in UTF-8 representation
if l < 2 || l > 6 { return Err(InvalidSequence(())) };
let mut x = (b as u32) & (0x7F >> l);
for _ in 0..l-1 {
self.0.next().map(|first_byte| {
// Emit InvalidSequence according to
// Unicode §5.22 Best Practice for U+FFFD Substitution
// http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630
// Roughly: consume at least one byte,
// then validate one byte at a time and stop before the first unexpected byte
// (which might be the valid start of the next byte sequence).
let mut code_point;
macro_rules! first_byte {
($mask: expr) => {
code_point = u32::from(first_byte & $mask)
}
}
macro_rules! continuation_byte {
() => { continuation_byte!(0x80...0xBF) };
($range: pat) => {
match self.0.peek() {
Some(&b) if b & 0xC0 == 0x80 => {
Some(&byte @ $range) => {
code_point = (code_point << 6) | u32::from(byte & 0b0011_1111);
self.0.next();
x = (x << 6) | (b as u32) & 0x3F;
},
_ => return Err(InvalidSequence(())),
}
_ => return Err(InvalidSequence(()))
}
}
match from_u32(x) {
Some(x) if l == x.len_utf8() => Ok(x),
_ => Err(InvalidSequence(())),
}
match first_byte {
0x00...0x7F => {
first_byte!(0b1111_1111);
}
0xC2...0xDF => {
first_byte!(0b0001_1111);
continuation_byte!();
}
0xE0 => {
first_byte!(0b0000_1111);
continuation_byte!(0xA0...0xBF); // 0x80...0x9F here are overlong
continuation_byte!();
}
0xE1...0xEC | 0xEE...0xEF => {
first_byte!(0b0000_1111);
continuation_byte!();
continuation_byte!();
}
0xED => {
first_byte!(0b0000_1111);
continuation_byte!(0x80...0x9F); // 0xA0..0xBF here are surrogates
continuation_byte!();
}
0xF0 => {
first_byte!(0b0000_0111);
continuation_byte!(0x90...0xBF); // 0x80..0x8F here are overlong
continuation_byte!();
continuation_byte!();
}
0xF1...0xF3 => {
first_byte!(0b0000_0111);
continuation_byte!();
continuation_byte!();
continuation_byte!();
}
0xF4 => {
first_byte!(0b0000_0111);
continuation_byte!(0x80...0x8F); // 0x90..0xBF here are beyond char::MAX
continuation_byte!();
continuation_byte!();
}
_ => return Err(InvalidSequence(())) // Illegal first byte, overlong, or beyond MAX
}
unsafe {
Ok(from_u32_unchecked(code_point))
}
})
}

View File

@ -358,29 +358,50 @@ fn eu_iterator_specializations() {
#[test]
fn test_decode_utf8() {
use core::char::*;
use core::iter::FromIterator;
for &(str, bs) in [("", &[] as &[u8]),
("A", &[0x41u8] as &[u8]),
("<EFBFBD>", &[0xC1u8, 0x81u8] as &[u8]),
("", &[0xE2u8, 0x99u8, 0xA5u8]),
("♥A", &[0xE2u8, 0x99u8, 0xA5u8, 0x41u8] as &[u8]),
("<EFBFBD>", &[0xE2u8, 0x99u8] as &[u8]),
("<EFBFBD>A", &[0xE2u8, 0x99u8, 0x41u8] as &[u8]),
("<EFBFBD>", &[0xC0u8] as &[u8]),
("<EFBFBD>A", &[0xC0u8, 0x41u8] as &[u8]),
("<EFBFBD>", &[0x80u8] as &[u8]),
("<EFBFBD>A", &[0x80u8, 0x41u8] as &[u8]),
("<EFBFBD>", &[0xFEu8] as &[u8]),
("<EFBFBD>A", &[0xFEu8, 0x41u8] as &[u8]),
("<EFBFBD>", &[0xFFu8] as &[u8]),
("<EFBFBD>A", &[0xFFu8, 0x41u8] as &[u8])].into_iter() {
assert!(Iterator::eq(str.chars(),
decode_utf8(bs.into_iter().map(|&b|b))
.map(|r_b| r_b.unwrap_or('\u{FFFD}'))),
"chars = {}, bytes = {:?}, decoded = {:?}", str, bs,
Vec::from_iter(decode_utf8(bs.into_iter().map(|&b|b))
.map(|r_b| r_b.unwrap_or('\u{FFFD}'))));
macro_rules! assert_decode_utf8 {
($input_bytes: expr, $expected_str: expr) => {
let input_bytes: &[u8] = &$input_bytes;
let s = char::decode_utf8(input_bytes.iter().cloned())
.map(|r_b| r_b.unwrap_or('\u{FFFD}'))
.collect::<String>();
assert_eq!(s, $expected_str,
"input bytes: {:?}, expected str: {:?}, result: {:?}",
input_bytes, $expected_str, s);
assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
}
}
assert_decode_utf8!([], "");
assert_decode_utf8!([0x41], "A");
assert_decode_utf8!([0xC1, 0x81], "<EFBFBD><EFBFBD>");
assert_decode_utf8!([0xE2, 0x99, 0xA5], "");
assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
assert_decode_utf8!([0xE2, 0x99], "<EFBFBD>");
assert_decode_utf8!([0xE2, 0x99, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xC0], "<EFBFBD>");
assert_decode_utf8!([0xC0, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0x80], "<EFBFBD>");
assert_decode_utf8!([0x80, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xFE], "<EFBFBD>");
assert_decode_utf8!([0xFE, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xFF], "<EFBFBD>");
assert_decode_utf8!([0xFF, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xC0, 0x80], "<EFBFBD><EFBFBD>");
// Surrogates
assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
assert_decode_utf8!([0xED, 0xA0, 0x80], "<EFBFBD><EFBFBD><EFBFBD>");
assert_decode_utf8!([0xED, 0xBF, 0x80], "<EFBFBD><EFBFBD><EFBFBD>");
assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
// char::MAX
assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 5 and 6 bytes sequence
// Part of the original design of UTF-8,
// but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}

View File

@ -173,12 +173,12 @@ impl<'doc> Doc<'doc> {
self.start == self.end
}
pub fn as_str_slice(&self) -> &'doc str {
pub fn as_str(&self) -> &'doc str {
str::from_utf8(&self.data[self.start..self.end]).unwrap()
}
pub fn as_str(&self) -> String {
self.as_str_slice().to_string()
pub fn to_string(&self) -> String {
self.as_str().to_string()
}
}
@ -773,7 +773,7 @@ pub mod reader {
Ok(char::from_u32(doc_as_u32(self.next_doc(EsChar)?)).unwrap())
}
fn read_str(&mut self) -> DecodeResult<String> {
Ok(self.next_doc(EsStr)?.as_str())
Ok(self.next_doc(EsStr)?.to_string())
}
// Compound types:

View File

@ -601,7 +601,7 @@ pub trait LintContext: Sized {
for (lint_id, level, span) in v {
let (now, now_source) = self.lints().get_level_source(lint_id);
if now == Forbid && level != Forbid {
let lint_name = lint_id.as_str();
let lint_name = lint_id.to_string();
let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
"{}({}) overruled by outer forbid({})",
level.as_str(), lint_name,
@ -1216,7 +1216,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
for &(lint, span, ref msg) in v {
span_bug!(span,
"unprocessed lint {} at {}: {}",
lint.as_str(), tcx.map.node_to_string(*id), *msg)
lint.to_string(), tcx.map.node_to_string(*id), *msg)
}
}
@ -1252,7 +1252,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
// in the iteration code.
for (_, v) in sess.lints.borrow().iter() {
for &(lint, span, ref msg) in v {
span_bug!(span, "unprocessed lint {}: {}", lint.as_str(), *msg)
span_bug!(span, "unprocessed lint {}: {}", lint.to_string(), *msg)
}
}
}

View File

@ -263,7 +263,7 @@ impl LintId {
}
/// Get the name of the lint.
pub fn as_str(&self) -> String {
pub fn to_string(&self) -> String {
self.lint.name_lower()
}
}

View File

@ -237,7 +237,7 @@ impl CodeExtent {
// (This is the special case aluded to in the
// doc-comment for this method)
let stmt_span = blk.stmts[r.first_statement_index as usize].span;
Some(Span { lo: stmt_span.hi, ..blk.span })
Some(Span { lo: stmt_span.hi, hi: blk.span.hi, expn_id: stmt_span.expn_id })
}
}
}

View File

@ -891,6 +891,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"force overflow checks on or off"),
trace_macros: bool = (false, parse_bool, [UNTRACKED],
"for every macro invocation, print its name and arguments"),
debug_macros: bool = (false, parse_bool, [TRACKED],
"emit line numbers debug info inside macros"),
enable_nonzeroing_move_hints: bool = (false, parse_bool, [TRACKED],
"force nonzeroing move optimization on"),
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],

View File

@ -861,7 +861,7 @@ Available lint options:
for (name, to) in lints {
let name = name.to_lowercase().replace("_", "-");
let desc = to.into_iter()
.map(|x| x.as_str().replace("_", "-"))
.map(|x| x.to_string().replace("_", "-"))
.collect::<Vec<String>>()
.join(", ");
println!(" {} {}", padded(&name[..]), desc);

View File

@ -1796,6 +1796,11 @@ extern {
Col: c_uint)
-> DILexicalBlock;
pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: DIBuilderRef,
Scope: DIScope,
File: DIFile)
-> DILexicalBlock;
pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
Context: DIScope,
Name: *const c_char,

View File

@ -86,7 +86,7 @@ pub fn load_index(data: &[u8]) -> index::Index {
pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
let doc = rbml::Doc::new(data);
reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str())
reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.to_string())
}
pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
@ -207,7 +207,7 @@ fn item_defaultness(item: rbml::Doc) -> hir::Defaultness {
fn item_sort(item: rbml::Doc) -> Option<char> {
reader::tagged_docs(item, tag_item_trait_item_sort).nth(0).map(|doc| {
doc.as_str_slice().as_bytes()[0] as char
doc.as_str().as_bytes()[0] as char
})
}
@ -282,7 +282,7 @@ fn item_name(item: rbml::Doc) -> ast::Name {
fn maybe_item_name(item: rbml::Doc) -> Option<ast::Name> {
reader::maybe_get_doc(item, tag_paths_data_name).map(|name| {
let string = name.as_str_slice();
let string = name.as_str();
token::intern(string)
})
}
@ -368,7 +368,7 @@ fn parse_polarity(item_doc: rbml::Doc) -> hir::ImplPolarity {
fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
reader::tagged_docs(names_doc, tag_associated_type_name)
.map(|name_doc| token::intern(name_doc.as_str_slice()))
.map(|name_doc| token::intern(name_doc.as_str()))
.collect()
}
@ -682,7 +682,7 @@ fn each_child_of_item_or_crate<F, G>(cdata: Cmd,
let name_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
let name = name_doc.as_str_slice();
let name = name_doc.as_str();
// This reexport may be in yet another crate.
let crate_data = if child_def_id.krate == cdata.cnum {
@ -869,7 +869,7 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
}
let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
let string = explicit_self_doc.as_str_slice();
let string = explicit_self_doc.as_str();
let explicit_self_kind = string.as_bytes()[0];
match explicit_self_kind as char {
@ -1124,19 +1124,19 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec<ast::Name> {
fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
reader::tagged_docs(md, tag_meta_item_word).map(|meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let n = token::intern_and_get_ident(nd.as_str_slice());
let n = token::intern_and_get_ident(nd.as_str());
attr::mk_word_item(n)
}).chain(reader::tagged_docs(md, tag_meta_item_name_value).map(|meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
let n = token::intern_and_get_ident(nd.as_str_slice());
let v = token::intern_and_get_ident(vd.as_str_slice());
let n = token::intern_and_get_ident(nd.as_str());
let v = token::intern_and_get_ident(vd.as_str());
// FIXME (#623): Should be able to decode MetaItemKind::NameValue variants,
// but currently the encoder just drops them
attr::mk_name_value_item_str(n, v)
})).chain(reader::tagged_docs(md, tag_meta_item_list).map(|meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let n = token::intern_and_get_ident(nd.as_str_slice());
let n = token::intern_and_get_ident(nd.as_str());
let subitems = get_meta_items(meta_item_doc);
attr::mk_list_item(n, subitems)
})).collect()
@ -1191,7 +1191,7 @@ pub fn get_crate_deps(data: &[u8]) -> Vec<CrateDep> {
fn docstr(doc: rbml::Doc, tag_: usize) -> String {
let d = reader::get_doc(doc, tag_);
d.as_str_slice().to_string()
d.as_str().to_string()
}
reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| {
@ -1233,14 +1233,14 @@ pub fn get_crate_hash(data: &[u8]) -> Svh {
pub fn maybe_get_crate_name(data: &[u8]) -> Option<&str> {
let cratedoc = rbml::Doc::new(data);
reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| {
doc.as_str_slice()
doc.as_str()
})
}
pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
let crate_doc = rbml::Doc::new(data);
let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
let slice: &'a str = disambiguator_doc.as_str_slice();
let slice: &'a str = disambiguator_doc.as_str();
slice
}
@ -1446,11 +1446,12 @@ pub fn get_dylib_dependency_formats(cdata: Cmd)
tag_dylib_dependency_formats);
let mut result = Vec::new();
debug!("found dylib deps: {}", formats.as_str_slice());
for spec in formats.as_str_slice().split(',') {
debug!("found dylib deps: {}", formats.as_str());
for spec in formats.as_str().split(',') {
if spec.is_empty() { continue }
let cnum = spec.split(':').nth(0).unwrap();
let link = spec.split(':').nth(1).unwrap();
let mut split = spec.split(':');
let cnum = split.next().unwrap();
let link = split.next().unwrap();
let cnum: ast::CrateNum = cnum.parse().unwrap();
let cnum = cdata.cnum_map.borrow()[cnum];
result.push((cnum, if link == "d" {
@ -1476,7 +1477,7 @@ pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec<String> {
match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
Some(args_doc) => {
reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| {
name_doc.as_str_slice().to_string()
name_doc.as_str().to_string()
}).collect()
},
None => vec![],
@ -1641,7 +1642,7 @@ fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
let mut decoder = reader::Decoder::new(def_key_doc);
let simple_key = def_key::DefKey::decode(&mut decoder).unwrap();
let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| {
token::intern(name.as_str_slice()).as_str()
token::intern(name.as_str()).as_str()
});
def_key::recover_def_key(simple_key, name)
}

View File

@ -25,11 +25,33 @@ use syntax_pos::Pos;
use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use syntax_pos::BytePos;
#[derive(Clone, Copy, Debug)]
pub struct MirDebugScope {
pub scope_metadata: DIScope,
// Start and end offsets of the file to which this DIScope belongs.
// These are used to quickly determine whether some span refers to the same file.
pub file_start_pos: BytePos,
pub file_end_pos: BytePos,
}
impl MirDebugScope {
pub fn is_valid(&self) -> bool {
!self.scope_metadata.is_null()
}
}
/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
/// If debuginfo is disabled, the returned vector is empty.
pub fn create_mir_scopes(fcx: &FunctionContext) -> IndexVec<VisibilityScope, DIScope> {
pub fn create_mir_scopes(fcx: &FunctionContext) -> IndexVec<VisibilityScope, MirDebugScope> {
let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn");
let mut scopes = IndexVec::from_elem(ptr::null_mut(), &mir.visibility_scopes);
let null_scope = MirDebugScope {
scope_metadata: ptr::null_mut(),
file_start_pos: BytePos(0),
file_end_pos: BytePos(0)
};
let mut scopes = IndexVec::from_elem(null_scope, &mir.visibility_scopes);
let fn_metadata = match fcx.debug_context {
FunctionDebugContext::RegularContext(box ref data) => data.fn_metadata,
@ -59,8 +81,8 @@ fn make_mir_scope(ccx: &CrateContext,
has_variables: &BitVector,
fn_metadata: DISubprogram,
scope: VisibilityScope,
scopes: &mut IndexVec<VisibilityScope, DIScope>) {
if !scopes[scope].is_null() {
scopes: &mut IndexVec<VisibilityScope, MirDebugScope>) {
if scopes[scope].is_valid() {
return;
}
@ -70,7 +92,12 @@ fn make_mir_scope(ccx: &CrateContext,
scopes[parent]
} else {
// The root is the function itself.
scopes[scope] = fn_metadata;
let loc = span_start(ccx, mir.span);
scopes[scope] = MirDebugScope {
scope_metadata: fn_metadata,
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
return;
};
@ -81,20 +108,25 @@ fn make_mir_scope(ccx: &CrateContext,
// However, we don't skip creating a nested scope if
// our parent is the root, because we might want to
// put arguments in the root and not have shadowing.
if parent_scope != fn_metadata {
if parent_scope.scope_metadata != fn_metadata {
scopes[scope] = parent_scope;
return;
}
}
let loc = span_start(ccx, scope_data.span);
scopes[scope] = unsafe {
let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
let scope_metadata = unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(ccx),
parent_scope,
parent_scope.scope_metadata,
file_metadata,
loc.line as c_uint,
loc.col.to_usize() as c_uint)
};
scopes[scope] = MirDebugScope {
scope_metadata: scope_metadata,
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
}

View File

@ -22,7 +22,7 @@ use context::SharedCrateContext;
use session::Session;
use llvm::{self, ValueRef};
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock};
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
@ -1839,3 +1839,17 @@ pub fn create_global_var_metadata(cx: &CrateContext,
ptr::null_mut());
}
}
// Creates an "extension" of an existing DIScope into another file.
pub fn extend_scope_to_file(ccx: &CrateContext,
scope_metadata: DIScope,
file: &syntax_pos::FileMap)
-> DILexicalBlock {
let file_metadata = file_metadata(ccx, &file.name, &file.abs_path);
unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
DIB(ccx),
scope_metadata,
file_metadata)
}
}

View File

@ -53,9 +53,10 @@ pub mod metadata;
mod create_scope_map;
mod source_loc;
pub use self::create_scope_map::create_mir_scopes;
pub use self::create_scope_map::{create_mir_scopes, MirDebugScope};
pub use self::source_loc::start_emitting_source_locations;
pub use self::metadata::create_global_var_metadata;
pub use self::metadata::extend_scope_to_file;
#[allow(non_upper_case_globals)]
const DW_TAG_auto_variable: c_uint = 0x100;

View File

@ -48,6 +48,12 @@ pub fn lvalue_locals<'bcx, 'tcx>(bcx: Block<'bcx,'tcx>,
common::type_is_fat_ptr(bcx.tcx(), ty));
} else if common::type_is_imm_pair(bcx.ccx(), ty) {
// We allow pairs and uses of any of their 2 fields.
} else if !analyzer.seen_assigned.contains(index) {
// No assignment has been seen, which means that
// either the local has been marked as lvalue
// already, or there is no possible initialization
// for the local, making any reads invalid.
// This is useful in weeding out dead temps.
} else {
// These sorts of types require an alloca. Note that
// type_is_immediate() may *still* be true, particularly

View File

@ -10,18 +10,17 @@
use libc::c_uint;
use llvm::{self, ValueRef};
use llvm::debuginfo::DIScope;
use rustc::ty;
use rustc::mir::repr as mir;
use rustc::mir::tcx::LvalueTy;
use session::config::FullDebugInfo;
use base;
use common::{self, Block, BlockAndBuilder, CrateContext, FunctionContext, C_null};
use debuginfo::{self, declare_local, DebugLoc, VariableAccess, VariableKind};
use debuginfo::{self, declare_local, DebugLoc, VariableAccess, VariableKind, FunctionDebugContext};
use machine;
use type_of;
use syntax_pos::DUMMY_SP;
use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos};
use syntax::parse::token::keywords;
use std::ops::Deref;
@ -103,12 +102,67 @@ pub struct MirContext<'bcx, 'tcx:'bcx> {
locals: IndexVec<mir::Local, LocalRef<'tcx>>,
/// Debug information for MIR scopes.
scopes: IndexVec<mir::VisibilityScope, DIScope>
scopes: IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
}
impl<'blk, 'tcx> MirContext<'blk, 'tcx> {
pub fn debug_loc(&self, source_info: mir::SourceInfo) -> DebugLoc {
DebugLoc::ScopeAt(self.scopes[source_info.scope], source_info.span)
pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> DebugLoc {
// Bail out if debug info emission is not enabled.
match self.fcx.debug_context {
FunctionDebugContext::DebugInfoDisabled |
FunctionDebugContext::FunctionWithoutDebugInfo => {
// Can't return DebugLoc::None here because intrinsic::trans_intrinsic_call()
// relies on debug location to obtain span of the call site.
return DebugLoc::ScopeAt(self.scopes[source_info.scope].scope_metadata,
source_info.span);
}
FunctionDebugContext::RegularContext(_) =>{}
}
// In order to have a good line stepping behavior in debugger, we overwrite debug
// locations of macro expansions with that of the outermost expansion site
// (unless the crate is being compiled with `-Z debug-macros`).
if source_info.span.expn_id == NO_EXPANSION ||
source_info.span.expn_id == COMMAND_LINE_EXPN ||
self.fcx.ccx.sess().opts.debugging_opts.debug_macros {
let scope_metadata = self.scope_metadata_for_loc(source_info.scope,
source_info.span.lo);
DebugLoc::ScopeAt(scope_metadata, source_info.span)
} else {
let cm = self.fcx.ccx.sess().codemap();
// Walk up the macro expansion chain until we reach a non-expanded span.
let mut span = source_info.span;
while span.expn_id != NO_EXPANSION && span.expn_id != COMMAND_LINE_EXPN {
if let Some(callsite_span) = cm.with_expn_info(span.expn_id,
|ei| ei.map(|ei| ei.call_site.clone())) {
span = callsite_span;
} else {
break;
}
}
let scope_metadata = self.scope_metadata_for_loc(source_info.scope, span.lo);
// Use span of the outermost call site, while keeping the original lexical scope
DebugLoc::ScopeAt(scope_metadata, span)
}
}
// DILocations inherit source file name from the parent DIScope. Due to macro expansions
// it may so happen that the current span belongs to a different file than the DIScope
// corresponding to span's containing visibility scope. If so, we need to create a DIScope
// "extension" into that file.
fn scope_metadata_for_loc(&self, scope_id: mir::VisibilityScope, pos: BytePos)
-> llvm::debuginfo::DIScope {
let scope_metadata = self.scopes[scope_id].scope_metadata;
if pos < self.scopes[scope_id].file_start_pos ||
pos >= self.scopes[scope_id].file_end_pos {
let cm = self.fcx.ccx.sess().codemap();
debuginfo::extend_scope_to_file(self.fcx.ccx,
scope_metadata,
&cm.lookup_char_pos(pos).file)
} else {
scope_metadata
}
}
}
@ -155,16 +209,38 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
analyze::cleanup_kinds(bcx, &mir))
});
// Allocate a `Block` for every basic block
let block_bcxs: IndexVec<mir::BasicBlock, Block<'blk,'tcx>> =
mir.basic_blocks().indices().map(|bb| {
if bb == mir::START_BLOCK {
fcx.new_block("start")
} else {
fcx.new_block(&format!("{:?}", bb))
}
}).collect();
// Compute debuginfo scopes from MIR scopes.
let scopes = debuginfo::create_mir_scopes(fcx);
let mut mircx = MirContext {
mir: mir.clone(),
fcx: fcx,
llpersonalityslot: None,
blocks: block_bcxs,
unreachable_block: None,
cleanup_kinds: cleanup_kinds,
landing_pads: IndexVec::from_elem(None, mir.basic_blocks()),
scopes: scopes,
locals: IndexVec::new(),
};
// Allocate variable and temp allocas
let locals = {
let args = arg_local_refs(&bcx, &mir, &scopes, &lvalue_locals);
mircx.locals = {
let args = arg_local_refs(&bcx, &mir, &mircx.scopes, &lvalue_locals);
let vars = mir.var_decls.iter().enumerate().map(|(i, decl)| {
let ty = bcx.monomorphize(&decl.ty);
let scope = scopes[decl.source_info.scope];
let dbg = !scope.is_null() && bcx.sess().opts.debuginfo == FullDebugInfo;
let debug_scope = mircx.scopes[decl.source_info.scope];
let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
let local = mir.local_index(&mir::Lvalue::Var(mir::Var::new(i))).unwrap();
if !lvalue_locals.contains(local.index()) && !dbg {
@ -173,11 +249,16 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
let lvalue = LvalueRef::alloca(&bcx, ty, &decl.name.as_str());
if dbg {
bcx.with_block(|bcx| {
declare_local(bcx, decl.name, ty, scope,
VariableAccess::DirectVariable { alloca: lvalue.llval },
VariableKind::LocalVariable, decl.source_info.span);
});
let dbg_loc = mircx.debug_loc(decl.source_info);
if let DebugLoc::ScopeAt(scope, span) = dbg_loc {
bcx.with_block(|bcx| {
declare_local(bcx, decl.name, ty, scope,
VariableAccess::DirectVariable { alloca: lvalue.llval },
VariableKind::LocalVariable, span);
});
} else {
panic!("Unexpected");
}
}
LocalRef::Lvalue(lvalue)
});
@ -203,18 +284,8 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
})).collect()
};
// Allocate a `Block` for every basic block
let block_bcxs: IndexVec<mir::BasicBlock, Block<'blk,'tcx>> =
mir.basic_blocks().indices().map(|bb| {
if bb == mir::START_BLOCK {
fcx.new_block("start")
} else {
fcx.new_block(&format!("{:?}", bb))
}
}).collect();
// Branch to the START block
let start_bcx = block_bcxs[mir::START_BLOCK];
let start_bcx = mircx.blocks[mir::START_BLOCK];
bcx.br(start_bcx.llbb);
// Up until here, IR instructions for this function have explicitly not been annotated with
@ -222,18 +293,6 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
// emitting should be enabled.
debuginfo::start_emitting_source_locations(fcx);
let mut mircx = MirContext {
mir: mir.clone(),
fcx: fcx,
llpersonalityslot: None,
blocks: block_bcxs,
unreachable_block: None,
cleanup_kinds: cleanup_kinds,
landing_pads: IndexVec::from_elem(None, mir.basic_blocks()),
locals: locals,
scopes: scopes
};
let mut visited = BitVector::new(mir.basic_blocks().len());
let mut rpo = traversal::reverse_postorder(&mir);
@ -271,7 +330,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
/// indirect.
fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
mir: &mir::Mir<'tcx>,
scopes: &IndexVec<mir::VisibilityScope, DIScope>,
scopes: &IndexVec<mir::VisibilityScope, debuginfo::MirDebugScope>,
lvalue_locals: &BitVector)
-> Vec<LocalRef<'tcx>> {
let fcx = bcx.fcx();
@ -281,8 +340,8 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
// Get the argument scope, if it exists and if we need it.
let arg_scope = scopes[mir::ARGUMENT_VISIBILITY_SCOPE];
let arg_scope = if !arg_scope.is_null() && bcx.sess().opts.debuginfo == FullDebugInfo {
Some(arg_scope)
let arg_scope = if arg_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo {
Some(arg_scope.scope_metadata)
} else {
None
};

View File

@ -12,7 +12,6 @@
//! that clean them.
pub use self::Type::*;
pub use self::PrimitiveType::*;
pub use self::TypeKind::*;
pub use self::VariantKind::*;
pub use self::Mutability::*;
@ -287,34 +286,34 @@ impl Item {
}
}
pub fn is_mod(&self) -> bool {
ItemType::from_item(self) == ItemType::Module
ItemType::from(self) == ItemType::Module
}
pub fn is_trait(&self) -> bool {
ItemType::from_item(self) == ItemType::Trait
ItemType::from(self) == ItemType::Trait
}
pub fn is_struct(&self) -> bool {
ItemType::from_item(self) == ItemType::Struct
ItemType::from(self) == ItemType::Struct
}
pub fn is_enum(&self) -> bool {
ItemType::from_item(self) == ItemType::Module
ItemType::from(self) == ItemType::Module
}
pub fn is_fn(&self) -> bool {
ItemType::from_item(self) == ItemType::Function
ItemType::from(self) == ItemType::Function
}
pub fn is_associated_type(&self) -> bool {
ItemType::from_item(self) == ItemType::AssociatedType
ItemType::from(self) == ItemType::AssociatedType
}
pub fn is_associated_const(&self) -> bool {
ItemType::from_item(self) == ItemType::AssociatedConst
ItemType::from(self) == ItemType::AssociatedConst
}
pub fn is_method(&self) -> bool {
ItemType::from_item(self) == ItemType::Method
ItemType::from(self) == ItemType::Method
}
pub fn is_ty_method(&self) -> bool {
ItemType::from_item(self) == ItemType::TyMethod
ItemType::from(self) == ItemType::TyMethod
}
pub fn is_primitive(&self) -> bool {
ItemType::from_item(self) == ItemType::Primitive
ItemType::from(self) == ItemType::Primitive
}
pub fn is_stripped(&self) -> bool {
match self.inner { StrippedItem(..) => true, _ => false }
@ -380,6 +379,23 @@ pub enum ItemEnum {
StrippedItem(Box<ItemEnum>),
}
impl ItemEnum {
pub fn generics(&self) -> Option<&Generics> {
Some(match *self {
ItemEnum::StructItem(ref s) => &s.generics,
ItemEnum::EnumItem(ref e) => &e.generics,
ItemEnum::FunctionItem(ref f) => &f.generics,
ItemEnum::TypedefItem(ref t, _) => &t.generics,
ItemEnum::TraitItem(ref t) => &t.generics,
ItemEnum::ImplItem(ref i) => &i.generics,
ItemEnum::TyMethodItem(ref i) => &i.generics,
ItemEnum::MethodItem(ref i) => &i.generics,
ItemEnum::ForeignFunctionItem(ref f) => &f.generics,
_ => return None,
})
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Module {
pub items: Vec<Item>,
@ -1469,8 +1485,8 @@ pub enum PrimitiveType {
Str,
Slice,
Array,
PrimitiveTuple,
PrimitiveRawPointer,
Tuple,
RawPointer,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@ -1500,12 +1516,12 @@ impl Type {
pub fn primitive_type(&self) -> Option<PrimitiveType> {
match *self {
Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
Vector(..) | BorrowedRef{ type_: box Vector(..), .. } => Some(Slice),
Vector(..) | BorrowedRef{ type_: box Vector(..), .. } => Some(PrimitiveType::Slice),
FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. } => {
Some(Array)
Some(PrimitiveType::Array)
}
Tuple(..) => Some(PrimitiveTuple),
RawPointer(..) => Some(PrimitiveRawPointer),
Tuple(..) => Some(PrimitiveType::Tuple),
RawPointer(..) => Some(PrimitiveType::RawPointer),
_ => None,
}
}
@ -1530,25 +1546,25 @@ impl GetDefId for Type {
impl PrimitiveType {
fn from_str(s: &str) -> Option<PrimitiveType> {
match s {
"isize" => Some(Isize),
"i8" => Some(I8),
"i16" => Some(I16),
"i32" => Some(I32),
"i64" => Some(I64),
"usize" => Some(Usize),
"u8" => Some(U8),
"u16" => Some(U16),
"u32" => Some(U32),
"u64" => Some(U64),
"bool" => Some(Bool),
"char" => Some(Char),
"str" => Some(Str),
"f32" => Some(F32),
"f64" => Some(F64),
"array" => Some(Array),
"slice" => Some(Slice),
"tuple" => Some(PrimitiveTuple),
"pointer" => Some(PrimitiveRawPointer),
"isize" => Some(PrimitiveType::Isize),
"i8" => Some(PrimitiveType::I8),
"i16" => Some(PrimitiveType::I16),
"i32" => Some(PrimitiveType::I32),
"i64" => Some(PrimitiveType::I64),
"usize" => Some(PrimitiveType::Usize),
"u8" => Some(PrimitiveType::U8),
"u16" => Some(PrimitiveType::U16),
"u32" => Some(PrimitiveType::U32),
"u64" => Some(PrimitiveType::U64),
"bool" => Some(PrimitiveType::Bool),
"char" => Some(PrimitiveType::Char),
"str" => Some(PrimitiveType::Str),
"f32" => Some(PrimitiveType::F32),
"f64" => Some(PrimitiveType::F64),
"array" => Some(PrimitiveType::Array),
"slice" => Some(PrimitiveType::Slice),
"tuple" => Some(PrimitiveType::Tuple),
"pointer" => Some(PrimitiveType::RawPointer),
_ => None,
}
}
@ -1568,25 +1584,25 @@ impl PrimitiveType {
pub fn to_string(&self) -> &'static str {
match *self {
Isize => "isize",
I8 => "i8",
I16 => "i16",
I32 => "i32",
I64 => "i64",
Usize => "usize",
U8 => "u8",
U16 => "u16",
U32 => "u32",
U64 => "u64",
F32 => "f32",
F64 => "f64",
Str => "str",
Bool => "bool",
Char => "char",
Array => "array",
Slice => "slice",
PrimitiveTuple => "tuple",
PrimitiveRawPointer => "pointer",
PrimitiveType::Isize => "isize",
PrimitiveType::I8 => "i8",
PrimitiveType::I16 => "i16",
PrimitiveType::I32 => "i32",
PrimitiveType::I64 => "i64",
PrimitiveType::Usize => "usize",
PrimitiveType::U8 => "u8",
PrimitiveType::U16 => "u16",
PrimitiveType::U32 => "u32",
PrimitiveType::U64 => "u64",
PrimitiveType::F32 => "f32",
PrimitiveType::F64 => "f64",
PrimitiveType::Str => "str",
PrimitiveType::Bool => "bool",
PrimitiveType::Char => "char",
PrimitiveType::Array => "array",
PrimitiveType::Slice => "slice",
PrimitiveType::Tuple => "tuple",
PrimitiveType::RawPointer => "pointer",
}
}
@ -1603,6 +1619,38 @@ impl PrimitiveType {
}
}
impl From<ast::IntTy> for PrimitiveType {
fn from(int_ty: ast::IntTy) -> PrimitiveType {
match int_ty {
ast::IntTy::Is => PrimitiveType::Isize,
ast::IntTy::I8 => PrimitiveType::I8,
ast::IntTy::I16 => PrimitiveType::I16,
ast::IntTy::I32 => PrimitiveType::I32,
ast::IntTy::I64 => PrimitiveType::I64,
}
}
}
impl From<ast::UintTy> for PrimitiveType {
fn from(uint_ty: ast::UintTy) -> PrimitiveType {
match uint_ty {
ast::UintTy::Us => PrimitiveType::Usize,
ast::UintTy::U8 => PrimitiveType::U8,
ast::UintTy::U16 => PrimitiveType::U16,
ast::UintTy::U32 => PrimitiveType::U32,
ast::UintTy::U64 => PrimitiveType::U64,
}
}
}
impl From<ast::FloatTy> for PrimitiveType {
fn from(float_ty: ast::FloatTy) -> PrimitiveType {
match float_ty {
ast::FloatTy::F32 => PrimitiveType::F32,
ast::FloatTy::F64 => PrimitiveType::F64,
}
}
}
// Poor man's type parameter substitution at HIR level.
// Used to replace private type aliases in public signatures with their aliased types.
@ -1754,21 +1802,12 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
fn clean(&self, cx: &DocContext) -> Type {
match self.sty {
ty::TyNever => Never,
ty::TyBool => Primitive(Bool),
ty::TyChar => Primitive(Char),
ty::TyInt(ast::IntTy::Is) => Primitive(Isize),
ty::TyInt(ast::IntTy::I8) => Primitive(I8),
ty::TyInt(ast::IntTy::I16) => Primitive(I16),
ty::TyInt(ast::IntTy::I32) => Primitive(I32),
ty::TyInt(ast::IntTy::I64) => Primitive(I64),
ty::TyUint(ast::UintTy::Us) => Primitive(Usize),
ty::TyUint(ast::UintTy::U8) => Primitive(U8),
ty::TyUint(ast::UintTy::U16) => Primitive(U16),
ty::TyUint(ast::UintTy::U32) => Primitive(U32),
ty::TyUint(ast::UintTy::U64) => Primitive(U64),
ty::TyFloat(ast::FloatTy::F32) => Primitive(F32),
ty::TyFloat(ast::FloatTy::F64) => Primitive(F64),
ty::TyStr => Primitive(Str),
ty::TyBool => Primitive(PrimitiveType::Bool),
ty::TyChar => Primitive(PrimitiveType::Char),
ty::TyInt(int_ty) => Primitive(int_ty.into()),
ty::TyUint(uint_ty) => Primitive(uint_ty.into()),
ty::TyFloat(float_ty) => Primitive(float_ty.into()),
ty::TyStr => Primitive(PrimitiveType::Str),
ty::TyBox(t) => {
let box_did = cx.tcx_opt().and_then(|tcx| {
tcx.lang_items.owned_box()
@ -2421,25 +2460,25 @@ fn build_deref_target_impls(cx: &DocContext,
}
};
let did = match primitive {
Isize => tcx.lang_items.isize_impl(),
I8 => tcx.lang_items.i8_impl(),
I16 => tcx.lang_items.i16_impl(),
I32 => tcx.lang_items.i32_impl(),
I64 => tcx.lang_items.i64_impl(),
Usize => tcx.lang_items.usize_impl(),
U8 => tcx.lang_items.u8_impl(),
U16 => tcx.lang_items.u16_impl(),
U32 => tcx.lang_items.u32_impl(),
U64 => tcx.lang_items.u64_impl(),
F32 => tcx.lang_items.f32_impl(),
F64 => tcx.lang_items.f64_impl(),
Char => tcx.lang_items.char_impl(),
Bool => None,
Str => tcx.lang_items.str_impl(),
Slice => tcx.lang_items.slice_impl(),
Array => tcx.lang_items.slice_impl(),
PrimitiveTuple => None,
PrimitiveRawPointer => tcx.lang_items.const_ptr_impl(),
PrimitiveType::Isize => tcx.lang_items.isize_impl(),
PrimitiveType::I8 => tcx.lang_items.i8_impl(),
PrimitiveType::I16 => tcx.lang_items.i16_impl(),
PrimitiveType::I32 => tcx.lang_items.i32_impl(),
PrimitiveType::I64 => tcx.lang_items.i64_impl(),
PrimitiveType::Usize => tcx.lang_items.usize_impl(),
PrimitiveType::U8 => tcx.lang_items.u8_impl(),
PrimitiveType::U16 => tcx.lang_items.u16_impl(),
PrimitiveType::U32 => tcx.lang_items.u32_impl(),
PrimitiveType::U64 => tcx.lang_items.u64_impl(),
PrimitiveType::F32 => tcx.lang_items.f32_impl(),
PrimitiveType::F64 => tcx.lang_items.f64_impl(),
PrimitiveType::Char => tcx.lang_items.char_impl(),
PrimitiveType::Bool => None,
PrimitiveType::Str => tcx.lang_items.str_impl(),
PrimitiveType::Slice => tcx.lang_items.slice_impl(),
PrimitiveType::Array => tcx.lang_items.slice_impl(),
PrimitiveType::Tuple => None,
PrimitiveType::RawPointer => tcx.lang_items.const_ptr_impl(),
};
if let Some(did) = did {
if !did.is_local() {
@ -2722,21 +2761,12 @@ fn resolve_type(cx: &DocContext,
let is_generic = match def {
Def::PrimTy(p) => match p {
hir::TyStr => return Primitive(Str),
hir::TyBool => return Primitive(Bool),
hir::TyChar => return Primitive(Char),
hir::TyInt(ast::IntTy::Is) => return Primitive(Isize),
hir::TyInt(ast::IntTy::I8) => return Primitive(I8),
hir::TyInt(ast::IntTy::I16) => return Primitive(I16),
hir::TyInt(ast::IntTy::I32) => return Primitive(I32),
hir::TyInt(ast::IntTy::I64) => return Primitive(I64),
hir::TyUint(ast::UintTy::Us) => return Primitive(Usize),
hir::TyUint(ast::UintTy::U8) => return Primitive(U8),
hir::TyUint(ast::UintTy::U16) => return Primitive(U16),
hir::TyUint(ast::UintTy::U32) => return Primitive(U32),
hir::TyUint(ast::UintTy::U64) => return Primitive(U64),
hir::TyFloat(ast::FloatTy::F32) => return Primitive(F32),
hir::TyFloat(ast::FloatTy::F64) => return Primitive(F64),
hir::TyStr => return Primitive(PrimitiveType::Str),
hir::TyBool => return Primitive(PrimitiveType::Bool),
hir::TyChar => return Primitive(PrimitiveType::Char),
hir::TyInt(int_ty) => return Primitive(int_ty.into()),
hir::TyUint(uint_ty) => return Primitive(uint_ty.into()),
hir::TyFloat(float_ty) => return Primitive(float_ty.into()),
},
Def::SelfTy(..) if path.segments.len() == 1 => {
return Generic(keywords::SelfType.name().to_string());

View File

@ -23,7 +23,7 @@ use rustc::hir::def_id::DefId;
use syntax::abi::Abi;
use rustc::hir;
use clean;
use clean::{self, PrimitiveType};
use core::DocAccessLevels;
use html::item_type::ItemType;
use html::escape::Escape;
@ -468,39 +468,39 @@ impl fmt::Display for clean::Type {
}
clean::Tuple(ref typs) => {
match &typs[..] {
&[] => primitive_link(f, clean::PrimitiveTuple, "()"),
&[] => primitive_link(f, PrimitiveType::Tuple, "()"),
&[ref one] => {
primitive_link(f, clean::PrimitiveTuple, "(")?;
primitive_link(f, PrimitiveType::Tuple, "(")?;
write!(f, "{},", one)?;
primitive_link(f, clean::PrimitiveTuple, ")")
primitive_link(f, PrimitiveType::Tuple, ")")
}
many => {
primitive_link(f, clean::PrimitiveTuple, "(")?;
primitive_link(f, PrimitiveType::Tuple, "(")?;
write!(f, "{}", CommaSep(&many))?;
primitive_link(f, clean::PrimitiveTuple, ")")
primitive_link(f, PrimitiveType::Tuple, ")")
}
}
}
clean::Vector(ref t) => {
primitive_link(f, clean::Slice, &format!("["))?;
primitive_link(f, PrimitiveType::Slice, &format!("["))?;
write!(f, "{}", t)?;
primitive_link(f, clean::Slice, &format!("]"))
primitive_link(f, PrimitiveType::Slice, &format!("]"))
}
clean::FixedVector(ref t, ref s) => {
primitive_link(f, clean::PrimitiveType::Array, "[")?;
primitive_link(f, PrimitiveType::Array, "[")?;
write!(f, "{}", t)?;
primitive_link(f, clean::PrimitiveType::Array,
primitive_link(f, PrimitiveType::Array,
&format!("; {}]", Escape(s)))
}
clean::Never => f.write_str("!"),
clean::RawPointer(m, ref t) => {
match **t {
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
primitive_link(f, clean::PrimitiveType::RawPointer,
&format!("*{}{}", RawMutableSpace(m), t))
}
_ => {
primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
primitive_link(f, clean::PrimitiveType::RawPointer,
&format!("*{}", RawMutableSpace(m)))?;
write!(f, "{}", t)
}
@ -516,12 +516,13 @@ impl fmt::Display for clean::Type {
clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T]
match **bt {
clean::Generic(_) =>
primitive_link(f, clean::Slice,
primitive_link(f, PrimitiveType::Slice,
&format!("&amp;{}{}[{}]", lt, m, **bt)),
_ => {
primitive_link(f, clean::Slice, &format!("&amp;{}{}[", lt, m))?;
primitive_link(f, PrimitiveType::Slice,
&format!("&amp;{}{}[", lt, m))?;
write!(f, "{}", **bt)?;
primitive_link(f, clean::Slice, "]")
primitive_link(f, PrimitiveType::Slice, "]")
}
}
}

View File

@ -50,8 +50,8 @@ pub enum NameSpace {
Macro,
}
impl ItemType {
pub fn from_item(item: &clean::Item) -> ItemType {
impl<'a> From<&'a clean::Item> for ItemType {
fn from(item: &'a clean::Item) -> ItemType {
let inner = match item.inner {
clean::StrippedItem(box ref item) => item,
ref inner@_ => inner,
@ -83,8 +83,10 @@ impl ItemType {
clean::StrippedItem(..) => unreachable!(),
}
}
}
pub fn from_type_kind(kind: clean::TypeKind) -> ItemType {
impl From<clean::TypeKind> for ItemType {
fn from(kind: clean::TypeKind) -> ItemType {
match kind {
clean::TypeStruct => ItemType::Struct,
clean::TypeEnum => ItemType::Enum,
@ -97,7 +99,9 @@ impl ItemType {
clean::TypeTypedef => ItemType::Typedef,
}
}
}
impl ItemType {
pub fn css_class(&self) -> &'static str {
match *self {
ItemType::Module => "mod",

View File

@ -509,7 +509,7 @@ pub fn run(mut krate: clean::Crate,
} = renderinfo;
let external_paths = external_paths.into_iter()
.map(|(k, (v, t))| (k, (v, ItemType::from_type_kind(t))))
.map(|(k, (v, t))| (k, (v, ItemType::from(t))))
.collect();
let mut cache = Cache {
@ -833,7 +833,7 @@ fn mkdir(path: &Path) -> io::Result<()> {
/// Returns a documentation-level item type from the item.
fn item_type(item: &clean::Item) -> ItemType {
ItemType::from_item(item)
ItemType::from(item)
}
/// Takes a path to a source file and cleans the path to it. This canonicalizes
@ -997,17 +997,8 @@ impl DocFolder for Cache {
// Register any generics to their corresponding string. This is used
// when pretty-printing types
match item.inner {
clean::StructItem(ref s) => self.generics(&s.generics),
clean::EnumItem(ref e) => self.generics(&e.generics),
clean::FunctionItem(ref f) => self.generics(&f.generics),
clean::TypedefItem(ref t, _) => self.generics(&t.generics),
clean::TraitItem(ref t) => self.generics(&t.generics),
clean::ImplItem(ref i) => self.generics(&i.generics),
clean::TyMethodItem(ref i) => self.generics(&i.generics),
clean::MethodItem(ref i) => self.generics(&i.generics),
clean::ForeignFunctionItem(ref f) => self.generics(&f.generics),
_ => {}
if let Some(generics) = item.inner.generics() {
self.generics(generics);
}
if !self.seen_mod {
@ -1362,7 +1353,7 @@ impl Context {
// these modules are recursed into, but not rendered normally
// (a flag on the context).
if !self.render_redirect_pages {
self.render_redirect_pages = self.maybe_ignore_item(&item);
self.render_redirect_pages = maybe_ignore_item(&item);
}
if item.is_mod() {
@ -1445,7 +1436,7 @@ impl Context {
// BTreeMap instead of HashMap to get a sorted output
let mut map = BTreeMap::new();
for item in &m.items {
if self.maybe_ignore_item(item) { continue }
if maybe_ignore_item(item) { continue }
let short = item_type(item).css_class();
let myname = match item.name {
@ -1462,17 +1453,6 @@ impl Context {
}
return map;
}
fn maybe_ignore_item(&self, it: &clean::Item) -> bool {
match it.inner {
clean::StrippedItem(..) => true,
clean::ModuleItem(ref m) => {
it.doc_value().is_none() && m.items.is_empty()
&& it.visibility != Some(clean::Public)
},
_ => false,
}
}
}
impl<'a> Item<'a> {
@ -1715,7 +1695,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
if let clean::DefaultImplItem(..) = items[*i].inner {
return false;
}
!cx.maybe_ignore_item(&items[*i])
!maybe_ignore_item(&items[*i])
}).collect::<Vec<usize>>();
// the order of item types in the listing
@ -1863,6 +1843,17 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
Ok(())
}
fn maybe_ignore_item(it: &clean::Item) -> bool {
match it.inner {
clean::StrippedItem(..) => true,
clean::ModuleItem(ref m) => {
it.doc_value().is_none() && m.items.is_empty()
&& it.visibility != Some(clean::Public)
},
_ => false,
}
}
fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<String> {
let mut stability = vec![];

View File

@ -521,6 +521,15 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
LLVMRustMetadataRef File) {
return wrap(Builder->createLexicalBlockFile(
unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File)));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Context,

View File

@ -0,0 +1,20 @@
// Copyright 2013-2016 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.
// compile-flags:-g
#![crate_type = "rlib"]
#[macro_export]
macro_rules! new_scope {
() => {
let x = 1;
}
}

View File

@ -10,7 +10,7 @@
// min-lldb-version: 310
// compile-flags:-g
// compile-flags:-g -Zdebug-macros
// === GDB TESTS ===================================================================================

View File

@ -0,0 +1,103 @@
// Copyright 2013-2016 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.
// ignore-windows
// ignore-android
// min-lldb-version: 310
// aux-build:macro-stepping.rs
#![allow(unused)]
#[macro_use]
extern crate macro_stepping; // exports new_scope!()
// compile-flags:-g
// === GDB TESTS ===================================================================================
// gdb-command:run
// gdb-command:next
// gdb-command:frame
// gdb-check:[...]#loc1[...]
// gdb-command:next
// gdb-command:frame
// gdb-check:[...]#loc2[...]
// gdb-command:next
// gdb-command:frame
// gdb-check:[...]#loc3[...]
// gdb-command:next
// gdb-command:frame
// gdb-check:[...]#loc4[...]
// gdb-command:next
// gdb-command:frame
// gdb-check:[...]#loc5[...]
// gdb-command:next
// gdb-command:frame
// gdb-check:[...]#loc6[...]
// === LLDB TESTS ==================================================================================
// lldb-command:set set stop-line-count-before 0
// lldb-command:set set stop-line-count-after 1
// Can't set both to zero or lldb will stop printing source at all. So it will output the current
// line and the next. We deal with this by having at least 2 lines between the #loc's
// lldb-command:run
// lldb-command:next
// lldb-command:frame select
// lldb-check:[...]#loc1[...]
// lldb-command:next
// lldb-command:frame select
// lldb-check:[...]#loc2[...]
// lldb-command:next
// lldb-command:frame select
// lldb-check:[...]#loc3[...]
// lldb-command:next
// lldb-command:frame select
// lldb-check:[...]#loc4[...]
// lldb-command:next
// lldb-command:frame select
// lldb-check:[...]#loc5[...]
macro_rules! foo {
() => {
let a = 1;
let b = 2;
let c = 3;
}
}
macro_rules! foo2 {
() => {
foo!();
let x = 1;
foo!();
}
}
fn main() {
zzz(); // #break
foo!(); // #loc1
foo2!(); // #loc2
let x = vec![42]; // #loc3
new_scope!(); // #loc4
println!("Hello {}", // #loc5
"world");
zzz(); // #loc6
}
fn zzz() {()}

View File

@ -0,0 +1,18 @@
// Copyright 2016 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.
const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024];
// Check that the promoted copy of TEST_DATA doesn't
// leave an alloca from an unused temp behind, which,
// without optimizations, can still blow the stack.
fn main() {
println!("{}", TEST_DATA.len());
}