diff --git a/mk/crates.mk b/mk/crates.mk index 0437e08de28b6..032a673836f99 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -58,12 +58,13 @@ TOOLS := compiletest rustdoc rustc DEPS_core := DEPS_std := core libc native:rustrt native:compiler-rt native:backtrace native:jemalloc +DEPS_graphviz := std DEPS_green := std rand native:context_switch DEPS_rustuv := std native:uv native:uv_support DEPS_native := std DEPS_syntax := std term serialize collections log fmt_macros DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \ - collections time log + collections time log graphviz DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \ test time DEPS_flate := std native:miniz diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index b60468e85bbf1..cd9e50157f2e2 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -516,12 +516,13 @@ pub fn optgroups() -> Vec { optopt( "", "out-dir", "Write output to compiler-chosen filename in ", "DIR"), optflag("", "parse-only", "Parse only; do not compile, assemble, or link"), optflagopt("", "pretty", - "Pretty-print the input instead of compiling; - valid types are: normal (un-annotated source), - expanded (crates expanded), - typed (crates expanded, with type annotations), - or identified (fully parenthesized, - AST nodes and blocks with IDs)", "TYPE"), + "Pretty-print the input instead of compiling; + valid types are: `normal` (un-annotated source), + `expanded` (crates expanded), + `typed` (crates expanded, with type annotations), + `expanded,identified` (fully parenthesized, AST nodes with IDs), or + `flowgraph=` (graphviz formatted flowgraph for node)", + "TYPE"), optflagopt("", "dep-info", "Output dependency info to after compiling, \ in a format suitable for use by Makefiles", "FILENAME"), diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 51bdf9ef9edd5..1cdabe68626fc 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -11,12 +11,15 @@ use back::link; use driver::session::Session; -use driver::config; +use driver::{config, PpMode}; +use driver::PpmFlowGraph; // FIXME (#14221). use front; use lib::llvm::{ContextRef, ModuleRef}; use metadata::common::LinkMeta; use metadata::creader; use metadata::creader::Loader; +use middle::cfg; +use middle::cfg::graphviz::LabelledCFG; use middle::{trans, freevars, kind, ty, typeck, lint, reachable}; use middle::dependency_format; use middle; @@ -24,6 +27,8 @@ use util::common::time; use util::ppaux; use util::nodemap::{NodeSet}; +use dot = graphviz; + use serialize::{json, Encodable}; use std::io; @@ -581,14 +586,14 @@ impl pprust::PpAnn for TypedAnnotation { pub fn pretty_print_input(sess: Session, cfg: ast::CrateConfig, input: &Input, - ppm: ::driver::PpMode, + ppm: PpMode, ofile: Option) { let krate = phase_1_parse_input(&sess, cfg, input); let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem().as_slice()); let (krate, ast_map, is_expanded) = match ppm { - PpmExpanded | PpmExpandedIdentified | PpmTyped => { + PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => { let loader = &mut Loader::new(&sess); let (krate, ast_map) = phase_2_configure_and_expand(&sess, loader, @@ -643,6 +648,18 @@ pub fn pretty_print_input(sess: Session, &annotation, is_expanded) } + PpmFlowGraph(nodeid) => { + let ast_map = ast_map.expect("--pretty flowgraph missing ast_map"); + let node = ast_map.find(nodeid).unwrap_or_else(|| { + fail!("--pretty flowgraph=id couldn't find id: {}", id) + }); + let block = match node { + syntax::ast_map::NodeBlock(block) => block, + _ => fail!("--pretty=flowgraph needs block, got {:?}", node) + }; + let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map); + print_flowgraph(analysis, block, out) + } _ => { pprust::print_crate(sess.codemap(), sess.diagnostic(), @@ -657,6 +674,32 @@ pub fn pretty_print_input(sess: Session, } +fn print_flowgraph(analysis: CrateAnalysis, + block: ast::P, + mut out: W) -> io::IoResult<()> { + let ty_cx = &analysis.ty_cx; + let cfg = cfg::CFG::new(ty_cx, block); + let lcfg = LabelledCFG { ast_map: &ty_cx.map, + cfg: &cfg, + name: format!("block{}", block.id).to_strbuf(), }; + debug!("cfg: {:?}", cfg); + let r = dot::render(&lcfg, &mut out); + return expand_err_details(r); + + fn expand_err_details(r: io::IoResult<()>) -> io::IoResult<()> { + r.map_err(|ioerr| { + let orig_detail = ioerr.detail.clone(); + let m = "graphviz::render failed"; + io::IoError { + detail: Some(match orig_detail { + None => m.into_owned(), Some(d) => format!("{}: {}", m, d) + }), + ..ioerr + } + }) + } +} + pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { // If we're generating a test executable, then ignore all other output diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index db91303b53316..093486e0aa1ac 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -284,20 +284,32 @@ pub enum PpMode { PpmExpanded, PpmTyped, PpmIdentified, - PpmExpandedIdentified + PpmExpandedIdentified, + PpmFlowGraph(ast::NodeId), } pub fn parse_pretty(sess: &Session, name: &str) -> PpMode { - match name { - "normal" => PpmNormal, - "expanded" => PpmExpanded, - "typed" => PpmTyped, - "expanded,identified" => PpmExpandedIdentified, - "identified" => PpmIdentified, + let mut split = name.splitn('=', 1); + let first = split.next().unwrap(); + let opt_second = split.next(); + match (opt_second, first) { + (None, "normal") => PpmNormal, + (None, "expanded") => PpmExpanded, + (None, "typed") => PpmTyped, + (None, "expanded,identified") => PpmExpandedIdentified, + (None, "identified") => PpmIdentified, + (Some(s), "flowgraph") => { + match from_str(s) { + Some(id) => PpmFlowGraph(id), + None => sess.fatal(format!("`pretty flowgraph=` needs \ + an integer ; got {}", s)) + } + } _ => { - sess.fatal("argument to `pretty` must be one of `normal`, \ - `expanded`, `typed`, `identified`, \ - or `expanded,identified`"); + sess.fatal(format!( + "argument to `pretty` must be one of `normal`, \ + `expanded`, `flowgraph=`, `typed`, `identified`, \ + or `expanded,identified`; got {}", name)); } } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d3b5fb1ca470c..18c59a955b527 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -33,6 +33,7 @@ This API is completely unstable and subject to change. extern crate flate; extern crate arena; +extern crate graphviz; extern crate syntax; extern crate serialize; extern crate sync; @@ -122,4 +123,3 @@ pub mod lib { pub fn main() { std::os::set_exit_status(driver::main_args(std::os::args().as_slice())); } - diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index d631340fc4e31..c9c397d3d6121 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -18,10 +18,10 @@ use util::nodemap::NodeMap; struct CFGBuilder<'a> { tcx: &'a ty::ctxt, - method_map: typeck::MethodMap, exit_map: NodeMap, graph: CFGGraph, - loop_scopes: Vec , + fn_exit: CFGIndex, + loop_scopes: Vec, } struct LoopScope { @@ -31,22 +31,35 @@ struct LoopScope { } pub fn construct(tcx: &ty::ctxt, - method_map: typeck::MethodMap, blk: &ast::Block) -> CFG { + let mut graph = graph::Graph::new(); + let entry = add_initial_dummy_node(&mut graph); + + // `fn_exit` is target of return exprs, which lies somewhere + // outside input `blk`. (Distinguishing `fn_exit` and `block_exit` + // also resolves chicken-and-egg problem that arises if you try to + // have return exprs jump to `block_exit` during construction.) + let fn_exit = add_initial_dummy_node(&mut graph); + let block_exit; + let mut cfg_builder = CFGBuilder { exit_map: NodeMap::new(), - graph: graph::Graph::new(), + graph: graph, + fn_exit: fn_exit, tcx: tcx, - method_map: method_map, loop_scopes: Vec::new() }; - let entry = cfg_builder.add_node(0, []); - let exit = cfg_builder.block(blk, entry); + block_exit = cfg_builder.block(blk, entry); + cfg_builder.add_contained_edge(block_exit, fn_exit); let CFGBuilder {exit_map, graph, ..} = cfg_builder; CFG {exit_map: exit_map, graph: graph, entry: entry, - exit: exit} + exit: fn_exit} +} + +fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex { + g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID }) } impl<'a> CFGBuilder<'a> { @@ -327,24 +340,25 @@ impl<'a> CFGBuilder<'a> { ast::ExprRet(v) => { let v_exit = self.opt_expr(v, pred); - let loop_scope = *self.loop_scopes.get(0); - self.add_exiting_edge(expr, v_exit, - loop_scope, loop_scope.break_index); - self.add_node(expr.id, []) + let b = self.add_node(expr.id, [v_exit]); + self.add_returning_edge(expr, b); + self.add_node(ast::DUMMY_NODE_ID, []) } ast::ExprBreak(label) => { let loop_scope = self.find_scope(expr, label); - self.add_exiting_edge(expr, pred, + let b = self.add_node(expr.id, [pred]); + self.add_exiting_edge(expr, b, loop_scope, loop_scope.break_index); - self.add_node(expr.id, []) + self.add_node(ast::DUMMY_NODE_ID, []) } ast::ExprAgain(label) => { let loop_scope = self.find_scope(expr, label); - self.add_exiting_edge(expr, pred, + let a = self.add_node(expr.id, [pred]); + self.add_exiting_edge(expr, a, loop_scope, loop_scope.continue_index); - self.add_node(expr.id, []) + self.add_node(ast::DUMMY_NODE_ID, []) } ast::ExprVec(ref elems) => { @@ -453,13 +467,16 @@ impl<'a> CFGBuilder<'a> { } fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex { - self.add_node(0, preds) + self.add_node(ast::DUMMY_NODE_ID, preds) } fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex { assert!(!self.exit_map.contains_key(&id)); let node = self.graph.add_node(CFGNodeData {id: id}); - self.exit_map.insert(id, node); + if id != ast::DUMMY_NODE_ID { + assert!(!self.exit_map.contains_key(&id)); + self.exit_map.insert(id, node); + } for &pred in preds.iter() { self.add_contained_edge(pred, node); } @@ -488,6 +505,16 @@ impl<'a> CFGBuilder<'a> { self.graph.add_edge(from_index, to_index, data); } + fn add_returning_edge(&mut self, + _from_expr: @ast::Expr, + from_index: CFGIndex) { + let mut data = CFGEdgeData {exiting_scopes: vec!() }; + for &LoopScope { loop_id: id, .. } in self.loop_scopes.iter().rev() { + data.exiting_scopes.push(id); + } + self.graph.add_edge(from_index, self.fn_exit, data); + } + fn find_scope(&self, expr: @ast::Expr, label: Option) -> LoopScope { @@ -521,6 +548,6 @@ impl<'a> CFGBuilder<'a> { fn is_method_call(&self, expr: &ast::Expr) -> bool { let method_call = typeck::MethodCall::expr(expr.id); - self.method_map.borrow().contains_key(&method_call) + self.tcx.method_map.borrow().contains_key(&method_call) } } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs new file mode 100644 index 0000000000000..b8baeefd3d02e --- /dev/null +++ b/src/librustc/middle/cfg/graphviz.rs @@ -0,0 +1,116 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// This module provides linkage between rustc::middle::graph and +/// libgraphviz traits. + +/// For clarity, rename the graphviz crate locally to dot. +use dot = graphviz; + +use syntax::ast; +use syntax::ast_map; + +use middle::cfg; + +pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); +pub type Edge<'a> = &'a cfg::CFGEdge; + +pub struct LabelledCFG<'a>{ + pub ast_map: &'a ast_map::Map, + pub cfg: &'a cfg::CFG, + pub name: StrBuf, +} + +fn replace_newline_with_backslash_l(s: StrBuf) -> StrBuf { + // Replacing newlines with \\l causes each line to be left-aligned, + // improving presentation of (long) pretty-printed expressions. + if s.as_slice().contains("\n") { + let mut s = s.replace("\n", "\\l"); + // Apparently left-alignment applies to the line that precedes + // \l, not the line that follows; so, add \l at end of string + // if not already present, ensuring last line gets left-aligned + // as well. + let mut last_two : Vec<_> = s.chars().rev().take(2).collect(); + last_two.reverse(); + if last_two.as_slice() != ['\\', 'l'] { + s = s.append("\\l"); + } + s.to_strbuf() + } else { + s + } +} + +impl<'a> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a> { + fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()) } + + fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> { + dot::Id::new(format!("N{:u}", i.node_id())) + } + + fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> { + if i == self.cfg.entry { + dot::LabelStr("entry".into_maybe_owned()) + } else if i == self.cfg.exit { + dot::LabelStr("exit".into_maybe_owned()) + } else if n.data.id == ast::DUMMY_NODE_ID { + dot::LabelStr("(dummy_node)".into_maybe_owned()) + } else { + let s = self.ast_map.node_to_str(n.data.id); + // left-aligns the lines + let s = replace_newline_with_backslash_l(s); + dot::EscStr(s.into_maybe_owned()) + } + } + + fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> { + let mut label = StrBuf::new(); + let mut put_one = false; + for (i, &node_id) in e.data.exiting_scopes.iter().enumerate() { + if put_one { + label = label.append(",\\l"); + } else { + put_one = true; + } + let s = self.ast_map.node_to_str(node_id); + // left-aligns the lines + let s = replace_newline_with_backslash_l(s); + label = label.append(format!("exiting scope_{} {}", i, s.as_slice())); + } + dot::EscStr(label.into_maybe_owned()) + } +} + +impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG { + fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { + let mut v = Vec::new(); + self.graph.each_node(|i, nd| { v.push((i, nd)); true }); + dot::maybe_owned_vec::Growable(v) + } + fn edges(&self) -> dot::Edges<'a, Edge<'a>> { + self.graph.all_edges().iter().collect() + } + fn source(&self, edge: &Edge<'a>) -> Node<'a> { + let i = edge.source(); + (i, self.graph.node(i)) + } + fn target(&self, edge: &Edge<'a>) -> Node<'a> { + let i = edge.target(); + (i, self.graph.node(i)) + } +} + +impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a> +{ + fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() } + fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() } + fn source(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) } + fn target(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) } +} diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs index 97ea996bb7e45..f0b912fb87bbf 100644 --- a/src/librustc/middle/cfg/mod.rs +++ b/src/librustc/middle/cfg/mod.rs @@ -19,25 +19,25 @@ Uses `Graph` as the underlying representation. use middle::graph; use middle::ty; -use middle::typeck; use syntax::ast; use util::nodemap::NodeMap; mod construct; +pub mod graphviz; pub struct CFG { - exit_map: NodeMap, - graph: CFGGraph, - entry: CFGIndex, - exit: CFGIndex, + pub exit_map: NodeMap, + pub graph: CFGGraph, + pub entry: CFGIndex, + pub exit: CFGIndex, } pub struct CFGNodeData { - id: ast::NodeId + pub id: ast::NodeId } pub struct CFGEdgeData { - exiting_scopes: Vec + pub exiting_scopes: Vec } pub type CFGIndex = graph::NodeIndex; @@ -55,8 +55,7 @@ pub struct CFGIndices { impl CFG { pub fn new(tcx: &ty::ctxt, - method_map: typeck::MethodMap, blk: &ast::Block) -> CFG { - construct::construct(tcx, method_map, blk) + construct::construct(tcx, blk) } } diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index 2705f9bf9bf4d..5773d0bafa1d1 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -70,10 +70,14 @@ pub static Incoming: Direction = Direction { repr: 1 }; impl NodeIndex { fn get(&self) -> uint { let NodeIndex(v) = *self; v } + /// Returns unique id (unique with respect to the graph holding associated node). + pub fn node_id(&self) -> uint { self.get() } } impl EdgeIndex { fn get(&self) -> uint { let EdgeIndex(v) = *self; v } + /// Returns unique id (unique with respect to the graph holding associated edge). + pub fn edge_id(&self) -> uint { self.get() } } impl Graph { @@ -201,39 +205,39 @@ impl Graph { /////////////////////////////////////////////////////////////////////////// // Iterating over nodes, edges - pub fn each_node(&self, f: |NodeIndex, &Node| -> bool) -> bool { + pub fn each_node<'a>(&'a self, f: |NodeIndex, &'a Node| -> bool) -> bool { //! Iterates over all edges defined in the graph. self.nodes.iter().enumerate().advance(|(i, node)| f(NodeIndex(i), node)) } - pub fn each_edge(&self, f: |EdgeIndex, &Edge| -> bool) -> bool { + pub fn each_edge<'a>(&'a self, f: |EdgeIndex, &'a Edge| -> bool) -> bool { //! Iterates over all edges defined in the graph self.edges.iter().enumerate().advance(|(i, edge)| f(EdgeIndex(i), edge)) } - pub fn each_outgoing_edge(&self, - source: NodeIndex, - f: |EdgeIndex, &Edge| -> bool) - -> bool { + pub fn each_outgoing_edge<'a>(&'a self, + source: NodeIndex, + f: |EdgeIndex, &'a Edge| -> bool) + -> bool { //! Iterates over all outgoing edges from the node `from` self.each_adjacent_edge(source, Outgoing, f) } - pub fn each_incoming_edge(&self, - target: NodeIndex, - f: |EdgeIndex, &Edge| -> bool) - -> bool { + pub fn each_incoming_edge<'a>(&'a self, + target: NodeIndex, + f: |EdgeIndex, &'a Edge| -> bool) + -> bool { //! Iterates over all incoming edges to the node `target` self.each_adjacent_edge(target, Incoming, f) } - pub fn each_adjacent_edge(&self, - node: NodeIndex, - dir: Direction, - f: |EdgeIndex, &Edge| -> bool) - -> bool { + pub fn each_adjacent_edge<'a>(&'a self, + node: NodeIndex, + dir: Direction, + f: |EdgeIndex, &'a Edge| -> bool) + -> bool { //! Iterates over all edges adjacent to the node `node` //! in the direction `dir` (either `Outgoing` or `Incoming) @@ -257,11 +261,11 @@ impl Graph { // variables or other bitsets. This method facilitates such a // computation. - pub fn iterate_until_fixed_point(&self, - op: |iter_index: uint, - edge_index: EdgeIndex, - edge: &Edge| - -> bool) { + pub fn iterate_until_fixed_point<'a>(&'a self, + op: |iter_index: uint, + edge_index: EdgeIndex, + edge: &'a Edge| + -> bool) { let mut iteration = 0; let mut changed = true; while changed { diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index bc3a0c0073f27..861caa62515b5 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -309,6 +309,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, ast_map::NodeStmt(..) | ast_map::NodeArg(..) | ast_map::NodeBlock(..) | + ast_map::NodePat(..) | ast_map::NodeLocal(..) => { ccx.sess().bug(format!("can't monomorphize a {:?}", map_node)) } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index fa4cf8e4427d0..aee5fe9ff968e 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -564,6 +564,11 @@ impl<'a> IntoMaybeOwned<'a> for ~str { fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self) } } +impl<'a> IntoMaybeOwned<'a> for StrBuf { + #[inline] + fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self.into_owned()) } +} + impl<'a> IntoMaybeOwned<'a> for &'a str { #[inline] fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 333f876e479b1..6a7b913dce406 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -103,6 +103,7 @@ pub enum Node { NodeStmt(@Stmt), NodeArg(@Pat), NodeLocal(@Pat), + NodePat(@Pat), NodeBlock(P), /// NodeStructCtor represents a tuple struct. @@ -127,6 +128,7 @@ enum MapEntry { EntryStmt(NodeId, @Stmt), EntryArg(NodeId, @Pat), EntryLocal(NodeId, @Pat), + EntryPat(NodeId, @Pat), EntryBlock(NodeId, P), EntryStructCtor(NodeId, @StructDef), EntryLifetime(NodeId, @Lifetime), @@ -154,6 +156,7 @@ impl MapEntry { EntryStmt(id, _) => id, EntryArg(id, _) => id, EntryLocal(id, _) => id, + EntryPat(id, _) => id, EntryBlock(id, _) => id, EntryStructCtor(id, _) => id, EntryLifetime(id, _) => id, @@ -172,6 +175,7 @@ impl MapEntry { EntryStmt(_, p) => NodeStmt(p), EntryArg(_, p) => NodeArg(p), EntryLocal(_, p) => NodeLocal(p), + EntryPat(_, p) => NodePat(p), EntryBlock(_, p) => NodeBlock(p), EntryStructCtor(_, p) => NodeStructCtor(p), EntryLifetime(_, p) => NodeLifetime(p), @@ -399,6 +403,7 @@ impl Map { Some(NodeExpr(expr)) => expr.span, Some(NodeStmt(stmt)) => stmt.span, Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span, + Some(NodePat(pat)) => pat.span, Some(NodeBlock(block)) => block.span, Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span, _ => fail!("node_span: could not find span for id {}", id), @@ -513,7 +518,9 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> { // Note: this is at least *potentially* a pattern... self.insert(pat.id, EntryLocal(self.parent, pat)); } - _ => {} + _ => { + self.insert(pat.id, EntryPat(self.parent, pat)); + } } pat @@ -704,6 +711,9 @@ fn node_id_to_str(map: &Map, id: NodeId) -> StrBuf { (format!("local {} (id={})", pprust::pat_to_str(pat), id)).to_strbuf() } + Some(NodePat(pat)) => { + (format!("pat {} (id={})", pprust::pat_to_str(pat), id)).to_strbuf() + } Some(NodeBlock(block)) => { (format!("block {} (id={})", pprust::block_to_str(block), id)).to_strbuf() diff --git a/src/test/run-make/graphviz-flowgraph/Makefile b/src/test/run-make/graphviz-flowgraph/Makefile new file mode 100644 index 0000000000000..fedcc89cd429f --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/Makefile @@ -0,0 +1,37 @@ +-include ../tools.mk + +FILES=f00.rs f01.rs f02.rs f03.rs f04.rs f05.rs f06.rs f07.rs \ + f08.rs f09.rs f10.rs f11.rs f12.rs f13.rs f14.rs f15.rs \ + f16.rs f17.rs f18.rs f19.rs f20.rs f21.rs f22.rs + + +# all: $(patsubst %.rs,$(TMPDIR)/%.dot,$(FILES)) $(patsubst %.rs,$(TMPDIR)/%.pp,$(FILES)) +all: $(patsubst %.rs,$(TMPDIR)/%.check,$(FILES)) + + +RUSTC_LIB=$(RUSTC) --crate-type=lib + +define FIND_LAST_BLOCK +LASTBLOCKNUM_$(1) := $(shell $(RUSTC_LIB) --pretty=expanded,identified $(1) \ + | grep block + | tail -1 + | sed -e 's@.*/\* block \([0-9]*\) \*/.*@\1@') +endef + +ifeq ($(findstring rustc,$(RUSTC)),) +$(error Must set RUSTC) +endif + +$(TMPDIR)/%.pp: %.rs + $(RUSTC_LIB) --pretty=expanded,identified $< -o $@ + +$(TMPDIR)/%.dot: %.rs + $(eval $(call FIND_LAST_BLOCK,$<)) + $(RUSTC_LIB) --pretty flowgraph=$(LASTBLOCKNUM_$<) $< -o $@.tmp + cat $@.tmp | sed -e 's@ (id=[0-9]*)@@g' \ + -e 's@\[label=""\]@@' \ + -e 's@digraph [a-zA-Z0-9_]* @digraph block @' \ + > $@ + +$(TMPDIR)/%.check: %.rs $(TMPDIR)/%.dot + diff -u $(patsubst %.rs,$(TMPDIR)/%.dot,$<) $(patsubst %.rs,%.dot-expected.dot,$<) diff --git a/src/test/run-make/graphviz-flowgraph/f00.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f00.dot-expected.dot new file mode 100644 index 0000000000000..f699771ef24c6 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f00.dot-expected.dot @@ -0,0 +1,7 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="block { }"]; + N0 -> N2; + N2 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f00.rs b/src/test/run-make/graphviz-flowgraph/f00.rs new file mode 100644 index 0000000000000..4e7fc7ea9b084 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f00.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn empty_0() { + +} diff --git a/src/test/run-make/graphviz-flowgraph/f01.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f01.dot-expected.dot new file mode 100644 index 0000000000000..9d8411cfc58df --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f01.dot-expected.dot @@ -0,0 +1,9 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 1"]; + N3[label="block { 1; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f01.rs b/src/test/run-make/graphviz-flowgraph/f01.rs new file mode 100644 index 0000000000000..231aab69e50d9 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f01.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn lit_1() { + 1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f02.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f02.dot-expected.dot new file mode 100644 index 0000000000000..ada3f091808b8 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f02.dot-expected.dot @@ -0,0 +1,9 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="local _x"]; + N3[label="block { let _x: int; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f02.rs b/src/test/run-make/graphviz-flowgraph/f02.rs new file mode 100644 index 0000000000000..3cdd73a49e18e --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f02.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn decl_x_2() { + let _x : int; +} diff --git a/src/test/run-make/graphviz-flowgraph/f03.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f03.dot-expected.dot new file mode 100644 index 0000000000000..aff430459e872 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f03.dot-expected.dot @@ -0,0 +1,13 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 3"]; + N3[label="expr 33"]; + N4[label="expr 3 + 33"]; + N5[label="block { 3 + 33; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f03.rs b/src/test/run-make/graphviz-flowgraph/f03.rs new file mode 100644 index 0000000000000..8b172c0a10512 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f03.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_add_3() { + 3 + 33; +} diff --git a/src/test/run-make/graphviz-flowgraph/f04.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f04.dot-expected.dot new file mode 100644 index 0000000000000..adcc582c73387 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f04.dot-expected.dot @@ -0,0 +1,11 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 4"]; + N3[label="local _x"]; + N4[label="block { let _x = 4; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f04.rs b/src/test/run-make/graphviz-flowgraph/f04.rs new file mode 100644 index 0000000000000..2a0ac8ac9e570 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f04.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn pat_id_4() { + let _x = 4; +} diff --git a/src/test/run-make/graphviz-flowgraph/f05.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f05.dot-expected.dot new file mode 100644 index 0000000000000..2d52c14da6246 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f05.dot-expected.dot @@ -0,0 +1,19 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 5"]; + N3[label="expr 55"]; + N4[label="expr (5, 55)"]; + N5[label="local _x"]; + N6[label="local _y"]; + N7[label="pat (_x, _y)"]; + N8[label="block { let (_x, _y) = (5, 55); }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f05.rs b/src/test/run-make/graphviz-flowgraph/f05.rs new file mode 100644 index 0000000000000..616d822bed07b --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f05.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn pat_tup_5() { + let (_x, _y) = (5, 55); +} diff --git a/src/test/run-make/graphviz-flowgraph/f06.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f06.dot-expected.dot new file mode 100644 index 0000000000000..61b40d68dd1b5 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f06.dot-expected.dot @@ -0,0 +1,15 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 6"]; + N3[label="expr S6{val: 6,}"]; + N4[label="local _x"]; + N5[label="pat S6{val: _x}"]; + N6[label="block { let S6{val: _x} = S6{val: 6,}; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f06.rs b/src/test/run-make/graphviz-flowgraph/f06.rs new file mode 100644 index 0000000000000..c914409629cb0 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f06.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S6 { val: int } +pub fn pat_struct_6() { + let S6 { val: _x } = S6{ val: 6 }; +} diff --git a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot new file mode 100644 index 0000000000000..c99af1791495f --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot @@ -0,0 +1,33 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 7"]; + N3[label="expr 77"]; + N4[label="expr 777"]; + N5[label="expr 7777"]; + N6[label="expr [7, 77, 777, 7777]"]; + N7[label="expr match [7, 77, 777, 7777] { [x, y, ..] => x + y }"]; + N8[label="local x"]; + N9[label="local y"]; + N10[label="pat .."]; + N11[label="pat [x, y, ..]"]; + N12[label="expr x"]; + N13[label="expr y"]; + N14[label="expr x + y"]; + N15[label="block { match [7, 77, 777, 7777] { [x, y, ..] => x + y }; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N8; + N8 -> N9; + N9 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N13; + N13 -> N14; + N14 -> N7; + N7 -> N15; + N15 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f07.rs b/src/test/run-make/graphviz-flowgraph/f07.rs new file mode 100644 index 0000000000000..39f71d309fdf9 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f07.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn pat_vec_7() { + match [7, 77, 777, 7777] { + [x, y, ..] => x + y + }; +} diff --git a/src/test/run-make/graphviz-flowgraph/f08.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f08.dot-expected.dot new file mode 100644 index 0000000000000..61a708cd9ccd4 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f08.dot-expected.dot @@ -0,0 +1,30 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 8"]; + N3[label="local x"]; + N4[label="local _y"]; + N5[label="expr x"]; + N6[label="expr 88"]; + N7[label="expr x > 88"]; + N8[label="expr 888"]; + N9[label="expr _y"]; + N10[label="expr _y = 888"]; + N11[label="block { _y = 888; }"]; + N12[label="expr if x > 88 { _y = 888; }"]; + N13[label="block { let x = 8; let _y; if x > 88 { _y = 888; } }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N9; + N9 -> N10; + N10 -> N11; + N7 -> N12; + N11 -> N12; + N12 -> N13; + N13 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f08.rs b/src/test/run-make/graphviz-flowgraph/f08.rs new file mode 100644 index 0000000000000..6ba7b03d54da5 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f08.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_if_onearm_8() { + let x = 8; let _y; + if x > 88 { + _y = 888; + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f09.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f09.dot-expected.dot new file mode 100644 index 0000000000000..892b9fcd841f8 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f09.dot-expected.dot @@ -0,0 +1,44 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 91"]; + N3[label="local x"]; + N4[label="local _y"]; + N5[label="expr x"]; + N6[label="expr 92"]; + N7[label="expr x > 92"]; + N8[label="expr 93"]; + N9[label="expr _y"]; + N10[label="expr _y = 93"]; + N11[label="block { _y = 93; }"]; + N12[label="expr 94"]; + N13[label="expr 95"]; + N14[label="expr 94 + 95"]; + N15[label="expr _y"]; + N16[label="expr _y = 94 + 95"]; + N17[label="block { _y = 94 + 95; }"]; + N18[label="expr { _y = 94 + 95; }"]; + N19[label="expr if x > 92 { _y = 93; } else { _y = 94 + 95; }"]; + N20[label="block { let x = 91; let _y; if x > 92 { _y = 93; } else { _y = 94 + 95; } }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N9; + N9 -> N10; + N10 -> N11; + N7 -> N12; + N12 -> N13; + N13 -> N14; + N14 -> N15; + N15 -> N16; + N16 -> N17; + N17 -> N18; + N11 -> N19; + N18 -> N19; + N19 -> N20; + N20 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f09.rs b/src/test/run-make/graphviz-flowgraph/f09.rs new file mode 100644 index 0000000000000..a78ccb8a93741 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f09.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_if_twoarm_9() { + let x = 91; let _y; + if x > 92 { + _y = 93; + } else { + _y = 94+95; + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot new file mode 100644 index 0000000000000..2cef122104eda --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot @@ -0,0 +1,30 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 10"]; + N3[label="local mut x"]; + N4[label="(dummy_node)"]; + N5[label="expr x"]; + N6[label="expr 0"]; + N7[label="expr x > 0"]; + N8[label="expr while x > 0 { x -= 1; }"]; + N9[label="expr 1"]; + N10[label="expr x"]; + N11[label="expr x -= 1"]; + N12[label="block { x -= 1; }"]; + N13[label="block { let mut x = 10; while x > 0 { x -= 1; } }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N8; + N7 -> N9; + N9 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N4; + N8 -> N13; + N13 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f10.rs b/src/test/run-make/graphviz-flowgraph/f10.rs new file mode 100644 index 0000000000000..0ca7cc5ee86bd --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f10.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_while_10() { + let mut x = 10; + while x > 0 { + x -= 1; + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f11.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f11.dot-expected.dot new file mode 100644 index 0000000000000..59d65e5b8b7fc --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f11.dot-expected.dot @@ -0,0 +1,25 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 11"]; + N3[label="local mut _x"]; + N4[label="(dummy_node)"]; + N5[label="expr loop { _x -= 1; }"]; + N6[label="expr 1"]; + N7[label="expr _x"]; + N8[label="expr _x -= 1"]; + N9[label="block { _x -= 1; }"]; + N10[label="expr \"unreachable\""]; + N11[label="block { let mut _x = 11; loop { _x -= 1; } \"unreachable\"; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N9; + N9 -> N4; + N5 -> N10; + N10 -> N11; + N11 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f11.rs b/src/test/run-make/graphviz-flowgraph/f11.rs new file mode 100644 index 0000000000000..d0f3452119e16 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f11.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_loop_11() { + let mut _x = 11; + loop { + _x -= 1; + } + "unreachable"; +} diff --git a/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot new file mode 100644 index 0000000000000..9c0f25d5bece5 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot @@ -0,0 +1,40 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 12"]; + N3[label="local mut x"]; + N4[label="(dummy_node)"]; + N5[label="expr loop { x -= 1; if x == 2 { break ; \"unreachable\"; } }"]; + N6[label="expr 1"]; + N7[label="expr x"]; + N8[label="expr x -= 1"]; + N9[label="expr x"]; + N10[label="expr 2"]; + N11[label="expr x == 2"]; + N12[label="expr break"]; + N13[label="(dummy_node)"]; + N14[label="expr \"unreachable\""]; + N15[label="block { break ; \"unreachable\"; }"]; + N16[label="expr if x == 2 { break ; \"unreachable\"; }"]; + N17[label="block { x -= 1; if x == 2 { break ; \"unreachable\"; } }"]; + N18[label="block { let mut x = 12; loop { x -= 1; if x == 2 { break ; \"unreachable\"; } } }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N9; + N9 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N5[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 2 { break ; \"unreachable\"; },\lexiting scope_4 block { x -= 1; if x == 2 { break ; \"unreachable\"; } }"]; + N13 -> N14; + N14 -> N15; + N11 -> N16; + N15 -> N16; + N16 -> N17; + N17 -> N4; + N5 -> N18; + N18 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f12.rs b/src/test/run-make/graphviz-flowgraph/f12.rs new file mode 100644 index 0000000000000..90b146340b6f5 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f12.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_loop_12() { + let mut x = 12; + loop { + x -= 1; + if x == 2 { break; "unreachable"; } + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot new file mode 100644 index 0000000000000..2be43dcaa7b66 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot @@ -0,0 +1,44 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr E13b"]; + N3[label="expr 13"]; + N4[label="expr E13b(13)"]; + N5[label="local x"]; + N6[label="local _y"]; + N7[label="expr x"]; + N8[label="expr match x { E13a => _y = 1, E13b(v) => _y = v + 1 }"]; + N9[label="local E13a"]; + N10[label="expr 1"]; + N11[label="expr _y"]; + N12[label="expr _y = 1"]; + N13[label="local v"]; + N14[label="pat E13b(v)"]; + N15[label="expr v"]; + N16[label="expr 1"]; + N17[label="expr v + 1"]; + N18[label="expr _y"]; + N19[label="expr _y = v + 1"]; + N20[label="block {\l let x = E13b(13);\l let _y;\l match x { E13a => _y = 1, E13b(v) => _y = v + 1 }\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N9; + N9 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N8; + N7 -> N13; + N13 -> N14; + N14 -> N15; + N15 -> N16; + N16 -> N17; + N17 -> N18; + N18 -> N19; + N19 -> N8; + N8 -> N20; + N20 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f13.rs b/src/test/run-make/graphviz-flowgraph/f13.rs new file mode 100644 index 0000000000000..0817a3210ce42 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f13.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum E13 { E13a, E13b(int) } +pub fn expr_match_13() { + let x = E13b(13); let _y; + match x { + E13a => _y = 1, + E13b(v) => _y = v + 1, + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f14.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f14.dot-expected.dot new file mode 100644 index 0000000000000..0fa4e9b44de34 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f14.dot-expected.dot @@ -0,0 +1,28 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 14"]; + N3[label="local x"]; + N4[label="expr x"]; + N5[label="expr 1"]; + N6[label="expr x > 1"]; + N7[label="expr return"]; + N8[label="(dummy_node)"]; + N9[label="expr \"unreachable\""]; + N10[label="block { return; \"unreachable\"; }"]; + N11[label="expr if x > 1 { return; \"unreachable\"; }"]; + N12[label="block { let x = 14; if x > 1 { return; \"unreachable\"; } }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N1; + N8 -> N9; + N9 -> N10; + N6 -> N11; + N10 -> N11; + N11 -> N12; + N12 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f14.rs b/src/test/run-make/graphviz-flowgraph/f14.rs new file mode 100644 index 0000000000000..98ff095c8317c --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f14.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_ret_14() { + let x = 14; + if x > 1 { + return; + "unreachable"; + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot new file mode 100644 index 0000000000000..f0278fba311e6 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot @@ -0,0 +1,79 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 15"]; + N3[label="local mut x"]; + N4[label="expr 151"]; + N5[label="local mut y"]; + N6[label="(dummy_node)"]; + N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l }\l"]; + N8[label="(dummy_node)"]; + N9[label="expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l"]; + N10[label="expr x"]; + N11[label="expr 1"]; + N12[label="expr x == 1"]; + N13[label="expr break \'outer"]; + N14[label="(dummy_node)"]; + N15[label="expr \"unreachable\""]; + N16[label="block { break \'outer ; \"unreachable\" }"]; + N17[label="expr if x == 1 { break \'outer ; \"unreachable\" }"]; + N18[label="expr y"]; + N19[label="expr 2"]; + N20[label="expr y >= 2"]; + N21[label="expr break"]; + N22[label="(dummy_node)"]; + N23[label="expr \"unreachable\""]; + N24[label="block { break ; \"unreachable\" }"]; + N25[label="expr if y >= 2 { break ; \"unreachable\" }"]; + N26[label="expr 3"]; + N27[label="expr y"]; + N28[label="expr y -= 3"]; + N29[label="block {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l}\l"]; + N30[label="expr 4"]; + N31[label="expr y"]; + N32[label="expr y -= 4"]; + N33[label="expr 5"]; + N34[label="expr x"]; + N35[label="expr x -= 5"]; + N36[label="block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l}\l"]; + N37[label="block {\l let mut x = 15;\l let mut y = 151;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l }\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N8; + N8 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N13; + N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\" },\lexiting scope_3 expr if x == 1 { break \'outer ; \"unreachable\" },\lexiting scope_4 stmt if x == 1 { break \'outer ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l}\l"]; + N14 -> N15; + N15 -> N16; + N12 -> N17; + N16 -> N17; + N17 -> N18; + N18 -> N19; + N19 -> N20; + N20 -> N21; + N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\" },\lexiting scope_3 expr if y >= 2 { break ; \"unreachable\" },\lexiting scope_4 stmt if y >= 2 { break ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { break \'outer ; \"unreachable\" }\l if y >= 2 { break ; \"unreachable\" }\l y -= 3;\l}\l"]; + N22 -> N23; + N23 -> N24; + N20 -> N25; + N24 -> N25; + N25 -> N26; + N26 -> N27; + N27 -> N28; + N28 -> N29; + N29 -> N8; + N9 -> N30; + N30 -> N31; + N31 -> N32; + N32 -> N33; + N33 -> N34; + N34 -> N35; + N35 -> N36; + N36 -> N6; + N7 -> N37; + N37 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f15.rs b/src/test/run-make/graphviz-flowgraph/f15.rs new file mode 100644 index 0000000000000..44c038d643bad --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f15.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_break_label_15() { + let mut x = 15; + let mut y = 151; + 'outer: loop { + 'inner: loop { + if x == 1 { + break 'outer; + "unreachable" + } + if y >= 2 { + break; + "unreachable" + } + y -= 3; + } + y -= 4; + x -= 5; + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot new file mode 100644 index 0000000000000..3f999ae378142 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot @@ -0,0 +1,81 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 16"]; + N3[label="local mut x"]; + N4[label="expr 16"]; + N5[label="local mut y"]; + N6[label="(dummy_node)"]; + N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l }\l"]; + N8[label="(dummy_node)"]; + N9[label="expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l"]; + N10[label="expr x"]; + N11[label="expr 1"]; + N12[label="expr x == 1"]; + N13[label="expr continue \'outer"]; + N14[label="(dummy_node)"]; + N15[label="expr \"unreachable\""]; + N16[label="block { continue \'outer ; \"unreachable\" }"]; + N17[label="expr if x == 1 { continue \'outer ; \"unreachable\" }"]; + N18[label="expr y"]; + N19[label="expr 1"]; + N20[label="expr y >= 1"]; + N21[label="expr break"]; + N22[label="(dummy_node)"]; + N23[label="expr \"unreachable\""]; + N24[label="block { break ; \"unreachable\" }"]; + N25[label="expr if y >= 1 { break ; \"unreachable\" }"]; + N26[label="expr 1"]; + N27[label="expr y"]; + N28[label="expr y -= 1"]; + N29[label="block {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l}\l"]; + N30[label="expr 1"]; + N31[label="expr y"]; + N32[label="expr y -= 1"]; + N33[label="expr 1"]; + N34[label="expr x"]; + N35[label="expr x -= 1"]; + N36[label="block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l}\l"]; + N37[label="expr \"unreachable\""]; + N38[label="block {\l let mut x = 16;\l let mut y = 16;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l }\l \"unreachable\";\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N8; + N8 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N13; + N13 -> N6[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\" },\lexiting scope_3 expr if x == 1 { continue \'outer ; \"unreachable\" },\lexiting scope_4 stmt if x == 1 { continue \'outer ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l }\l y -= 1;\l x -= 1;\l}\l"]; + N14 -> N15; + N15 -> N16; + N12 -> N17; + N16 -> N17; + N17 -> N18; + N18 -> N19; + N19 -> N20; + N20 -> N21; + N21 -> N9[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\" },\lexiting scope_3 expr if y >= 1 { break ; \"unreachable\" },\lexiting scope_4 stmt if y >= 1 { break ; \"unreachable\" },\lexiting scope_5 block {\l if x == 1 { continue \'outer ; \"unreachable\" }\l if y >= 1 { break ; \"unreachable\" }\l y -= 1;\l}\l"]; + N22 -> N23; + N23 -> N24; + N20 -> N25; + N24 -> N25; + N25 -> N26; + N26 -> N27; + N27 -> N28; + N28 -> N29; + N29 -> N8; + N9 -> N30; + N30 -> N31; + N31 -> N32; + N32 -> N33; + N33 -> N34; + N34 -> N35; + N35 -> N36; + N36 -> N6; + N7 -> N37; + N37 -> N38; + N38 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f16.rs b/src/test/run-make/graphviz-flowgraph/f16.rs new file mode 100644 index 0000000000000..f4f23a65c9350 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f16.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_continue_label_16() { + let mut x = 16; + let mut y = 16; + 'outer: loop { + 'inner: loop { + if x == 1 { + continue 'outer; + "unreachable" + } + if y >= 1 { + break; + "unreachable" + } + y -= 1; + } + y -= 1; + x -= 1; + } + "unreachable"; +} diff --git a/src/test/run-make/graphviz-flowgraph/f17.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f17.dot-expected.dot new file mode 100644 index 0000000000000..e9bccdab81be1 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f17.dot-expected.dot @@ -0,0 +1,17 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 1"]; + N3[label="expr 7"]; + N4[label="expr 17"]; + N5[label="expr [1, 7, 17]"]; + N6[label="local _v"]; + N7[label="block { let _v = [1, 7, 17]; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f17.rs b/src/test/run-make/graphviz-flowgraph/f17.rs new file mode 100644 index 0000000000000..23f5bb8a1eb17 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f17.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_vec_17() { + let _v = [1, 7, 17]; +} diff --git a/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot new file mode 100644 index 0000000000000..6345b4effaf1e --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot @@ -0,0 +1,17 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr inner"]; + N3[label="expr inner"]; + N4[label="expr 18"]; + N5[label="expr inner(18)"]; + N6[label="expr inner(inner(18))"]; + N7[label="block {\l fn inner(x: int) -> int { x + x }\l inner(inner(18));\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f18.rs b/src/test/run-make/graphviz-flowgraph/f18.rs new file mode 100644 index 0000000000000..0ace542b8f5db --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f18.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_call_18() { + fn inner(x:int) -> int { x + x } + inner(inner(18)); +} diff --git a/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot new file mode 100644 index 0000000000000..5fad18536e593 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot @@ -0,0 +1,19 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 19"]; + N3[label="expr S19{x: 19,}"]; + N4[label="local s"]; + N5[label="expr s"]; + N6[label="expr s.inner()"]; + N7[label="expr s.inner().inner()"]; + N8[label="block {\l struct S19 {\l x: int,\l }\l impl S19 {\l fn inner(self) -> S19 { S19{x: self.x + self.x,} }\l }\l let s = S19{x: 19,};\l s.inner().inner();\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f19.rs b/src/test/run-make/graphviz-flowgraph/f19.rs new file mode 100644 index 0000000000000..092f6890a152a --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f19.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_method_call_19() { + struct S19 { x: int } + impl S19 { fn inner(self) -> S19 { S19 { x: self.x + self.x } } } + let s = S19 { x: 19 }; + s.inner().inner(); +} diff --git a/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot new file mode 100644 index 0000000000000..593ad6f91ea5c --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot @@ -0,0 +1,23 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 2"]; + N3[label="expr 0"]; + N4[label="expr 20"]; + N5[label="expr [2, 0, 20]"]; + N6[label="local v"]; + N7[label="expr v"]; + N8[label="expr 20"]; + N9[label="expr v[20]"]; + N10[label="block { let v = [2, 0, 20]; v[20]; }"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N7; + N7 -> N8; + N8 -> N9; + N9 -> N10; + N10 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f20.rs b/src/test/run-make/graphviz-flowgraph/f20.rs new file mode 100644 index 0000000000000..d7349932355b1 --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f20.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn expr_index_20() { + let v = [2, 0, 20]; + v[20]; +} diff --git a/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot new file mode 100644 index 0000000000000..0798c4a01c05a --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot @@ -0,0 +1,75 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 15"]; + N3[label="local mut x"]; + N4[label="expr 151"]; + N5[label="local mut y"]; + N6[label="(dummy_node)"]; + N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l }\l"]; + N8[label="(dummy_node)"]; + N9[label="expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l"]; + N10[label="expr x"]; + N11[label="expr 1"]; + N12[label="expr x == 1"]; + N13[label="expr break \'outer"]; + N14[label="(dummy_node)"]; + N15[label="expr \"unreachable\""]; + N16[label="block { break \'outer ; \"unreachable\"; }"]; + N17[label="expr if x == 1 { break \'outer ; \"unreachable\"; }"]; + N18[label="expr y"]; + N19[label="expr 2"]; + N20[label="expr y >= 2"]; + N21[label="expr return"]; + N22[label="(dummy_node)"]; + N23[label="expr \"unreachable\""]; + N24[label="block { return; \"unreachable\"; }"]; + N25[label="expr if y >= 2 { return; \"unreachable\"; }"]; + N26[label="expr 3"]; + N27[label="expr y"]; + N28[label="expr y -= 3"]; + N29[label="expr 5"]; + N30[label="expr x"]; + N31[label="expr x -= 5"]; + N32[label="block {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l}\l"]; + N33[label="expr \"unreachable\""]; + N34[label="block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l}\l"]; + N35[label="block {\l let mut x = 15;\l let mut y = 151;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l }\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N8; + N8 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N13; + N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1 { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1 { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l}\l"]; + N14 -> N15; + N15 -> N16; + N12 -> N17; + N16 -> N17; + N17 -> N18; + N18 -> N19; + N19 -> N20; + N20 -> N21; + N21 -> N1[label="exiting scope_0 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l,\lexiting scope_1 expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l y -= 3;\l x -= 5;\l }\l \"unreachable\";\l }\l"]; + N22 -> N23; + N23 -> N24; + N20 -> N25; + N24 -> N25; + N25 -> N26; + N26 -> N27; + N27 -> N28; + N28 -> N29; + N29 -> N30; + N30 -> N31; + N31 -> N32; + N32 -> N8; + N9 -> N33; + N33 -> N34; + N34 -> N6; + N7 -> N35; + N35 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f21.rs b/src/test/run-make/graphviz-flowgraph/f21.rs new file mode 100644 index 0000000000000..70083ed8312cb --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f21.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_break_label_21() { + let mut x = 15; + let mut y = 151; + 'outer: loop { + 'inner: loop { + if x == 1 { + break 'outer; + "unreachable"; + } + if y >= 2 { + return; + "unreachable"; + } + y -= 3; + x -= 5; + } + "unreachable"; + } +} diff --git a/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot new file mode 100644 index 0000000000000..9ad731bc756bf --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot @@ -0,0 +1,77 @@ +digraph block { + N0[label="entry"]; + N1[label="exit"]; + N2[label="expr 15"]; + N3[label="local mut x"]; + N4[label="expr 151"]; + N5[label="local mut y"]; + N6[label="(dummy_node)"]; + N7[label="expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l }\l"]; + N8[label="(dummy_node)"]; + N9[label="expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l"]; + N10[label="expr x"]; + N11[label="expr 1"]; + N12[label="expr x == 1"]; + N13[label="expr continue \'outer"]; + N14[label="(dummy_node)"]; + N15[label="expr \"unreachable\""]; + N16[label="block { continue \'outer ; \"unreachable\"; }"]; + N17[label="expr if x == 1 { continue \'outer ; \"unreachable\"; }"]; + N18[label="expr y"]; + N19[label="expr 2"]; + N20[label="expr y >= 2"]; + N21[label="expr return"]; + N22[label="(dummy_node)"]; + N23[label="expr \"unreachable\""]; + N24[label="block { return; \"unreachable\"; }"]; + N25[label="expr if y >= 2 { return; \"unreachable\"; }"]; + N26[label="expr 1"]; + N27[label="expr x"]; + N28[label="expr x -= 1"]; + N29[label="expr 3"]; + N30[label="expr y"]; + N31[label="expr y -= 3"]; + N32[label="block {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l}\l"]; + N33[label="expr \"unreachable\""]; + N34[label="block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l}\l"]; + N35[label="expr \"unreachable\""]; + N36[label="block {\l let mut x = 15;\l let mut y = 151;\l \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l }\l \"unreachable\";\l}\l"]; + N0 -> N2; + N2 -> N3; + N3 -> N4; + N4 -> N5; + N5 -> N6; + N6 -> N8; + N8 -> N10; + N10 -> N11; + N11 -> N12; + N12 -> N13; + N13 -> N6[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1 { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1 { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l}\l"]; + N14 -> N15; + N15 -> N16; + N12 -> N17; + N16 -> N17; + N17 -> N18; + N18 -> N19; + N19 -> N20; + N20 -> N21; + N21 -> N1[label="exiting scope_0 expr \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l,\lexiting scope_1 expr \'outer:\l loop {\l \'inner:\l loop {\l if x == 1 { continue \'outer ; \"unreachable\"; }\l if y >= 2 { return; \"unreachable\"; }\l x -= 1;\l y -= 3;\l }\l \"unreachable\";\l }\l"]; + N22 -> N23; + N23 -> N24; + N20 -> N25; + N24 -> N25; + N25 -> N26; + N26 -> N27; + N27 -> N28; + N28 -> N29; + N29 -> N30; + N30 -> N31; + N31 -> N32; + N32 -> N8; + N9 -> N33; + N33 -> N34; + N34 -> N6; + N7 -> N35; + N35 -> N36; + N36 -> N1; +} diff --git a/src/test/run-make/graphviz-flowgraph/f22.rs b/src/test/run-make/graphviz-flowgraph/f22.rs new file mode 100644 index 0000000000000..b35aac9ec422e --- /dev/null +++ b/src/test/run-make/graphviz-flowgraph/f22.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unreachable_code)] +pub fn expr_break_label_21() { + let mut x = 15; + let mut y = 151; + 'outer: loop { + 'inner: loop { + if x == 1 { + continue 'outer; + "unreachable"; + } + if y >= 2 { + return; + "unreachable"; + } + x -= 1; + y -= 3; + } + "unreachable"; + } + "unreachable"; +}