auto merge of #20032 : Manishearth/rust/plugin-loader, r=cmr
`rustc something.rs -L folder_with_plugin_dylib/ -Z extra-plugins=foo` works via this My way of testing this is by cloning https://github.com/Manishearth/rust-clippy, `cargo build`ing it, and then running `rustc examples/box_vec.rs -L target/ -Z extra-plugins=rust_clippy` after editing out the `exern crate rust_clippy` from `box_vec.rs` r? @huonw fixes #15446
This commit is contained in:
commit
a8a210b57e
19 changed files with 330 additions and 275 deletions
|
@ -42,6 +42,8 @@ pub struct TestProps {
|
|||
pub pretty_compare_only: bool,
|
||||
// Patterns which must not appear in the output of a cfail test.
|
||||
pub forbid_output: Vec<String>,
|
||||
// Ignore errors which originate from a command line span
|
||||
pub ignore_command_line: bool,
|
||||
}
|
||||
|
||||
// Load any test directives embedded in the file
|
||||
|
@ -60,6 +62,8 @@ pub fn load_props(testfile: &Path) -> TestProps {
|
|||
let mut pretty_mode = None;
|
||||
let mut pretty_compare_only = false;
|
||||
let mut forbid_output = Vec::new();
|
||||
let mut ignore_command_line = false;
|
||||
|
||||
iter_header(testfile, |ln| {
|
||||
match parse_error_pattern(ln) {
|
||||
Some(ep) => error_patterns.push(ep),
|
||||
|
@ -102,6 +106,10 @@ pub fn load_props(testfile: &Path) -> TestProps {
|
|||
pretty_compare_only = parse_pretty_compare_only(ln);
|
||||
}
|
||||
|
||||
if !ignore_command_line {
|
||||
ignore_command_line = parse_ignore_command_line(ln);
|
||||
}
|
||||
|
||||
match parse_aux_build(ln) {
|
||||
Some(ab) => { aux_builds.push(ab); }
|
||||
None => {}
|
||||
|
@ -140,6 +148,7 @@ pub fn load_props(testfile: &Path) -> TestProps {
|
|||
pretty_mode: pretty_mode.unwrap_or("normal".to_string()),
|
||||
pretty_compare_only: pretty_compare_only,
|
||||
forbid_output: forbid_output,
|
||||
ignore_command_line: ignore_command_line,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,6 +300,10 @@ fn parse_pretty_compare_only(line: &str) -> bool {
|
|||
parse_name_directive(line, "pretty-compare-only")
|
||||
}
|
||||
|
||||
fn parse_ignore_command_line(line: &str) -> bool {
|
||||
parse_name_directive(line, "ignore-command-line")
|
||||
}
|
||||
|
||||
fn parse_exec_env(line: &str) -> Option<(String, String)> {
|
||||
parse_name_value_directive(line, "exec-env").map(|nv| {
|
||||
// nv is either FOO or FOO=BAR
|
||||
|
|
|
@ -104,7 +104,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
|
|||
if !props.error_patterns.is_empty() {
|
||||
fatal("both error pattern and expected errors specified");
|
||||
}
|
||||
check_expected_errors(expected_errors, testfile, &proc_res);
|
||||
check_expected_errors(props, expected_errors, testfile, &proc_res);
|
||||
} else {
|
||||
check_error_patterns(props, testfile, output_to_check.as_slice(), &proc_res);
|
||||
}
|
||||
|
@ -941,7 +941,8 @@ fn check_forbid_output(props: &TestProps,
|
|||
}
|
||||
}
|
||||
|
||||
fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
|
||||
fn check_expected_errors(props: &TestProps,
|
||||
expected_errors: Vec<errors::ExpectedError> ,
|
||||
testfile: &Path,
|
||||
proc_res: &ProcRes) {
|
||||
|
||||
|
@ -996,6 +997,11 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
|
|||
was_expected = true;
|
||||
}
|
||||
|
||||
if line.starts_with("<command line option>") &&
|
||||
props.ignore_command_line {
|
||||
was_expected = true;
|
||||
}
|
||||
|
||||
if !was_expected && is_compiler_error_or_warning(line) {
|
||||
fatal_proc_rec(format!("unexpected compiler error or warning: '{}'",
|
||||
line).as_slice(),
|
||||
|
|
|
@ -26,7 +26,7 @@ use syntax::ast;
|
|||
use syntax::abi;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::{Span, mk_sp};
|
||||
use syntax::codemap::{COMMAND_LINE_SP, Span, mk_sp};
|
||||
use syntax::parse;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::parse::token;
|
||||
|
@ -445,8 +445,20 @@ impl<'a> CrateReader<'a> {
|
|||
}
|
||||
|
||||
pub fn read_plugin_metadata<'b>(&'b mut self,
|
||||
vi: &'b ast::ViewItem) -> PluginMetadata<'b> {
|
||||
let info = self.extract_crate_info(vi).unwrap();
|
||||
krate: CrateOrString<'b>) -> PluginMetadata<'b> {
|
||||
let (info, span) = match krate {
|
||||
CrateOrString::Krate(c) => {
|
||||
(self.extract_crate_info(c).unwrap(), c.span)
|
||||
}
|
||||
CrateOrString::Str(s) => {
|
||||
(CrateInfo {
|
||||
name: s.to_string(),
|
||||
ident: s.to_string(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
should_link: true,
|
||||
}, COMMAND_LINE_SP)
|
||||
}
|
||||
};
|
||||
let target_triple = &self.sess.opts.target_triple[];
|
||||
let is_cross = target_triple != config::host_triple();
|
||||
let mut should_link = info.should_link && !is_cross;
|
||||
|
@ -455,7 +467,7 @@ impl<'a> CrateReader<'a> {
|
|||
let name = info.name.clone();
|
||||
let mut load_ctxt = loader::Context {
|
||||
sess: self.sess,
|
||||
span: vi.span,
|
||||
span: span,
|
||||
ident: &ident[],
|
||||
crate_name: &name[],
|
||||
hash: None,
|
||||
|
@ -486,7 +498,7 @@ impl<'a> CrateReader<'a> {
|
|||
let metadata = if register {
|
||||
// Register crate now to avoid double-reading metadata
|
||||
let (_, cmd, _) = self.register_crate(&None, &info.ident[],
|
||||
&info.name[], vi.span, library);
|
||||
&info.name[], span, library);
|
||||
PMDSource::Registered(cmd)
|
||||
} else {
|
||||
// Not registering the crate; just hold on to the metadata
|
||||
|
@ -498,12 +510,18 @@ impl<'a> CrateReader<'a> {
|
|||
metadata: metadata,
|
||||
dylib: dylib,
|
||||
info: info,
|
||||
vi_span: vi.span,
|
||||
vi_span: span,
|
||||
target_only: target_only,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
pub enum CrateOrString<'a> {
|
||||
Krate(&'a ast::ViewItem),
|
||||
Str(&'a str)
|
||||
}
|
||||
|
||||
impl<'a> PluginMetadata<'a> {
|
||||
/// Read exported macros
|
||||
pub fn exported_macros(&self) -> Vec<ast::MacroDef> {
|
||||
|
|
|
@ -22,7 +22,6 @@ use middle::ty;
|
|||
use super::Constraint;
|
||||
use middle::infer::SubregionOrigin;
|
||||
use middle::infer::region_inference::RegionVarBindings;
|
||||
use session::config;
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
use util::ppaux::Repr;
|
||||
|
||||
|
@ -55,7 +54,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
|
|||
subject_node: ast::NodeId) {
|
||||
let tcx = region_vars.tcx;
|
||||
|
||||
if !region_vars.tcx.sess.debugging_opt(config::PRINT_REGION_GRAPH) {
|
||||
if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//! Used by `rustc` when loading a plugin, or a crate with exported macros.
|
||||
|
||||
use session::Session;
|
||||
use metadata::creader::CrateReader;
|
||||
use metadata::creader::{CrateOrString, CrateReader};
|
||||
use plugin::registry::Registry;
|
||||
|
||||
use std::mem;
|
||||
|
@ -44,11 +44,11 @@ pub struct Plugins {
|
|||
pub registrars: Vec<PluginRegistrar>,
|
||||
}
|
||||
|
||||
struct PluginLoader<'a> {
|
||||
pub struct PluginLoader<'a> {
|
||||
sess: &'a Session,
|
||||
span_whitelist: HashSet<Span>,
|
||||
reader: CrateReader<'a>,
|
||||
plugins: Plugins,
|
||||
pub plugins: Plugins,
|
||||
}
|
||||
|
||||
impl<'a> PluginLoader<'a> {
|
||||
|
@ -67,7 +67,7 @@ impl<'a> PluginLoader<'a> {
|
|||
|
||||
/// Read plugin metadata and dynamically load registrar functions.
|
||||
pub fn load_plugins(sess: &Session, krate: &ast::Crate,
|
||||
addl_plugins: Option<Plugins>) -> Plugins {
|
||||
addl_plugins: Option<Vec<String>>) -> Plugins {
|
||||
let mut loader = PluginLoader::new(sess);
|
||||
|
||||
// We need to error on `#[macro_use] extern crate` when it isn't at the
|
||||
|
@ -79,19 +79,14 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
|
|||
|
||||
visit::walk_crate(&mut loader, krate);
|
||||
|
||||
let mut plugins = loader.plugins;
|
||||
|
||||
match addl_plugins {
|
||||
Some(addl_plugins) => {
|
||||
// Add in the additional plugins requested by the frontend
|
||||
let Plugins { macros: addl_macros, registrars: addl_registrars } = addl_plugins;
|
||||
plugins.macros.extend(addl_macros.into_iter());
|
||||
plugins.registrars.extend(addl_registrars.into_iter());
|
||||
if let Some(plugins) = addl_plugins {
|
||||
for plugin in plugins.iter() {
|
||||
loader.load_plugin(CrateOrString::Str(plugin.as_slice()),
|
||||
None, None, None)
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
|
||||
return plugins;
|
||||
return loader.plugins;
|
||||
}
|
||||
|
||||
// note that macros aren't expanded yet, and therefore macros can't add plugins.
|
||||
|
@ -160,22 +155,39 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, Some(reexport))
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, _: &ast::Mac) {
|
||||
// bummer... can't see plugins inside macros.
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PluginLoader<'a> {
|
||||
pub fn load_plugin<'b>(&mut self,
|
||||
c: CrateOrString<'b>,
|
||||
plugin_attr: Option<P<ast::MetaItem>>,
|
||||
macro_selection: Option<HashSet<token::InternedString>>,
|
||||
reexport: Option<HashSet<token::InternedString>>) {
|
||||
let mut macros = vec![];
|
||||
let mut registrar = None;
|
||||
|
||||
let load_macros = match macro_selection.as_ref() {
|
||||
Some(sel) => sel.len() != 0 || reexport.len() != 0,
|
||||
None => true,
|
||||
let load_macros = match (macro_selection.as_ref(), reexport.as_ref()) {
|
||||
(Some(sel), Some(re)) => sel.len() != 0 || re.len() != 0,
|
||||
_ => true,
|
||||
};
|
||||
let load_registrar = plugin_attr.is_some();
|
||||
|
||||
if load_macros && !self.span_whitelist.contains(&vi.span) {
|
||||
self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
|
||||
the crate root");
|
||||
}
|
||||
if let CrateOrString::Krate(vi) = c {
|
||||
if load_macros && !self.span_whitelist.contains(&vi.span) {
|
||||
self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
|
||||
the crate root");
|
||||
}
|
||||
}
|
||||
|
||||
if load_macros || load_registrar {
|
||||
let pmd = self.reader.read_plugin_metadata(vi);
|
||||
let pmd = self.reader.read_plugin_metadata(c);
|
||||
if load_macros {
|
||||
macros = pmd.exported_macros();
|
||||
}
|
||||
|
@ -190,12 +202,16 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
|
|||
None => true,
|
||||
Some(sel) => sel.contains(&name),
|
||||
};
|
||||
def.export = reexport.contains(&name);
|
||||
def.export = if let Some(ref re) = reexport {
|
||||
re.contains(&name)
|
||||
} else {
|
||||
false // Don't reexport macros from crates loaded from the command line
|
||||
};
|
||||
self.plugins.macros.push(def);
|
||||
}
|
||||
|
||||
if let Some((lib, symbol)) = registrar {
|
||||
let fun = self.dylink_registrar(vi, lib, symbol);
|
||||
let fun = self.dylink_registrar(c, lib, symbol);
|
||||
self.plugins.registrars.push(PluginRegistrar {
|
||||
fun: fun,
|
||||
args: plugin_attr.unwrap(),
|
||||
|
@ -203,16 +219,9 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, _: &ast::Mac) {
|
||||
// bummer... can't see plugins inside macros.
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PluginLoader<'a> {
|
||||
// Dynamically link a registrar function into the compiler process.
|
||||
fn dylink_registrar(&mut self,
|
||||
vi: &ast::ViewItem,
|
||||
fn dylink_registrar<'b>(&mut self,
|
||||
c: CrateOrString<'b>,
|
||||
path: Path,
|
||||
symbol: String) -> PluginRegistrarFun {
|
||||
// Make sure the path contains a / or the linker will search for it.
|
||||
|
@ -223,7 +232,13 @@ impl<'a> PluginLoader<'a> {
|
|||
// this is fatal: there are almost certainly macros we need
|
||||
// inside this crate, so continue would spew "macro undefined"
|
||||
// errors
|
||||
Err(err) => self.sess.span_fatal(vi.span, &err[])
|
||||
Err(err) => {
|
||||
if let CrateOrString::Krate(cr) = c {
|
||||
self.sess.span_fatal(cr.span, &err[])
|
||||
} else {
|
||||
self.sess.fatal(&err[])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
|
@ -233,7 +248,13 @@ impl<'a> PluginLoader<'a> {
|
|||
mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
|
||||
}
|
||||
// again fatal if we can't register macros
|
||||
Err(err) => self.sess.span_fatal(vi.span, &err[])
|
||||
Err(err) => {
|
||||
if let CrateOrString::Krate(cr) = c {
|
||||
self.sess.span_fatal(cr.span, &err[])
|
||||
} else {
|
||||
self.sess.fatal(&err[])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Intentionally leak the dynamic library. We can't ever unload it
|
||||
|
|
|
@ -99,7 +99,7 @@ pub struct Options {
|
|||
pub parse_only: bool,
|
||||
pub no_trans: bool,
|
||||
pub no_analysis: bool,
|
||||
pub debugging_opts: u64,
|
||||
pub debugging_opts: DebuggingOptions,
|
||||
/// Whether to write dependency files. It's (enabled, optional filename).
|
||||
pub write_dependency_info: (bool, Option<Path>),
|
||||
pub prints: Vec<PrintRequest>,
|
||||
|
@ -224,7 +224,7 @@ pub fn basic_options() -> Options {
|
|||
parse_only: false,
|
||||
no_trans: false,
|
||||
no_analysis: false,
|
||||
debugging_opts: 0,
|
||||
debugging_opts: basic_debugging_options(),
|
||||
write_dependency_info: (false, None),
|
||||
prints: Vec::new(),
|
||||
cg: basic_codegen_options(),
|
||||
|
@ -257,103 +257,6 @@ pub enum CrateType {
|
|||
CrateTypeStaticlib,
|
||||
}
|
||||
|
||||
macro_rules! debugging_opts {
|
||||
([ $opt:ident ] $cnt:expr ) => (
|
||||
pub const $opt: u64 = 1 << $cnt;
|
||||
);
|
||||
([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
|
||||
pub const $opt: u64 = 1 << $cnt;
|
||||
debugging_opts! { [ $($rest),* ] $cnt + 1 }
|
||||
)
|
||||
}
|
||||
|
||||
debugging_opts! {
|
||||
[
|
||||
VERBOSE,
|
||||
TIME_PASSES,
|
||||
COUNT_LLVM_INSNS,
|
||||
TIME_LLVM_PASSES,
|
||||
TRANS_STATS,
|
||||
ASM_COMMENTS,
|
||||
NO_VERIFY,
|
||||
BORROWCK_STATS,
|
||||
NO_LANDING_PADS,
|
||||
DEBUG_LLVM,
|
||||
COUNT_TYPE_SIZES,
|
||||
META_STATS,
|
||||
GC,
|
||||
PRINT_LINK_ARGS,
|
||||
PRINT_LLVM_PASSES,
|
||||
AST_JSON,
|
||||
AST_JSON_NOEXPAND,
|
||||
LS,
|
||||
SAVE_ANALYSIS,
|
||||
PRINT_MOVE_FRAGMENTS,
|
||||
FLOWGRAPH_PRINT_LOANS,
|
||||
FLOWGRAPH_PRINT_MOVES,
|
||||
FLOWGRAPH_PRINT_ASSIGNS,
|
||||
FLOWGRAPH_PRINT_ALL,
|
||||
PRINT_REGION_GRAPH,
|
||||
PARSE_ONLY,
|
||||
NO_TRANS,
|
||||
NO_ANALYSIS,
|
||||
UNSTABLE_OPTIONS,
|
||||
PRINT_ENUM_SIZES
|
||||
]
|
||||
0
|
||||
}
|
||||
|
||||
pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
|
||||
vec![("verbose", "in general, enable more debug printouts", VERBOSE),
|
||||
("time-passes", "measure time of each rustc pass", TIME_PASSES),
|
||||
("count-llvm-insns", "count where LLVM \
|
||||
instrs originate", COUNT_LLVM_INSNS),
|
||||
("time-llvm-passes", "measure time of each LLVM pass",
|
||||
TIME_LLVM_PASSES),
|
||||
("trans-stats", "gather trans statistics", TRANS_STATS),
|
||||
("asm-comments", "generate comments into the assembly (may change behavior)",
|
||||
ASM_COMMENTS),
|
||||
("no-verify", "skip LLVM verification", NO_VERIFY),
|
||||
("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
|
||||
("no-landing-pads", "omit landing pads for unwinding",
|
||||
NO_LANDING_PADS),
|
||||
("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
|
||||
("count-type-sizes", "count the sizes of aggregate types",
|
||||
COUNT_TYPE_SIZES),
|
||||
("meta-stats", "gather metadata statistics", META_STATS),
|
||||
("print-link-args", "Print the arguments passed to the linker",
|
||||
PRINT_LINK_ARGS),
|
||||
("gc", "Garbage collect shared data (experimental)", GC),
|
||||
("print-llvm-passes",
|
||||
"Prints the llvm optimization passes being run",
|
||||
PRINT_LLVM_PASSES),
|
||||
("ast-json", "Print the AST as JSON and halt", AST_JSON),
|
||||
("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
|
||||
("ls", "List the symbols defined by a library crate", LS),
|
||||
("save-analysis", "Write syntax and type analysis information \
|
||||
in addition to normal output", SAVE_ANALYSIS),
|
||||
("print-move-fragments", "Print out move-fragment data for every fn",
|
||||
PRINT_MOVE_FRAGMENTS),
|
||||
("flowgraph-print-loans", "Include loan analysis data in \
|
||||
--pretty flowgraph output", FLOWGRAPH_PRINT_LOANS),
|
||||
("flowgraph-print-moves", "Include move analysis data in \
|
||||
--pretty flowgraph output", FLOWGRAPH_PRINT_MOVES),
|
||||
("flowgraph-print-assigns", "Include assignment analysis data in \
|
||||
--pretty flowgraph output", FLOWGRAPH_PRINT_ASSIGNS),
|
||||
("flowgraph-print-all", "Include all dataflow analysis data in \
|
||||
--pretty flowgraph output", FLOWGRAPH_PRINT_ALL),
|
||||
("print-region-graph", "Prints region inference graph. \
|
||||
Use with RUST_REGION_GRAPH=help for more info",
|
||||
PRINT_REGION_GRAPH),
|
||||
("parse-only", "Parse only; do not compile, assemble, or link", PARSE_ONLY),
|
||||
("no-trans", "Run all passes except translation; no output", NO_TRANS),
|
||||
("no-analysis", "Parse and expand the source, but run no analysis and",
|
||||
NO_ANALYSIS),
|
||||
("unstable-options", "Adds unstable command line options to rustc interface",
|
||||
UNSTABLE_OPTIONS),
|
||||
("print-enum-sizes", "Print the size of enums and their variants", PRINT_ENUM_SIZES),
|
||||
]
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Passes {
|
||||
|
@ -370,7 +273,7 @@ impl Passes {
|
|||
}
|
||||
}
|
||||
|
||||
/// Declare a macro that will define all CodegenOptions fields and parsers all
|
||||
/// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all
|
||||
/// at once. The goal of this macro is to define an interface that can be
|
||||
/// programmatically used by the option parser in order to initialize the struct
|
||||
/// without hardcoding field names all over the place.
|
||||
|
@ -380,23 +283,70 @@ impl Passes {
|
|||
/// cgsetters module which is a bunch of generated code to parse an option into
|
||||
/// its respective field in the struct. There are a few hand-written parsers for
|
||||
/// parsing specific types of values in this module.
|
||||
macro_rules! cgoptions {
|
||||
($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
|
||||
macro_rules! options {
|
||||
($struct_name:ident, $setter_name:ident, $defaultfn:ident,
|
||||
$buildfn:ident, $prefix:expr, $outputname:expr,
|
||||
$stat:ident, $mod_desc:ident, $mod_set:ident,
|
||||
$($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
|
||||
(
|
||||
#[derive(Clone)]
|
||||
pub struct CodegenOptions { $(pub $opt: $t),* }
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub struct $struct_name { $(pub $opt: $t),* }
|
||||
|
||||
pub fn basic_codegen_options() -> CodegenOptions {
|
||||
CodegenOptions { $($opt: $init),* }
|
||||
pub fn $defaultfn() -> $struct_name {
|
||||
$struct_name { $($opt: $init),* }
|
||||
}
|
||||
|
||||
pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
|
||||
pub const CG_OPTIONS: &'static [(&'static str, CodegenSetter,
|
||||
Option<&'static str>, &'static str)] =
|
||||
&[ $( (stringify!($opt), cgsetters::$opt, cg_type_descs::$parse, $desc) ),* ];
|
||||
pub fn $buildfn(matches: &getopts::Matches) -> $struct_name
|
||||
{
|
||||
let mut op = $defaultfn();
|
||||
for option in matches.opt_strs($prefix).into_iter() {
|
||||
let mut iter = option.splitn(1, '=');
|
||||
let key = iter.next().unwrap();
|
||||
let value = iter.next();
|
||||
let option_to_lookup = key.replace("-", "_");
|
||||
let mut found = false;
|
||||
for &(candidate, setter, opt_type_desc, _) in $stat.iter() {
|
||||
if option_to_lookup != candidate { continue }
|
||||
if !setter(&mut op, value) {
|
||||
match (value, opt_type_desc) {
|
||||
(Some(..), None) => {
|
||||
early_error(&format!("{} option `{}` takes no \
|
||||
value", $outputname, key)[])
|
||||
}
|
||||
(None, Some(type_desc)) => {
|
||||
early_error(&format!("{0} option `{1}` requires \
|
||||
{2} ({3} {1}=<value>)",
|
||||
$outputname, key,
|
||||
type_desc, $prefix)[])
|
||||
}
|
||||
(Some(value), Some(type_desc)) => {
|
||||
early_error(&format!("incorrect value `{}` for {} \
|
||||
option `{}` - {} was expected",
|
||||
value, $outputname,
|
||||
key, type_desc)[])
|
||||
}
|
||||
(None, None) => unreachable!()
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if !found {
|
||||
early_error(&format!("unknown codegen option: `{}`",
|
||||
key)[]);
|
||||
}
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod cg_type_descs {
|
||||
pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool;
|
||||
pub const $stat: &'static [(&'static str, $setter_name,
|
||||
Option<&'static str>, &'static str)] =
|
||||
&[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ];
|
||||
|
||||
#[allow(non_upper_case_globals, dead_code)]
|
||||
mod $mod_desc {
|
||||
pub const parse_bool: Option<&'static str> = None;
|
||||
pub const parse_opt_bool: Option<&'static str> = None;
|
||||
pub const parse_string: Option<&'static str> = Some("a string");
|
||||
|
@ -410,11 +360,12 @@ macro_rules! cgoptions {
|
|||
Some("a number");
|
||||
}
|
||||
|
||||
mod cgsetters {
|
||||
use super::{CodegenOptions, Passes, SomePasses, AllPasses};
|
||||
#[allow(dead_code)]
|
||||
mod $mod_set {
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses};
|
||||
|
||||
$(
|
||||
pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
|
||||
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
|
||||
$parse(&mut cg.$opt, v)
|
||||
}
|
||||
)*
|
||||
|
@ -506,7 +457,9 @@ macro_rules! cgoptions {
|
|||
}
|
||||
) }
|
||||
|
||||
cgoptions! {
|
||||
options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
||||
build_codegen_options, "C", "codegen",
|
||||
CG_OPTIONS, cg_type_desc, cgsetters,
|
||||
ar: Option<String> = (None, parse_opt_string,
|
||||
"tool to assemble archives with"),
|
||||
linker: Option<String> = (None, parse_opt_string,
|
||||
|
@ -562,45 +515,73 @@ cgoptions! {
|
|||
"Optimize with possible levels 0-3"),
|
||||
}
|
||||
|
||||
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
|
||||
{
|
||||
let mut cg = basic_codegen_options();
|
||||
for option in matches.opt_strs("C").into_iter() {
|
||||
let mut iter = option.splitn(1, '=');
|
||||
let key = iter.next().unwrap();
|
||||
let value = iter.next();
|
||||
let option_to_lookup = key.replace("-", "_");
|
||||
let mut found = false;
|
||||
for &(candidate, setter, opt_type_desc, _) in CG_OPTIONS.iter() {
|
||||
if option_to_lookup != candidate { continue }
|
||||
if !setter(&mut cg, value) {
|
||||
match (value, opt_type_desc) {
|
||||
(Some(..), None) => {
|
||||
early_error(&format!("codegen option `{}` takes no \
|
||||
value", key)[])
|
||||
}
|
||||
(None, Some(type_desc)) => {
|
||||
early_error(&format!("codegen option `{0}` requires \
|
||||
{1} (-C {0}=<value>)",
|
||||
key, type_desc)[])
|
||||
}
|
||||
(Some(value), Some(type_desc)) => {
|
||||
early_error(&format!("incorrect value `{}` for codegen \
|
||||
option `{}` - {} was expected",
|
||||
value, key, type_desc)[])
|
||||
}
|
||||
(None, None) => unreachable!()
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if !found {
|
||||
early_error(&format!("unknown codegen option: `{}`",
|
||||
key)[]);
|
||||
}
|
||||
}
|
||||
return cg;
|
||||
|
||||
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
build_debugging_options, "Z", "debugging",
|
||||
DB_OPTIONS, db_type_desc, dbsetters,
|
||||
verbose: bool = (false, parse_bool,
|
||||
"in general, enable more debug printouts"),
|
||||
time_passes: bool = (false, parse_bool,
|
||||
"measure time of each rustc pass"),
|
||||
count_llvm_insns: bool = (false, parse_bool,
|
||||
"count where LLVM instrs originate"),
|
||||
time_llvm_passes: bool = (false, parse_bool,
|
||||
"measure time of each LLVM pass"),
|
||||
trans_stats: bool = (false, parse_bool,
|
||||
"gather trans statistics"),
|
||||
asm_comments: bool = (false, parse_bool,
|
||||
"generate comments into the assembly (may change behavior)"),
|
||||
no_verify: bool = (false, parse_bool,
|
||||
"skip LLVM verification"),
|
||||
borrowck_stats: bool = (false, parse_bool,
|
||||
"gather borrowck statistics"),
|
||||
no_landing_pads: bool = (false, parse_bool,
|
||||
"omit landing pads for unwinding"),
|
||||
debug_llvm: bool = (false, parse_bool,
|
||||
"enable debug output from LLVM"),
|
||||
count_type_sizes: bool = (false, parse_bool,
|
||||
"count the sizes of aggregate types"),
|
||||
meta_stats: bool = (false, parse_bool,
|
||||
"gather metadata statistics"),
|
||||
print_link_args: bool = (false, parse_bool,
|
||||
"Print the arguments passed to the linker"),
|
||||
gc: bool = (false, parse_bool,
|
||||
"Garbage collect shared data (experimental)"),
|
||||
print_llvm_passes: bool = (false, parse_bool,
|
||||
"Prints the llvm optimization passes being run"),
|
||||
ast_json: bool = (false, parse_bool,
|
||||
"Print the AST as JSON and halt"),
|
||||
ast_json_noexpand: bool = (false, parse_bool,
|
||||
"Print the pre-expansion AST as JSON and halt"),
|
||||
ls: bool = (false, parse_bool,
|
||||
"List the symbols defined by a library crate"),
|
||||
save_analysis: bool = (false, parse_bool,
|
||||
"Write syntax and type analysis information in addition to normal output"),
|
||||
print_move_fragments: bool = (false, parse_bool,
|
||||
"Print out move-fragment data for every fn"),
|
||||
flowgraph_print_loans: bool = (false, parse_bool,
|
||||
"Include loan analysis data in --pretty flowgraph output"),
|
||||
flowgraph_print_moves: bool = (false, parse_bool,
|
||||
"Include move analysis data in --pretty flowgraph output"),
|
||||
flowgraph_print_assigns: bool = (false, parse_bool,
|
||||
"Include assignment analysis data in --pretty flowgraph output"),
|
||||
flowgraph_print_all: bool = (false, parse_bool,
|
||||
"Include all dataflow analysis data in --pretty flowgraph output"),
|
||||
print_region_graph: bool = (false, parse_bool,
|
||||
"Prints region inference graph. \
|
||||
Use with RUST_REGION_GRAPH=help for more info"),
|
||||
parse_only: bool = (false, parse_bool,
|
||||
"Parse only; do not compile, assemble, or link"),
|
||||
no_trans: bool = (false, parse_bool,
|
||||
"Run all passes except translation; no output"),
|
||||
no_analysis: bool = (false, parse_bool,
|
||||
"Parse and expand the source, but run no analysis"),
|
||||
extra_plugins: Vec<String> = (Vec::new(), parse_list,
|
||||
"load extra plugins"),
|
||||
unstable_options: bool = (false, parse_bool,
|
||||
"Adds unstable command line options to rustc interface"),
|
||||
print_enum_sizes: bool = (false, parse_bool,
|
||||
"Print the size of enums and their variants"),
|
||||
}
|
||||
|
||||
pub fn default_lib_output() -> CrateType {
|
||||
|
@ -878,52 +859,36 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
}
|
||||
}
|
||||
|
||||
let mut debugging_opts = 0;
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
let debug_map = debugging_opts_map();
|
||||
for debug_flag in debug_flags.iter() {
|
||||
let mut this_bit = 0;
|
||||
for &(name, _, bit) in debug_map.iter() {
|
||||
if name == *debug_flag {
|
||||
this_bit = bit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if this_bit == 0 {
|
||||
early_error(&format!("unknown debug flag: {}",
|
||||
*debug_flag)[])
|
||||
}
|
||||
debugging_opts |= this_bit;
|
||||
}
|
||||
let debugging_opts = build_debugging_options(matches);
|
||||
|
||||
let parse_only = if matches.opt_present("parse-only") {
|
||||
// FIXME(acrichto) remove this eventually
|
||||
early_warn("--parse-only is deprecated in favor of -Z parse-only");
|
||||
true
|
||||
} else {
|
||||
debugging_opts & PARSE_ONLY != 0
|
||||
debugging_opts.parse_only
|
||||
};
|
||||
let no_trans = if matches.opt_present("no-trans") {
|
||||
// FIXME(acrichto) remove this eventually
|
||||
early_warn("--no-trans is deprecated in favor of -Z no-trans");
|
||||
true
|
||||
} else {
|
||||
debugging_opts & NO_TRANS != 0
|
||||
debugging_opts.no_trans
|
||||
};
|
||||
let no_analysis = if matches.opt_present("no-analysis") {
|
||||
// FIXME(acrichto) remove this eventually
|
||||
early_warn("--no-analysis is deprecated in favor of -Z no-analysis");
|
||||
true
|
||||
} else {
|
||||
debugging_opts & NO_ANALYSIS != 0
|
||||
debugging_opts.no_analysis
|
||||
};
|
||||
|
||||
if debugging_opts & DEBUG_LLVM != 0 {
|
||||
if debugging_opts.debug_llvm {
|
||||
unsafe { llvm::LLVMSetDebug(1); }
|
||||
}
|
||||
|
||||
let mut output_types = Vec::new();
|
||||
if !parse_only && !no_trans {
|
||||
if !debugging_opts.parse_only && !no_trans {
|
||||
let unparsed_output_types = matches.opt_strs("emit");
|
||||
for unparsed_output_type in unparsed_output_types.iter() {
|
||||
for part in unparsed_output_type.split(',') {
|
||||
|
@ -993,7 +958,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
}
|
||||
}
|
||||
};
|
||||
let gc = debugging_opts & GC != 0;
|
||||
let gc = debugging_opts.gc;
|
||||
let debuginfo = if matches.opt_present("g") {
|
||||
if matches.opt_present("debuginfo") {
|
||||
early_error("-g and --debuginfo both provided");
|
||||
|
|
|
@ -164,9 +164,6 @@ impl Session {
|
|||
pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler {
|
||||
&self.parse_sess.span_diagnostic
|
||||
}
|
||||
pub fn debugging_opt(&self, opt: u64) -> bool {
|
||||
(self.opts.debugging_opts & opt) != 0
|
||||
}
|
||||
pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
|
||||
&self.parse_sess.span_diagnostic.cm
|
||||
}
|
||||
|
@ -176,36 +173,36 @@ impl Session {
|
|||
self.span_bug(sp,
|
||||
&format!("impossible case reached: {}", msg)[]);
|
||||
}
|
||||
pub fn verbose(&self) -> bool { self.debugging_opt(config::VERBOSE) }
|
||||
pub fn time_passes(&self) -> bool { self.debugging_opt(config::TIME_PASSES) }
|
||||
pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
|
||||
pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
|
||||
pub fn count_llvm_insns(&self) -> bool {
|
||||
self.debugging_opt(config::COUNT_LLVM_INSNS)
|
||||
self.opts.debugging_opts.count_llvm_insns
|
||||
}
|
||||
pub fn count_type_sizes(&self) -> bool {
|
||||
self.debugging_opt(config::COUNT_TYPE_SIZES)
|
||||
self.opts.debugging_opts.count_type_sizes
|
||||
}
|
||||
pub fn time_llvm_passes(&self) -> bool {
|
||||
self.debugging_opt(config::TIME_LLVM_PASSES)
|
||||
self.opts.debugging_opts.time_llvm_passes
|
||||
}
|
||||
pub fn trans_stats(&self) -> bool { self.debugging_opt(config::TRANS_STATS) }
|
||||
pub fn meta_stats(&self) -> bool { self.debugging_opt(config::META_STATS) }
|
||||
pub fn asm_comments(&self) -> bool { self.debugging_opt(config::ASM_COMMENTS) }
|
||||
pub fn no_verify(&self) -> bool { self.debugging_opt(config::NO_VERIFY) }
|
||||
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(config::BORROWCK_STATS) }
|
||||
pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats }
|
||||
pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats }
|
||||
pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments }
|
||||
pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify }
|
||||
pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats }
|
||||
pub fn print_llvm_passes(&self) -> bool {
|
||||
self.debugging_opt(config::PRINT_LLVM_PASSES)
|
||||
self.opts.debugging_opts.print_llvm_passes
|
||||
}
|
||||
pub fn lto(&self) -> bool {
|
||||
self.opts.cg.lto
|
||||
}
|
||||
pub fn no_landing_pads(&self) -> bool {
|
||||
self.debugging_opt(config::NO_LANDING_PADS)
|
||||
self.opts.debugging_opts.no_landing_pads
|
||||
}
|
||||
pub fn unstable_options(&self) -> bool {
|
||||
self.debugging_opt(config::UNSTABLE_OPTIONS)
|
||||
self.opts.debugging_opts.unstable_options
|
||||
}
|
||||
pub fn print_enum_sizes(&self) -> bool {
|
||||
self.debugging_opt(config::PRINT_ENUM_SIZES)
|
||||
self.opts.debugging_opts.print_enum_sizes
|
||||
}
|
||||
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
||||
match self.opts.maybe_sysroot {
|
||||
|
|
|
@ -19,7 +19,6 @@ use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend};
|
|||
use borrowck::LoanPathElem::{LpDeref, LpInterior};
|
||||
use borrowck::move_data::{InvalidMovePathIndex};
|
||||
use borrowck::move_data::{MoveData, MovePathIndex};
|
||||
use rustc::session::config;
|
||||
use rustc::middle::ty;
|
||||
use rustc::middle::mem_categorization as mc;
|
||||
use rustc::util::ppaux::{Repr, UserString};
|
||||
|
@ -133,7 +132,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
|
|||
|
||||
let span_err =
|
||||
attrs.iter().any(|a| a.check_name("rustc_move_fragments"));
|
||||
let print = tcx.sess.debugging_opt(config::PRINT_MOVE_FRAGMENTS);
|
||||
let print = tcx.sess.opts.debugging_opts.print_move_fragments;
|
||||
|
||||
(span_err, print)
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ pub fn compile_input(sess: Session,
|
|||
input: &Input,
|
||||
outdir: &Option<Path>,
|
||||
output: &Option<Path>,
|
||||
addl_plugins: Option<Plugins>) {
|
||||
addl_plugins: Option<Vec<String>>) {
|
||||
// We need nested scopes here, because the intermediate results can keep
|
||||
// large chunks of memory alive and we want to free them as soon as
|
||||
// possible to keep the peak memory usage low
|
||||
|
@ -142,7 +142,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
|
|||
}
|
||||
});
|
||||
|
||||
if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 {
|
||||
if sess.opts.debugging_opts.ast_json_noexpand {
|
||||
println!("{}", json::as_json(&krate));
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
|
|||
pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
mut krate: ast::Crate,
|
||||
crate_name: &str,
|
||||
addl_plugins: Option<Plugins>)
|
||||
addl_plugins: Option<Vec<String>>)
|
||||
-> Option<ast::Crate> {
|
||||
let time_passes = sess.time_passes();
|
||||
|
||||
|
@ -334,7 +334,7 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session,
|
|||
let map = time(sess.time_passes(), "assigning node ids and indexing ast", forest, |forest|
|
||||
ast_map::map_crate(forest, NodeIdAssigner { sess: sess }));
|
||||
|
||||
if sess.opts.debugging_opts & config::AST_JSON != 0 {
|
||||
if sess.opts.debugging_opts.ast_json {
|
||||
println!("{}", json::as_json(map.krate()));
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
|||
}
|
||||
|
||||
fn save_analysis(sess: &Session) -> bool {
|
||||
(sess.opts.debugging_opts & config::SAVE_ANALYSIS) != 0
|
||||
sess.opts.debugging_opts.save_analysis
|
||||
}
|
||||
|
||||
pub fn phase_save_analysis(sess: &Session,
|
||||
|
@ -575,7 +575,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool {
|
|||
if sess.opts.show_span.is_some() {
|
||||
return true;
|
||||
}
|
||||
return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
|
||||
return sess.opts.debugging_opts.ast_json_noexpand;
|
||||
}
|
||||
|
||||
pub fn stop_after_phase_2(sess: &Session) -> bool {
|
||||
|
@ -583,7 +583,7 @@ pub fn stop_after_phase_2(sess: &Session) -> bool {
|
|||
debug!("invoked with --no-analysis, returning early from compile_input");
|
||||
return true;
|
||||
}
|
||||
return sess.opts.debugging_opts & config::AST_JSON != 0;
|
||||
return sess.opts.debugging_opts.ast_json;
|
||||
}
|
||||
|
||||
pub fn stop_after_phase_5(sess: &Session) -> bool {
|
||||
|
|
|
@ -53,6 +53,7 @@ use rustc::session::config::{Input, PrintRequest, UnstableFeatures};
|
|||
use rustc::lint::Lint;
|
||||
use rustc::lint;
|
||||
use rustc::metadata;
|
||||
use rustc::metadata::creader::CrateOrString::Str;
|
||||
use rustc::DIAGNOSTICS;
|
||||
|
||||
use std::cmp::Ordering::Equal;
|
||||
|
@ -185,7 +186,8 @@ fn run_compiler(args: &[String]) {
|
|||
return;
|
||||
}
|
||||
|
||||
driver::compile_input(sess, cfg, &input, &odir, &ofile, None);
|
||||
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
|
||||
driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins));
|
||||
}
|
||||
|
||||
pub fn get_unstable_features_setting() -> UnstableFeatures {
|
||||
|
@ -378,13 +380,13 @@ Available lint options:
|
|||
|
||||
fn describe_debug_flags() {
|
||||
println!("\nAvailable debug options:\n");
|
||||
let r = config::debugging_opts_map();
|
||||
for tuple in r.iter() {
|
||||
match *tuple {
|
||||
(ref name, ref desc, _) => {
|
||||
println!(" -Z {:>20} -- {}", *name, *desc);
|
||||
}
|
||||
}
|
||||
for &(name, _, opt_type_desc, desc) in config::DB_OPTIONS.iter() {
|
||||
let (width, extra) = match opt_type_desc {
|
||||
Some(..) => (21, "=val"),
|
||||
None => (25, "")
|
||||
};
|
||||
println!(" -Z {:>width$}{} -- {}", name.replace("_", "-"),
|
||||
extra, desc, width=width);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use rustc::middle::ty;
|
|||
use rustc::middle::cfg;
|
||||
use rustc::middle::cfg::graphviz::LabelledCFG;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{self, Input};
|
||||
use rustc::session::config::Input;
|
||||
use rustc::util::ppaux;
|
||||
use rustc_borrowck as borrowck;
|
||||
use rustc_borrowck::graphviz as borrowck_dot;
|
||||
|
@ -305,19 +305,18 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> {
|
|||
}
|
||||
|
||||
fn gather_flowgraph_variants(sess: &Session) -> Vec<borrowck_dot::Variant> {
|
||||
let print_loans = config::FLOWGRAPH_PRINT_LOANS;
|
||||
let print_moves = config::FLOWGRAPH_PRINT_MOVES;
|
||||
let print_assigns = config::FLOWGRAPH_PRINT_ASSIGNS;
|
||||
let print_all = config::FLOWGRAPH_PRINT_ALL;
|
||||
let opt = |&: print_which| sess.debugging_opt(print_which);
|
||||
let print_loans = sess.opts.debugging_opts.flowgraph_print_loans;
|
||||
let print_moves = sess.opts.debugging_opts.flowgraph_print_moves;
|
||||
let print_assigns = sess.opts.debugging_opts.flowgraph_print_assigns;
|
||||
let print_all = sess.opts.debugging_opts.flowgraph_print_all;
|
||||
let mut variants = Vec::new();
|
||||
if opt(print_all) || opt(print_loans) {
|
||||
if print_all || print_loans {
|
||||
variants.push(borrowck_dot::Loans);
|
||||
}
|
||||
if opt(print_all) || opt(print_moves) {
|
||||
if print_all || print_moves {
|
||||
variants.push(borrowck_dot::Moves);
|
||||
}
|
||||
if opt(print_all) || opt(print_assigns) {
|
||||
if print_all || print_assigns {
|
||||
variants.push(borrowck_dot::Assigns);
|
||||
}
|
||||
variants
|
||||
|
|
|
@ -99,7 +99,7 @@ fn test_env<F>(source_string: &str,
|
|||
{
|
||||
let mut options =
|
||||
config::basic_options();
|
||||
options.debugging_opts |= config::VERBOSE;
|
||||
options.debugging_opts.verbose = true;
|
||||
let codemap =
|
||||
CodeMap::new();
|
||||
let diagnostic_handler =
|
||||
|
|
|
@ -778,7 +778,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
|
|||
cmd.arg("-lcompiler-rt");
|
||||
}
|
||||
|
||||
if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
|
||||
if sess.opts.debugging_opts.print_link_args {
|
||||
println!("{}", &cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -715,7 +715,7 @@ pub fn run_passes(sess: &Session,
|
|||
|
||||
cmd.args(&sess.target.target.options.post_link_args[]);
|
||||
|
||||
if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
|
||||
if sess.opts.debugging_opts.print_link_args {
|
||||
println!("{}", &cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,11 @@ pub struct Span {
|
|||
|
||||
pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION };
|
||||
|
||||
// Generic span to be used for code originating from the command line
|
||||
pub const COMMAND_LINE_SP: Span = Span { lo: BytePos(0),
|
||||
hi: BytePos(0),
|
||||
expn_id: COMMAND_LINE_EXPN };
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
|
||||
pub struct Spanned<T> {
|
||||
pub node: T,
|
||||
|
@ -235,6 +240,8 @@ pub struct ExpnInfo {
|
|||
pub struct ExpnId(u32);
|
||||
|
||||
pub const NO_EXPANSION: ExpnId = ExpnId(-1);
|
||||
// For code appearing from the command line
|
||||
pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(-2);
|
||||
|
||||
impl ExpnId {
|
||||
pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
|
||||
|
|
|
@ -13,7 +13,7 @@ pub use self::RenderSpan::*;
|
|||
pub use self::ColorConfig::*;
|
||||
use self::Destination::*;
|
||||
|
||||
use codemap::{Pos, Span};
|
||||
use codemap::{COMMAND_LINE_SP, Pos, Span};
|
||||
use codemap;
|
||||
use diagnostics;
|
||||
|
||||
|
@ -368,6 +368,9 @@ impl Emitter for EmitterWriter {
|
|||
cmsp: Option<(&codemap::CodeMap, Span)>,
|
||||
msg: &str, code: Option<&str>, lvl: Level) {
|
||||
let error = match cmsp {
|
||||
Some((cm, COMMAND_LINE_SP)) => emit(self, cm,
|
||||
FileLine(COMMAND_LINE_SP),
|
||||
msg, code, lvl, false),
|
||||
Some((cm, sp)) => emit(self, cm, FullSpan(sp), msg, code, lvl, false),
|
||||
None => print_diagnostic(self, "", lvl, msg, code),
|
||||
};
|
||||
|
@ -390,8 +393,11 @@ impl Emitter for EmitterWriter {
|
|||
fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
|
||||
msg: &str, code: Option<&str>, lvl: Level, custom: bool) -> io::IoResult<()> {
|
||||
let sp = rsp.span();
|
||||
let ss = cm.span_to_string(sp);
|
||||
let lines = cm.span_to_lines(sp);
|
||||
let ss = if sp == COMMAND_LINE_SP {
|
||||
"<command line option>".to_string()
|
||||
} else {
|
||||
cm.span_to_string(sp)
|
||||
};
|
||||
if custom {
|
||||
// we want to tell compiletest/runtest to look at the last line of the
|
||||
// span (since `custom_highlight_lines` displays an arrow to the end of
|
||||
|
@ -400,15 +406,17 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
|
|||
let ses = cm.span_to_string(span_end);
|
||||
try!(print_diagnostic(dst, &ses[], lvl, msg, code));
|
||||
if rsp.is_full_span() {
|
||||
try!(custom_highlight_lines(dst, cm, sp, lvl, lines));
|
||||
try!(custom_highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp)));
|
||||
}
|
||||
} else {
|
||||
try!(print_diagnostic(dst, &ss[], lvl, msg, code));
|
||||
if rsp.is_full_span() {
|
||||
try!(highlight_lines(dst, cm, sp, lvl, lines));
|
||||
try!(highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp)));
|
||||
}
|
||||
}
|
||||
try!(print_macro_backtrace(dst, cm, sp));
|
||||
if sp != COMMAND_LINE_SP {
|
||||
try!(print_macro_backtrace(dst, cm, sp));
|
||||
}
|
||||
match code {
|
||||
Some(code) =>
|
||||
match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//~^^^^^^^^^^ ERROR overflow
|
||||
// ignore-command-line: See https://github.com/rust-lang/rust/issues/20747
|
||||
//
|
||||
// We also get a second error message at the top of file (dummy
|
||||
// span). This is not helpful, but also kind of annoying to prevent,
|
||||
|
|
21
src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs
Normal file
21
src/test/run-pass-fulldeps/lint-plugin-cmdline-load.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
// aux-build:lint_plugin_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-pretty: Random space appears with the pretty test
|
||||
// compile-flags: -Z extra-plugins=lint_plugin_test
|
||||
|
||||
fn lintme() { } //~ WARNING item is named 'lintme'
|
||||
|
||||
#[allow(test_lint)]
|
||||
pub fn main() {
|
||||
fn lintme() { }
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue