]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #14234 : alexcrichton/rust/rollup, r=alexcrichton
authorbors <bors@rust-lang.org>
Thu, 15 May 2014 22:56:54 +0000 (15:56 -0700)
committerbors <bors@rust-lang.org>
Thu, 15 May 2014 22:56:54 +0000 (15:56 -0700)
Let's try this again!

95 files changed:
Makefile.in
mk/crates.mk
mk/docs.mk
mk/tests.mk
src/doc/rust.md
src/libcore/cell.rs
src/libcore/cmp.rs
src/libcore/default.rs
src/libcore/lib.rs
src/libcore/owned.rs [deleted file]
src/libcore/unit.rs [deleted file]
src/libgreen/sched.rs
src/libnative/io/file_unix.rs
src/libnative/io/file_win32.rs
src/librlibc/lib.rs [new file with mode: 0644]
src/librustc/back/link.rs
src/librustc/driver/config.rs
src/librustc/driver/driver.rs
src/librustc/driver/mod.rs
src/librustc/lib.rs
src/librustc/lib/llvm.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/cfg/graphviz.rs [new file with mode: 0644]
src/librustc/middle/cfg/mod.rs
src/librustc/middle/graph.rs
src/librustc/middle/lint.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/monomorphize.rs
src/librustdoc/clean.rs
src/librustuv/file.rs
src/librustuv/lib.rs
src/librustuv/uvio.rs
src/libstd/bitflags.rs
src/libstd/io/buffered.rs
src/libstd/io/flate.rs [deleted file]
src/libstd/io/tempfile.rs
src/libstd/lib.rs
src/libstd/rt/local.rs
src/libstd/rt/thread.rs
src/libstd/str.rs
src/libstd/unstable/mod.rs
src/libstd/vec.rs
src/libsyntax/ast_map.rs
src/rustllvm/PassWrapper.cpp
src/snapshots.txt
src/test/bench/shootout-mandelbrot.rs
src/test/run-make/graphviz-flowgraph/Makefile [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f00.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f00.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f01.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f01.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f02.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f02.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f03.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f03.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f04.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f04.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f05.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f05.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f06.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f06.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f07.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f08.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f08.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f09.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f09.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f10.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f10.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f11.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f11.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f12.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f13.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f14.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f14.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f15.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f16.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f17.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f17.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f18.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f19.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f20.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f21.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f22.rs [new file with mode: 0644]
src/test/run-pass/foreign-call-no-runtime.rs
src/test/run-pass/tempfile.rs

index c0e1973e95e59038da25441e125095d1fbc1b10f..5d37c1da8fb3cb51453324b5c76d9aca11b4f4da 100644 (file)
@@ -68,7 +68,7 @@
 #
 #   * `TESTNAME=...` - Specify the name of tests to run
 #   * `CHECK_IGNORED=1` - Run normally-ignored tests
-#   * `NO_BENCH=1` - Don't run crate benchmarks (disable `--bench` flag)
+#   * `PLEASE_BENCH=1` - Run crate benchmarks (enable `--bench` flag)
 #
 #   * `CFG_ENABLE_VALGRIND=1` - Run tests under valgrind
 #   * `VALGRIND_COMPILE=1` - Run the compiler itself under valgrind
index 0b923cca7a2b950dff8ab40b683fd54c45246716..943cd528fcdc95b5527a2d039ff24aad40d65050 100644 (file)
 
 TARGET_CRATES := libc std green rustuv native flate arena glob term semver \
                  uuid serialize sync getopts collections num test time rand \
-                workcache url log regex graphviz core
+                workcache url log regex graphviz core rlibc
 HOST_CRATES := syntax rustc rustdoc fourcc hexfloat regex_macros fmt_macros
 CRATES := $(TARGET_CRATES) $(HOST_CRATES)
 TOOLS := compiletest rustdoc rustc
 
 DEPS_core :=
+DEPS_rlibc :=
 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
@@ -98,6 +100,7 @@ TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs
 TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
 
 ONLY_RLIB_core := 1
+ONLY_RLIB_rlibc := 1
 
 ################################################################################
 # You should not need to edit below this line
index 40c2440c0c07a524d519e9f8d22c3496367ec184..4d00223fca88045e871e1f9493a8972324059db2 100644 (file)
@@ -30,7 +30,7 @@ DOCS := index intro tutorial guide-ffi guide-macros guide-lifetimes \
        guide-tasks guide-container guide-pointers guide-testing \
        guide-runtime complement-bugreport complement-cheatsheet \
        complement-lang-faq complement-project-faq rust rustdoc \
-       guide-unsafe not_found
+       guide-unsafe
 
 PDF_DOCS := tutorial rust
 
@@ -42,10 +42,11 @@ L10N_LANGS := ja
 # Generally no need to edit below here.
 
 # The options are passed to the documentation generators.
-RUSTDOC_HTML_OPTS = --markdown-css rust.css \
-       --markdown-before-content=doc/version_info.html \
+RUSTDOC_HTML_OPTS_NO_CSS = --markdown-before-content=doc/version_info.html \
        --markdown-in-header=doc/favicon.inc --markdown-after-content=doc/footer.inc
 
+RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css
+
 PANDOC_BASE_OPTS := --standalone --toc --number-sections
 PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --include-before-body=doc/version.tex \
        --from=markdown --include-before-body=doc/footer.tex --to=latex
@@ -152,6 +153,11 @@ doc/footer.tex: $(D)/footer.inc | doc/
        @$(call E, pandoc: $@)
        $(CFG_PANDOC) --from=html --to=latex $< --output=$@
 
+# HTML (rustdoc)
+DOC_TARGETS += doc/not_found.html
+doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/
+       $(RUSTDOC) $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css http://static.rust-lang.org/doc/master/rust.css $<
+
 define DEF_DOC
 
 # HTML (rustdoc)
index befd1a737f7e67a1a096b3c8f1fcf0a99e1ae028..8f20d55e3859cf997ee36e7dd75cd8f6042cd0eb 100644 (file)
@@ -32,7 +32,7 @@ ifdef CHECK_IGNORED
   TESTARGS += --ignored
 endif
 
-TEST_BENCH = --bench
+TEST_BENCH =
 
 # Arguments to the cfail/rfail/rpass/bench tests
 ifdef CFG_VALGRIND
@@ -40,8 +40,8 @@ ifdef CFG_VALGRIND
   TEST_BENCH =
 endif
 
-ifdef NO_BENCH
-  TEST_BENCH =
+ifdef PLEASE_BENCH
+  TEST_BENCH = --bench
 endif
 
 # Arguments to the perf tests
index f242a89784ce966c4dbcb36e76b94d78106db52d..838ddca042dfc661c2b5f70676bbdaec59659565 100644 (file)
@@ -1799,6 +1799,8 @@ type int8_t = i8;
 - `no_start` - disable linking to the `native` crate, which specifies the
   "start" language item.
 - `no_std` - disable linking to the `std` crate.
+- `no_builtins` - disable optimizing certain code patterns to invocations of
+                  library functions that are assumed to exist
 
 ### Module-only attributes
 
index 0413b31e8b76efa1694e3204a4db420fe9983150..8b3494f3127339cc83beaa7f592393a4364c5732 100644 (file)
@@ -186,6 +186,25 @@ fn deref<'a>(&'a self) -> &'a T {
     }
 }
 
+/// Copy a `Ref`.
+///
+/// The `RefCell` is already immutably borrowed, so this cannot fail.
+///
+/// A `Clone` implementation would interfere with the widespread
+/// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
+#[experimental]
+pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> {
+    // Since this Ref exists, we know the borrow flag
+    // is not set to WRITING.
+    let borrow = orig.parent.borrow.get();
+    debug_assert!(borrow != WRITING && borrow != UNUSED);
+    orig.parent.borrow.set(borrow + 1);
+
+    Ref {
+        parent: orig.parent,
+    }
+}
+
 /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
 pub struct RefMut<'b, T> {
     parent: &'b RefCell<T>
@@ -307,4 +326,19 @@ fn discard_doesnt_unborrow() {
         let _ = _b;
         let _b = x.borrow_mut();
     }
+
+    #[test]
+    fn clone_ref_updates_flag() {
+        let x = RefCell::new(0);
+        {
+            let b1 = x.borrow();
+            assert!(x.try_borrow_mut().is_none());
+            {
+                let _b2 = clone_ref(&b1);
+                assert!(x.try_borrow_mut().is_none());
+            }
+            assert!(x.try_borrow_mut().is_none());
+        }
+        assert!(x.try_borrow_mut().is_some());
+    }
 }
index 52df7e71727ee2c8baa2b4216c2a6e22237be612..bf02f053336bb9822b6189d4e565e6630a9a94f5 100644 (file)
@@ -192,7 +192,23 @@ pub fn max<T: TotalOrd>(v1: T, v2: T) -> T {
 // Implementation of Eq/TotalEq for some primitive types
 #[cfg(not(test))]
 mod impls {
-    use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering};
+    use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering, Equal};
+
+    impl Eq for () {
+        #[inline]
+        fn eq(&self, _other: &()) -> bool { true }
+        #[inline]
+        fn ne(&self, _other: &()) -> bool { false }
+    }
+    impl TotalEq for () {}
+    impl Ord for () {
+        #[inline]
+        fn lt(&self, _other: &()) -> bool { false }
+    }
+    impl TotalOrd for () {
+        #[inline]
+        fn cmp(&self, _other: &()) -> Ordering { Equal }
+    }
 
     // & pointers
     impl<'a, T: Eq> Eq for &'a T {
index af65fcc5a779da550cbf2410c9b6b732148bfe1f..50ddfcc52f7beed7c9c78ac3cc9f8a0a43416f23 100644 (file)
@@ -16,6 +16,11 @@ pub trait Default {
     fn default() -> Self;
 }
 
+impl Default for () {
+    #[inline]
+    fn default() -> () { () }
+}
+
 impl<T: Default + 'static> Default for @T {
     fn default() -> @T { @Default::default() }
 }
index 4eab7e9d45d351c2b83881ff6e8be7d95a546312..22719dc9f2d71daaf44e185b4a38f661b0c217bb 100644 (file)
@@ -18,6 +18,9 @@
 //! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
 //!   often generated by LLVM. Additionally, this library can make explicit
 //!   calls to these funcitons. Their signatures are the same as found in C.
+//!   These functions are often provided by the system libc, but can also be
+//!   provided by `librlibc` which is distributed with the standard rust
+//!   distribution.
 //!
 //! * `rust_begin_unwind` - This function takes three arguments, a
 //!   `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
 /* Core types and methods on primitives */
 
 mod unicode;
-mod unit;
 pub mod any;
 pub mod atomics;
 pub mod bool;
 pub mod str;
 pub mod tuple;
 
-#[cfg(stage0, not(test))]
-pub mod owned;
-
 // FIXME: this module should not exist. Once owned allocations are no longer a
 //        language type, this module can move outside to the owned allocation
 //        crate.
diff --git a/src/libcore/owned.rs b/src/libcore/owned.rs
deleted file mode 100644 (file)
index 3af12c5..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2012 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.
-
-//! Operations on unique pointer types
-
-use any::{Any, AnyRefExt};
-use clone::Clone;
-use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering};
-use default::Default;
-use intrinsics;
-use mem;
-use raw::TraitObject;
-use result::{Ok, Err, Result};
-
-/// A value that represents the global exchange heap. This is the default
-/// place that the `box` keyword allocates into when no place is supplied.
-///
-/// The following two examples are equivalent:
-///
-///     let foo = box(HEAP) Bar::new(...);
-///     let foo = box Bar::new(...);
-#[lang="exchange_heap"]
-pub static HEAP: () = ();
-
-/// A type that represents a uniquely-owned value.
-#[lang="owned_box"]
-pub struct Box<T>(*T);
-
-impl<T: Default> Default for Box<T> {
-    fn default() -> Box<T> { box Default::default() }
-}
-
-impl<T: Clone> Clone for Box<T> {
-    /// Return a copy of the owned box.
-    #[inline]
-    fn clone(&self) -> Box<T> { box {(**self).clone()} }
-
-    /// Perform copy-assignment from `source` by reusing the existing allocation.
-    #[inline]
-    fn clone_from(&mut self, source: &Box<T>) {
-        (**self).clone_from(&(**source));
-    }
-}
-
-// box pointers
-impl<T:Eq> Eq for Box<T> {
-    #[inline]
-    fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
-    #[inline]
-    fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
-}
-impl<T:Ord> Ord for Box<T> {
-    #[inline]
-    fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
-    #[inline]
-    fn le(&self, other: &Box<T>) -> bool { *(*self) <= *(*other) }
-    #[inline]
-    fn ge(&self, other: &Box<T>) -> bool { *(*self) >= *(*other) }
-    #[inline]
-    fn gt(&self, other: &Box<T>) -> bool { *(*self) > *(*other) }
-}
-impl<T: TotalOrd> TotalOrd for Box<T> {
-    #[inline]
-    fn cmp(&self, other: &Box<T>) -> Ordering { (**self).cmp(*other) }
-}
-impl<T: TotalEq> TotalEq for Box<T> {}
-
-/// Extension methods for an owning `Any` trait object
-pub trait AnyOwnExt {
-    /// Returns the boxed value if it is of type `T`, or
-    /// `Err(Self)` if it isn't.
-    fn move<T: 'static>(self) -> Result<Box<T>, Self>;
-}
-
-impl AnyOwnExt for Box<Any> {
-    #[inline]
-    fn move<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
-        if self.is::<T>() {
-            unsafe {
-                // Get the raw representation of the trait object
-                let to: TraitObject =
-                    *mem::transmute::<&Box<Any>, &TraitObject>(&self);
-
-                // Prevent destructor on self being run
-                intrinsics::forget(self);
-
-                // Extract the data pointer
-                Ok(mem::transmute(to.data))
-            }
-        } else {
-            Err(self)
-        }
-    }
-}
diff --git a/src/libcore/unit.rs b/src/libcore/unit.rs
deleted file mode 100644 (file)
index f55cb2d..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Functions for the unit type.
-
-#[cfg(not(test))]
-use default::Default;
-#[cfg(not(test))]
-use cmp::{Eq, Equal, Ord, Ordering, TotalEq, TotalOrd};
-
-#[cfg(not(test))]
-impl Eq for () {
-    #[inline]
-    fn eq(&self, _other: &()) -> bool { true }
-    #[inline]
-    fn ne(&self, _other: &()) -> bool { false }
-}
-
-#[cfg(not(test))]
-impl Ord for () {
-    #[inline]
-    fn lt(&self, _other: &()) -> bool { false }
-}
-
-#[cfg(not(test))]
-impl TotalOrd for () {
-    #[inline]
-    fn cmp(&self, _other: &()) -> Ordering { Equal }
-}
-
-#[cfg(not(test))]
-impl TotalEq for () {}
-
-#[cfg(not(test))]
-impl Default for () {
-    #[inline]
-    fn default() -> () { () }
-}
index 8c294fa2928f0a5e35f31e37e6becb8d3069b89b..812e998ad9d901978eba33b7c8bb1c3232077eb4 100644 (file)
@@ -1137,11 +1137,10 @@ fn test_home_sched() {
     fn test_schedule_home_states() {
         use sleeper_list::SleeperList;
         use super::{Shutdown, Scheduler, SchedHandle};
-        use std::unstable::run_in_bare_thread;
         use std::rt::thread::Thread;
         use std::sync::deque::BufferPool;
 
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let sleepers = SleeperList::new();
             let mut pool = BufferPool::new();
             let (normal_worker, normal_stealer) = pool.deque();
@@ -1260,7 +1259,7 @@ fn run(next: Box<GreenTask>) {
 
             normal_thread.join();
             special_thread.join();
-        });
+        }).join();
     }
 
     //#[test]
index c2b69483fa1e0d4e206f5de4ddb10216a155478b..046d2875d553101700a56b970ca2c6a72098e52c 100644 (file)
@@ -493,9 +493,7 @@ fn gen(_stat: &libc::stat) -> u64 { 0 }
     io::FileStat {
         size: stat.st_size as u64,
         kind: kind,
-        perm: unsafe {
-            io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
-        },
+        perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
         created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
         modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
         accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
index d721e1d67f1b99bf9d85f79c50c6868b144f3251..3222c912dd0857fe6f3afea505dd7b47c6d7eef8 100644 (file)
@@ -492,9 +492,7 @@ fn mkstat(stat: &libc::stat) -> io::FileStat {
     io::FileStat {
         size: stat.st_size as u64,
         kind: kind,
-        perm: unsafe {
-          io::FilePermission::from_bits(stat.st_mode as u32)  & io::AllPermissions
-        },
+        perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
         created: stat.st_ctime as u64,
         modified: stat.st_mtime as u64,
         accessed: stat.st_atime as u64,
diff --git a/src/librlibc/lib.rs b/src/librlibc/lib.rs
new file mode 100644 (file)
index 0000000..904fbe9
--- /dev/null
@@ -0,0 +1,99 @@
+// 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.
+
+//! A bare-metal library supplying functions rustc may lower code to
+//!
+//! This library is not intended for general use, and is superseded by a system
+//! libc if one is available. In a freestanding context, however, common
+//! functions such as memset, memcpy, etc are not implemented. This library
+//! provides an implementation of these functions which are either required by
+//! libcore or called by rustc implicitly.
+//!
+//! This library is never included by default, and must be manually included if
+//! necessary. It is an error to include this library when also linking with
+//! the system libc library.
+
+#![crate_id = "rlibc#0.11.0-pre"]
+#![license = "MIT/ASL2"]
+#![crate_type = "rlib"]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_root_url = "http://static.rust-lang.org/doc/master")]
+
+#![no_std]
+#![experimental]
+
+// This library is definining the builtin functions, so it would be a shame for
+// LLVM to optimize these function calls to themselves!
+#![no_builtins]
+
+#[cfg(test)] extern crate std;
+#[cfg(test)] extern crate native;
+
+// Require the offset intrinsics for LLVM to properly optimize the
+// implementations below. If pointer arithmetic is done through integers the
+// optimizations start to break down.
+extern "rust-intrinsic" {
+    fn offset<T>(dst: *T, offset: int) -> *T;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *u8, n: uint) -> *mut u8 {
+    let mut i = 0;
+    while i < n {
+        *(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int);
+        i += 1;
+    }
+    return dest;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn memmove(dest: *mut u8, src: *u8, n: uint) -> *mut u8 {
+    if src < dest as *u8 { // copy from end
+        let mut i = n;
+        while i != 0 {
+            i -= 1;
+            *(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int);
+        }
+    } else { // copy from beginning
+        let mut i = 0;
+        while i < n {
+            *(offset(dest as *u8, i as int) as *mut u8) = *offset(src, i as int);
+            i += 1;
+        }
+    }
+    return dest;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
+    let mut i = 0;
+    while i < n {
+        *(offset(s as *u8, i as int) as *mut u8) = c as u8;
+        i += 1;
+    }
+    return s;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn memcmp(s1: *u8, s2: *u8, n: uint) -> i32 {
+    let mut i = 0;
+    while i < n {
+        let a = *offset(s1, i as int);
+        let b = *offset(s2, i as int);
+        if a != b {
+            return (a - b) as i32
+        }
+        i += 1;
+    }
+    return 0;
+}
+
+#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows
index 4d70ecb888fdb6ec34136550b4ed33e6c90804ab..429a8f5be5eb5f54604b862465c7e1fe82e952d1 100644 (file)
@@ -212,7 +212,8 @@ pub fn run_passes(sess: &Session,
             if !sess.opts.cg.no_prepopulate_passes {
                 llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
                 llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
-                populate_llvm_passes(fpm, mpm, llmod, opt_level);
+                populate_llvm_passes(fpm, mpm, llmod, opt_level,
+                                     trans.no_builtins);
             }
 
             for pass in sess.opts.cg.passes.iter() {
@@ -264,11 +265,11 @@ pub fn run_passes(sess: &Session,
             // escape the closure itself, and the manager should only be
             // used once.
             fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
-                            f: |PassManagerRef|) {
+                            no_builtins: bool, f: |PassManagerRef|) {
                 unsafe {
                     let cpm = llvm::LLVMCreatePassManager();
                     llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
-                    llvm::LLVMRustAddLibraryInfo(cpm, llmod);
+                    llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
                     f(cpm);
                     llvm::LLVMDisposePassManager(cpm);
                 }
@@ -286,7 +287,7 @@ fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
                     }
                     OutputTypeLlvmAssembly => {
                         path.with_c_str(|output| {
-                            with_codegen(tm, llmod, |cpm| {
+                            with_codegen(tm, llmod, trans.no_builtins, |cpm| {
                                 llvm::LLVMRustPrintModule(cpm, llmod, output);
                             })
                         })
@@ -303,7 +304,7 @@ fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
                             needs_metadata = true;
                             output.temp_path(OutputTypeAssembly)
                         };
-                        with_codegen(tm, llmod, |cpm| {
+                        with_codegen(tm, llmod, trans.no_builtins, |cpm| {
                             WriteOutputFile(sess, tm, cpm, llmod, &path,
                                             lib::llvm::AssemblyFile);
                         });
@@ -321,7 +322,7 @@ fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
             time(sess.time_passes(), "codegen passes", (), |()| {
                 match object_file {
                     Some(ref path) => {
-                        with_codegen(tm, llmod, |cpm| {
+                        with_codegen(tm, llmod, trans.no_builtins, |cpm| {
                             WriteOutputFile(sess, tm, cpm, llmod, path,
                                             lib::llvm::ObjectFile);
                         });
@@ -329,7 +330,8 @@ fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
                     None => {}
                 }
                 if needs_metadata {
-                    with_codegen(tm, trans.metadata_module, |cpm| {
+                    with_codegen(tm, trans.metadata_module,
+                                 trans.no_builtins, |cpm| {
                         let out = output.temp_path(OutputTypeObject)
                                         .with_extension("metadata.o");
                         WriteOutputFile(sess, tm, cpm,
@@ -437,7 +439,8 @@ unsafe fn configure_llvm(sess: &Session) {
     unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef,
                                    mpm: lib::llvm::PassManagerRef,
                                    llmod: ModuleRef,
-                                   opt: lib::llvm::CodeGenOptLevel) {
+                                   opt: lib::llvm::CodeGenOptLevel,
+                                   no_builtins: bool) {
         // Create the PassManagerBuilder for LLVM. We configure it with
         // reasonable defaults and prepare it to actually populate the pass
         // manager.
@@ -461,7 +464,7 @@ unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef,
             }
         }
         llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
-        llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod);
+        llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
 
         // Use the builder to populate the function/module pass managers.
         llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
index e929c64e58ad44d5496cd0d12573b5538cd8fe8e..da573a014d000e827324350a5cb507bb0dc9fc3c 100644 (file)
@@ -519,12 +519,13 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
         optopt( "",  "out-dir", "Write output to compiler-chosen filename in <dir>", "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=<nodeid>` (graphviz formatted flowgraph for node)",
+                 "TYPE"),
         optflagopt("", "dep-info",
                  "Output dependency info to <filename> after compiling, \
                   in a format suitable for use by Makefiles", "FILENAME"),
index 51bdf9ef9edd58304359792ad6991d21a5964bcc..5f9fd7124a9e92289804ed8e3da117b5c3fed88d 100644 (file)
 
 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::ppaux;
 use util::nodemap::{NodeSet};
 
+use dot = graphviz;
+
 use serialize::{json, Encodable};
 
 use std::io;
@@ -356,6 +361,7 @@ pub struct CrateTranslation {
     pub metadata: Vec<u8>,
     pub reachable: Vec<StrBuf>,
     pub crate_formats: dependency_format::Dependencies,
+    pub no_builtins: bool,
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
@@ -581,14 +587,14 @@ fn post(&self,
 pub fn pretty_print_input(sess: Session,
                           cfg: ast::CrateConfig,
                           input: &Input,
-                          ppm: ::driver::PpMode,
+                          ppm: PpMode,
                           ofile: Option<Path>) {
     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 +649,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 +675,32 @@ pub fn pretty_print_input(sess: Session,
 
 }
 
+fn print_flowgraph<W:io::Writer>(analysis: CrateAnalysis,
+                                 block: ast::P<ast::Block>,
+                                 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<config::CrateType> {
     // If we're generating a test executable, then ignore all other output
index b355d474bd572a9438b5766a34f08d8e21b68214..f32a8ec7cd735ca035fe8fbccc060d794b5c2164 100644 (file)
@@ -285,20 +285,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=<nodeid>` needs \
+                                             an integer <nodeid>; 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=<nodeid>`, `typed`, `identified`, \
+                 or `expanded,identified`; got {}", name));
         }
     }
 }
index d3b5fb1ca470c4f62e97f9a962c5c7e43e2346d2..18c59a955b527a413d9e1ed4c54c0f436d106a20 100644 (file)
@@ -33,6 +33,7 @@
 
 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()));
 }
-
index 0c874bd776ed11d1fd8a7e162d4741d3354197b3..711081f46d6669703a276c2d8981881c4398b078 100644 (file)
@@ -1755,8 +1755,10 @@ pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef,
                                          PM: PassManagerRef,
                                          M: ModuleRef);
         pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
-                                             M: ModuleRef);
-        pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef);
+                                             M: ModuleRef,
+                                             DisableSimplifyLibCalls: bool);
+        pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
+                                      DisableSimplifyLibCalls: bool);
         pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
         pub fn LLVMRustWriteOutputFile(T: TargetMachineRef,
                                        PM: PassManagerRef,
index d631340fc4e31c974c1ed4bc287b2b5ed3157a7e..c9c397d3d6121141a0cc6a7dc901dfe884ff3653 100644 (file)
 
 struct CFGBuilder<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
     exit_map: NodeMap<CFGIndex>,
     graph: CFGGraph,
-    loop_scopes: Vec<LoopScope> ,
+    fn_exit: CFGIndex,
+    loop_scopes: Vec<LoopScope>,
 }
 
 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 @@ fn expr(&mut self, expr: @ast::Expr, pred: CFGIndex) -> CFGIndex {
 
             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 @@ fn straightline(&mut self,
     }
 
     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 @@ fn add_exiting_edge(&mut self,
         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<ast::Ident>) -> LoopScope {
@@ -521,6 +548,6 @@ fn find_scope(&self,
 
     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 (file)
index 0000000..b8baeef
--- /dev/null
@@ -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 <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.
+
+/// 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) }
+}
index 97ea996bb7e458e3dd53aecd37b2c375e4b38118..f0b912fb87bbff17b7f4aac7ebf31b8c90fd2efb 100644 (file)
 
 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<CFGIndex>,
-    graph: CFGGraph,
-    entry: CFGIndex,
-    exit: CFGIndex,
+    pub exit_map: NodeMap<CFGIndex>,
+    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<ast::NodeId>
+    pub exiting_scopes: Vec<ast::NodeId>
 }
 
 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)
     }
 }
index 2705f9bf9bf4dfc0e4de7cd98409a7076f981a41..5773d0bafa1d1a9e9265b22323b9300c5cfeab8a 100644 (file)
@@ -70,10 +70,14 @@ pub struct Direction { repr: uint }
 
 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<N,E> Graph<N,E> {
@@ -201,39 +205,39 @@ pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
     ///////////////////////////////////////////////////////////////////////////
     // Iterating over nodes, edges
 
-    pub fn each_node(&self, f: |NodeIndex, &Node<N>| -> bool) -> bool {
+    pub fn each_node<'a>(&'a self, f: |NodeIndex, &'a Node<N>| -> 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<E>| -> bool) -> bool {
+    pub fn each_edge<'a>(&'a self, f: |EdgeIndex, &'a Edge<E>| -> 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<E>| -> bool)
-                              -> bool {
+    pub fn each_outgoing_edge<'a>(&'a self,
+                                  source: NodeIndex,
+                                  f: |EdgeIndex, &'a Edge<E>| -> 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<E>| -> bool)
-                              -> bool {
+    pub fn each_incoming_edge<'a>(&'a self,
+                                  target: NodeIndex,
+                                  f: |EdgeIndex, &'a Edge<E>| -> 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<E>| -> bool)
-                              -> bool {
+    pub fn each_adjacent_edge<'a>(&'a self,
+                                  node: NodeIndex,
+                                  dir: Direction,
+                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
+                                  -> bool {
         //! Iterates over all edges adjacent to the node `node`
         //! in the direction `dir` (either `Outgoing` or `Incoming)
 
@@ -257,11 +261,11 @@ pub fn each_adjacent_edge(&self,
     // 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<E>|
-                                          -> bool) {
+    pub fn iterate_until_fixed_point<'a>(&'a self,
+                                         op: |iter_index: uint,
+                                              edge_index: EdgeIndex,
+                                              edge: &'a Edge<E>|
+                                              -> bool) {
         let mut iteration = 0;
         let mut changed = true;
         while changed {
index 062a7418287e3e7da0b17daabb35d5aa8fbf8240..1c24d609551ab992d7791537ff8af17a96e1f80b 100644 (file)
@@ -1050,6 +1050,7 @@ fn check_raw_ptr_deriving(cx: &mut Context, item: &ast::Item) {
 static crate_attrs: &'static [&'static str] = &[
     "crate_type", "feature", "no_start", "no_main", "no_std", "crate_id",
     "desc", "comment", "license", "copyright", // not used in rustc now
+    "no_builtins",
 ];
 
 
index 17aa0664d479410d8de9bb5bc587b6598962668a..92e3b95abadc1d34eb94c867a55c04a7a22fe0f2 100644 (file)
@@ -2226,6 +2226,7 @@ pub fn trans_crate(krate: ast::Crate,
 
     let metadata_module = ccx.metadata_llmod;
     let formats = ccx.tcx.dependency_formats.borrow().clone();
+    let no_builtins = attr::contains_name(krate.attrs.as_slice(), "no_builtins");
 
     (ccx.tcx, CrateTranslation {
         context: llcx,
@@ -2235,5 +2236,6 @@ pub fn trans_crate(krate: ast::Crate,
         metadata: metadata,
         reachable: reachable,
         crate_formats: formats,
+        no_builtins: no_builtins,
     })
 }
index bc3a0c0073f272b1d649dc39b5134990dfb94f54..861caa62515b517b0dcbe6cac2cc6f23be6145eb 100644 (file)
@@ -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))
         }
index 4439f626b2ce12a2fc9f95069bedb81f3f6c04d9..bd911f42db0fa046002ffeb8b212e123341a671f 100644 (file)
@@ -1204,7 +1204,7 @@ fn clean(&self) -> Item {
                 ForeignFunctionItem(Function {
                     decl: decl.clean(),
                     generics: generics.clean(),
-                    fn_style: ast::NormalFn,
+                    fn_style: ast::UnsafeFn,
                 })
             }
             ast::ForeignItemStatic(ref ty, mutbl) => {
index 06271e61ce7a0f9f72d4361a835ee4e3584a62da..12636a3c490ad0ca64daafe083f8ff9dea0eb5d7 100644 (file)
@@ -285,9 +285,7 @@ fn to_msec(stat: uvll::uv_timespec_t) -> u64 {
         FileStat {
             size: stat.st_size as u64,
             kind: kind,
-            perm: unsafe {
-                io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
-            },
+            perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
             created: to_msec(stat.st_birthtim),
             modified: to_msec(stat.st_mtim),
             accessed: to_msec(stat.st_atim),
index c9bff2e80bfe64f1992842f75748cb07c90f5628..53515ec58e580c53b0d5fc96c1a0fc436fc59607 100644 (file)
@@ -472,7 +472,7 @@ fn local_loop() -> &'static mut uvio::UvIoFactory {
 #[cfg(test)]
 mod test {
     use std::mem::transmute;
-    use std::unstable::run_in_bare_thread;
+    use std::rt::thread::Thread;
 
     use super::{slice_to_uv_buf, Loop};
 
@@ -496,10 +496,10 @@ fn test_slice_to_uv_buf() {
 
     #[test]
     fn loop_smoke_test() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let mut loop_ = Loop::new();
             loop_.run();
             loop_.close();
-        });
+        }).join();
     }
 }
index 1b8175448fc90be62a38d98b196220745f20073f..71589e00fc008e5f08f68877a0e750be5db757d7 100644 (file)
@@ -27,7 +27,7 @@
 use std::rt::rtio::{ProcessConfig, IoFactory, EventLoop};
 use ai = std::io::net::addrinfo;
 
-#[cfg(test)] use std::unstable::run_in_bare_thread;
+#[cfg(test)] use std::rt::thread::Thread;
 
 use super::{uv_error_to_io_error, Loop};
 
@@ -116,7 +116,7 @@ fn has_active_io(&self) -> bool {
 
 #[test]
 fn test_callback_run_once() {
-    run_in_bare_thread(proc() {
+    Thread::start(proc() {
         let mut event_loop = UvEventLoop::new();
         let mut count = 0;
         let count_ptr: *mut int = &mut count;
@@ -125,7 +125,7 @@ fn test_callback_run_once() {
         });
         event_loop.run();
         assert_eq!(count, 1);
-    });
+    }).join();
 }
 
 pub struct UvIoFactory {
index 32f9bc1173b2dec7e148fb22a049762a3e694d87..163ccd22552d36fed65495580b6c4a5c1b7798a0 100644 (file)
@@ -136,10 +136,20 @@ pub fn bits(&self) -> $T {
                 self.bits
             }
 
-            /// Convert from underlying bit representation. Unsafe because the
-            /// bits are not guaranteed to represent valid flags.
-            pub unsafe fn from_bits(bits: $T) -> $BitFlags {
-                $BitFlags { bits: bits }
+            /// Convert from underlying bit representation, unless that
+            /// representation contains bits that do not correspond to a flag.
+            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
+                if (bits & !$BitFlags::all().bits()) != 0 {
+                    ::std::option::None
+                } else {
+                    ::std::option::Some($BitFlags { bits: bits })
+                }
+            }
+
+            /// Convert from underlying bit representation, dropping any bits
+            /// that do not correspond to flags.
+            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
+                $BitFlags { bits: bits } & $BitFlags::all()
             }
 
             /// Returns `true` if no flags are currently stored.
@@ -209,6 +219,7 @@ fn not(&self) -> $BitFlags {
 
 #[cfg(test)]
 mod tests {
+    use option::{Some, None};
     use ops::{BitOr, BitAnd, Sub, Not};
 
     bitflags!(
@@ -231,9 +242,21 @@ fn test_bits(){
 
     #[test]
     fn test_from_bits() {
-        assert!(unsafe { Flags::from_bits(0x00000000) } == Flags::empty());
-        assert!(unsafe { Flags::from_bits(0x00000001) } == FlagA);
-        assert!(unsafe { Flags::from_bits(0x00000111) } == FlagABC);
+        assert!(Flags::from_bits(0) == Some(Flags::empty()));
+        assert!(Flags::from_bits(0x1) == Some(FlagA));
+        assert!(Flags::from_bits(0x10) == Some(FlagB));
+        assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
+        assert!(Flags::from_bits(0x1000) == None);
+    }
+
+    #[test]
+    fn test_from_bits_truncate() {
+        assert!(Flags::from_bits_truncate(0) == Flags::empty());
+        assert!(Flags::from_bits_truncate(0x1) == FlagA);
+        assert!(Flags::from_bits_truncate(0x10) == FlagB);
+        assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
+        assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
+        assert!(Flags::from_bits_truncate(0x1001) == FlagA);
     }
 
     #[test]
index a8e7b324bd755e3285abdc705b561fdecf9c1b70..68cbdd2e0aa4740c5c2bd457de0acba6d593075e 100644 (file)
@@ -209,7 +209,7 @@ fn flush(&mut self) -> IoResult<()> {
 impl<W: Writer> Drop for BufferedWriter<W> {
     fn drop(&mut self) {
         if self.inner.is_some() {
-            // FIXME(#12628): should this error be ignored?
+            // dtors should not fail, so we ignore a failed flush
             let _ = self.flush_buf();
         }
     }
@@ -370,6 +370,7 @@ mod test {
     use io;
     use prelude::*;
     use super::*;
+    use super::super::{IoResult, EndOfFile};
     use super::super::mem::{MemReader, MemWriter, BufReader};
     use self::test::Bencher;
     use str::StrSlice;
@@ -584,6 +585,24 @@ fn test_chars() {
         assert_eq!(it.next(), None);
     }
 
+    #[test]
+    #[should_fail]
+    fn dont_fail_in_drop_on_failed_flush() {
+        struct FailFlushWriter;
+
+        impl Writer for FailFlushWriter {
+            fn write(&mut self, _buf: &[u8]) -> IoResult<()> { Ok(()) }
+            fn flush(&mut self) -> IoResult<()> { Err(io::standard_error(EndOfFile)) }
+        }
+
+        let writer = FailFlushWriter;
+        let _writer = BufferedWriter::new(writer);
+
+        // Trigger failure. If writer fails *again* due to the flush
+        // error then the process will abort.
+        fail!();
+    }
+
     #[bench]
     fn bench_buffered_reader(b: &mut Bencher) {
         b.iter(|| {
diff --git a/src/libstd/io/flate.rs b/src/libstd/io/flate.rs
deleted file mode 100644 (file)
index 0cf00b2..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Some various other I/O types
-
-// FIXME(#3660): should move to libextra
-
-use prelude::*;
-use super::*;
-
-/// A Writer decorator that compresses using the 'deflate' scheme
-pub struct DeflateWriter<W> {
-    priv inner_writer: W
-}
-
-impl<W: Writer> DeflateWriter<W> {
-    pub fn new(inner_writer: W) -> DeflateWriter<W> {
-        DeflateWriter {
-            inner_writer: inner_writer
-        }
-    }
-}
-
-impl<W: Writer> Writer for DeflateWriter<W> {
-    fn write(&mut self, _buf: &[u8]) { fail!() }
-
-    fn flush(&mut self) { fail!() }
-}
-
-/// A Reader decorator that decompresses using the 'deflate' scheme
-pub struct InflateReader<R> {
-    priv inner_reader: R
-}
-
-impl<R: Reader> InflateReader<R> {
-    pub fn new(inner_reader: R) -> InflateReader<R> {
-        InflateReader {
-            inner_reader: inner_reader
-        }
-    }
-}
-
-impl<R: Reader> Reader for InflateReader<R> {
-    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
-}
index 8c28caa988a5c05d0671b446e3b3e3a1fcba8bcc..b4fb95c8af7702769858038a2a4180a99d561df4 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Temporary files and directories
 
-use io::fs;
+use io::{fs, IoResult};
 use io;
 use iter::{Iterator, range};
 use libc;
 use option::{Option, None, Some};
 use os;
 use path::{Path, GenericPath};
-use result::{Ok, Err, ResultUnwrap};
+use result::{Ok, Err};
 use sync::atomics;
 
 /// A wrapper for a path to temporary directory implementing automatic
 /// scope-based deletion.
 pub struct TempDir {
-    path: Option<Path>
+    path: Option<Path>,
+    disarmed: bool
 }
 
 impl TempDir {
@@ -48,7 +49,7 @@ pub fn new_in(tmpdir: &Path, suffix: &str) -> Option<TempDir> {
             let p = tmpdir.join(filename);
             match fs::mkdir(&p, io::UserRWX) {
                 Err(..) => {}
-                Ok(()) => return Some(TempDir { path: Some(p) })
+                Ok(()) => return Some(TempDir { path: Some(p), disarmed: false })
             }
         }
         None
@@ -75,15 +76,32 @@ pub fn unwrap(self) -> Path {
     pub fn path<'a>(&'a self) -> &'a Path {
         self.path.get_ref()
     }
+
+    /// Close and remove the temporary directory
+    ///
+    /// Although `TempDir` removes the directory on drop, in the destructor
+    /// any errors are ignored. To detect errors cleaning up the temporary
+    /// directory, call `close` instead.
+    pub fn close(mut self) -> IoResult<()> {
+        self.cleanup_dir()
+    }
+
+    fn cleanup_dir(&mut self) -> IoResult<()> {
+        assert!(!self.disarmed);
+        self.disarmed = true;
+        match self.path {
+            Some(ref p) => {
+                fs::rmdir_recursive(p)
+            }
+            None => Ok(())
+        }
+    }
 }
 
 impl Drop for TempDir {
     fn drop(&mut self) {
-        for path in self.path.iter() {
-            if path.exists() {
-                // FIXME: is failing the right thing to do?
-                fs::rmdir_recursive(path).unwrap();
-            }
+        if !self.disarmed {
+            let _ = self.cleanup_dir();
         }
     }
 }
index a37f9a516fdb92afda011f05a15d4869ae14ffc4..87c4ef1046f1a490405395c7431bf4789b244ec6 100644 (file)
 #[cfg(test)] pub use ops = realstd::ops;
 #[cfg(test)] pub use cmp = realstd::cmp;
 #[cfg(test)] pub use ty = realstd::ty;
-#[cfg(not(stage0), test)] pub use owned = realstd::owned;
+#[cfg(test)] pub use owned = realstd::owned;
 
 #[cfg(not(test))] pub use cmp = core::cmp;
 #[cfg(not(test))] pub use kinds = core::kinds;
 #[cfg(not(test))] pub use ops = core::ops;
 #[cfg(not(test))] pub use ty = core::ty;
 
-#[cfg(stage0, test)] pub use owned = realstd::owned;
-#[cfg(stage0, not(test))] pub use owned = core::owned;
-
 pub use core::any;
 pub use core::bool;
 pub use core::cell;
@@ -209,7 +206,7 @@ fn start(argc: int, argv: **u8) -> int {
 
 pub mod rc;
 pub mod gc;
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
 pub mod owned;
 
 /* Common traits */
index 05d1f1764b59f0d34bb8b1ae69cf0b7fc9e0d95d..9f0ed8044800cbbfec32f75954eb5ba9ae779347 100644 (file)
@@ -53,24 +53,24 @@ unsafe fn try_unsafe_borrow() -> Option<*mut Task> {
 #[cfg(test)]
 mod test {
     use option::{None, Option};
-    use unstable::run_in_bare_thread;
+    use rt::thread::Thread;
     use super::*;
     use owned::Box;
     use rt::task::Task;
 
     #[test]
     fn thread_local_task_smoke_test() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn thread_local_task_two_instances() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
             let task: Box<Task> = Local::take();
@@ -79,12 +79,12 @@ fn thread_local_task_two_instances() {
             Local::put(task);
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn borrow_smoke_test() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
 
@@ -93,12 +93,12 @@ fn borrow_smoke_test() {
             }
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn borrow_with_return() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
 
@@ -108,12 +108,12 @@ fn borrow_with_return() {
 
             let task: Box<Task> = Local::take();
             cleanup_task(task);
-        });
+        }).join();
     }
 
     #[test]
     fn try_take() {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let task = box Task::new();
             Local::put(task);
 
@@ -122,7 +122,7 @@ fn try_take() {
             assert!(u.is_none());
 
             cleanup_task(t);
-        });
+        }).join();
     }
 
     fn cleanup_task(mut t: Box<Task>) {
index 4f0d7d35ce892f4618821719cce83558fa4c36a1..e25fa4734d5cb0e06161e8daae2a6e8607264503 100644 (file)
@@ -273,13 +273,8 @@ pub unsafe fn detach(native: rust_thread) {
         assert_eq!(pthread_detach(native), 0);
     }
 
-    #[cfg(target_os = "macos")]
-    #[cfg(target_os = "android")]
     pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
 
-    #[cfg(not(target_os = "macos"), not(target_os = "android"))]
-    pub unsafe fn yield_now() { assert_eq!(pthread_yield(), 0); }
-
     // glibc >= 2.15 has a __pthread_get_minstack() function that returns
     // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
     // storage.  We need that information to avoid blowing up when a small stack
@@ -326,12 +321,7 @@ fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
         fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                        state: libc::c_int) -> libc::c_int;
         fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
-
-        #[cfg(target_os = "macos")]
-        #[cfg(target_os = "android")]
         fn sched_yield() -> libc::c_int;
-        #[cfg(not(target_os = "macos"), not(target_os = "android"))]
-        fn pthread_yield() -> libc::c_int;
     }
 }
 
index fa4cf8e4427d0473b14e10fc5ebf1f1f8f35f101..aee5fe9ff968e837e6943c247cbdeabaeed20236 100644 (file)
@@ -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) }
index 8b07850263fe85111e0dc224a9ddfce48d80d84e..f464f70772d9412e6616f21c4f3b9bf70931f9d4 100644 (file)
@@ -11,7 +11,6 @@
 #![doc(hidden)]
 
 use libc::uintptr_t;
-use kinds::Send;
 
 pub use core::finally;
 
 pub mod sync;
 pub mod mutex;
 
-/**
-
-Start a new thread outside of the current runtime context and wait
-for it to terminate.
-
-The executing thread has no access to a task pointer and will be using
-a normal large stack.
-*/
-pub fn run_in_bare_thread(f: proc():Send) {
-    use rt::thread::Thread;
-    Thread::start(f).join()
-}
-
-#[test]
-fn test_run_in_bare_thread() {
-    let i = 100;
-    run_in_bare_thread(proc() {
-        assert_eq!(i, 100);
-    });
-}
-
-#[test]
-fn test_run_in_bare_thread_exchange() {
-    // Does the exchange heap work without the runtime?
-    let i = box 100;
-    run_in_bare_thread(proc() {
-        assert!(i == box 100);
-    });
-}
-
 /// Dynamically inquire about whether we're running under V.
 /// You should usually not use this unless your test definitely
 /// can't run correctly un-altered. Valgrind is there to help
index 528ab72762aab904a695541dba25c27fc79e700b..57f8d78948fa0ac5faab057f25693e42daf2c9c4 100644 (file)
@@ -635,14 +635,14 @@ pub fn append_one(mut self, x: T) -> Vec<T> {
     /// ```
     pub fn truncate(&mut self, len: uint) {
         unsafe {
-            let mut i = len;
             // drop any extra elements
-            while i < self.len {
-                ptr::read(self.as_slice().unsafe_ref(i));
-                i += 1;
+            while len < self.len {
+                // decrement len before the read(), so a failure on Drop doesn't
+                // re-drop the just-failed value.
+                self.len -= 1;
+                ptr::read(self.as_slice().unsafe_ref(self.len));
             }
         }
-        self.len = len;
     }
 
     /// Work with `self` as a mutable slice.
@@ -1862,4 +1862,39 @@ struct Foo {
         assert_eq!(b[0].x, 42);
         assert_eq!(b[1].x, 84);
     }
+
+    #[test]
+    fn test_vec_truncate_drop() {
+        static mut drops: uint = 0;
+        struct Elem(int);
+        impl Drop for Elem {
+            fn drop(&mut self) {
+                unsafe { drops += 1; }
+            }
+        }
+
+        let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
+        assert_eq!(unsafe { drops }, 0);
+        v.truncate(3);
+        assert_eq!(unsafe { drops }, 2);
+        v.truncate(0);
+        assert_eq!(unsafe { drops }, 5);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_vec_truncate_fail() {
+        struct BadElem(int);
+        impl Drop for BadElem {
+            fn drop(&mut self) {
+                let BadElem(ref mut x) = *self;
+                if *x == 0xbadbeef {
+                    fail!("BadElem failure: 0xbadbeef")
+                }
+            }
+        }
+
+        let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
+        v.truncate(0);
+    }
 }
index 333f876e479b168a839df0f575d243b0f0a3f758..6a7b913dce406222ffd0674888170f6520290051 100644 (file)
@@ -103,6 +103,7 @@ pub enum Node {
     NodeStmt(@Stmt),
     NodeArg(@Pat),
     NodeLocal(@Pat),
+    NodePat(@Pat),
     NodeBlock(P<Block>),
 
     /// 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<Block>),
     EntryStructCtor(NodeId, @StructDef),
     EntryLifetime(NodeId, @Lifetime),
@@ -154,6 +156,7 @@ fn parent(&self) -> Option<NodeId> {
             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 @@ fn to_node(&self) -> Option<Node> {
             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 @@ pub fn span(&self, id: NodeId) -> Span {
             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 @@ fn fold_pat(&mut self, pat: @Pat) -> @Pat {
                 // 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()
index 1031f3c1570e98892444cc2a3d91d637ff565d21..64776421fa1451c122839a93926844d4b8b52087 100644 (file)
@@ -128,17 +128,27 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
 // field of a PassManagerBuilder, we expose our own method of doing so.
 extern "C" void
-LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB, LLVMModuleRef M) {
+LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
+                              LLVMModuleRef M,
+                              bool DisableSimplifyLibCalls) {
     Triple TargetTriple(unwrap(M)->getTargetTriple());
-    unwrap(PMB)->LibraryInfo = new TargetLibraryInfo(TargetTriple);
+    TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
+    if (DisableSimplifyLibCalls)
+      TLI->disableAllFunctions();
+    unwrap(PMB)->LibraryInfo = TLI;
 }
 
 // Unfortunately, the LLVM C API doesn't provide a way to create the
 // TargetLibraryInfo pass, so we use this method to do so.
 extern "C" void
-LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB, LLVMModuleRef M) {
+LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
+                       LLVMModuleRef M,
+                       bool DisableSimplifyLibCalls) {
     Triple TargetTriple(unwrap(M)->getTargetTriple());
-    unwrap(PMB)->add(new TargetLibraryInfo(TargetTriple));
+    TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
+    if (DisableSimplifyLibCalls)
+      TLI->disableAllFunctions();
+    unwrap(PMB)->add(TLI);
 }
 
 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
index e88ae02c1c65b62984578a4cfee3d4957a29bfa0..4c62d519d78122c7d0ce83c1f9d79444e84a7387 100644 (file)
@@ -1,3 +1,11 @@
+S 2014-05-15 6a2b3d1
+  freebsd-x86_64 afc98b59cb819025fecdb9d145ca4463f857a477
+  linux-i386 d6f7a404412ea34db3d19814ca21fe6fa662b02f
+  linux-x86_64 3dfb54406a7ea75565a7ea3071daad885cb91775
+  macos-i386 bebb937551d601ad908c9e4eaa196cc7a977c503
+  macos-x86_64 08346ed401ad2891c7d2ba0aac0960f6e77bb78b
+  winnt-i386 ad8e5b8292a00f60f1f7dc2e35bd18abeb5b858d
+
 S 2014-05-11 72fc4a5
   freebsd-x86_64 82db6355b0b7c8023c8845a74e2f224da2831b50
   linux-i386 91901299d5f86f5b67377d940073908a1f0e4e82
index e17324ee596491dfb58a87439bd880ce37e70060..debd12874da1ee6e1c485096df7ef1ae3143e7b1 100644 (file)
 // <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.
+#![feature(macro_rules)]
+#![feature(simd)]
+#![allow(experimental)]
 
 // ignore-pretty very bad with line comments
 
 extern crate sync;
 
 use std::io;
+use std::os;
+use std::unstable::simd::f64x2;
 use sync::Future;
+use sync::Arc;
 
 static ITER: int = 50;
 static LIMIT: f64 = 2.0;
+static WORKERS: uint = 16;
+
+#[inline(always)]
+fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
+    assert!(WORKERS % 2 == 0);
+
+    // Ensure w and h are multiples of 8.
+    let w = (w + 7) / 8 * 8;
+    let h = w;
+
+    let chunk_size = h / WORKERS;
+
+    // Account for remainders in workload division, e.g. 1000 / 16 = 62.5
+    let first_chunk_size = if h % WORKERS != 0 {
+        chunk_size + h % WORKERS
+    } else {
+        chunk_size
+    };
+
+    // precalc values
+    let inverse_w_doubled = 2.0 / w as f64;
+    let inverse_h_doubled = 2.0 / h as f64;
+    let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled);
+    let v_consts = f64x2(1.5, 1.0);
+
+    // A lot of this code assumes this (so do other lang benchmarks)
+    assert!(w == h);
+    let mut precalc_r = Vec::with_capacity(w);
+    let mut precalc_i = Vec::with_capacity(h);
+
+    let precalc_futures = Vec::from_fn(WORKERS, |i| {
+        Future::spawn(proc () {
+            let mut rs = Vec::with_capacity(w / WORKERS);
+            let mut is = Vec::with_capacity(w / WORKERS);
+
+            let start = i * chunk_size;
+            let end = if i == 0 {
+                first_chunk_size
+            } else {
+                (i + 1) * chunk_size
+            };
+
+            // This assumes w == h
+            for x in range(start, end) {
+                let xf = x as f64;
+                let xy = f64x2(xf, xf);
+
+                let f64x2(r, i) = xy * v_inverses - v_consts;
+                rs.push(r);
+                is.push(i);
+            }
+
+            (rs, is)
+        })
+    });
+
+    for res in precalc_futures.move_iter() {
+        let (rs, is) = res.unwrap();
+        precalc_r.push_all_move(rs);
+        precalc_i.push_all_move(is);
+    }
+
+    assert_eq!(precalc_r.len(), w);
+    assert_eq!(precalc_i.len(), h);
+
+    let arc_init_r = Arc::new(precalc_r);
+    let arc_init_i = Arc::new(precalc_i);
+
+    let data = Vec::from_fn(WORKERS, |i| {
+        let vec_init_r = arc_init_r.clone();
+        let vec_init_i = arc_init_i.clone();
+
+        Future::spawn(proc () {
+            let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
+            let init_r_slice = vec_init_r.as_slice();
+            for &init_i in vec_init_i.slice(i * chunk_size, (i + 1) * chunk_size).iter() {
+                write_line(init_i, init_r_slice, &mut res);
+            }
+
+            res
+        })
+    });
+
+    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
+    for res in data.move_iter() {
+        try!(out.write(res.unwrap().as_slice()));
+    }
+    out.flush()
+}
 
 fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
+    let v_init_i : f64x2 = f64x2(init_i, init_i);
+    let v_2 : f64x2 = f64x2(2.0, 2.0);
+    static LIMIT_SQUARED: f64 = LIMIT * LIMIT;
+
     for chunk_init_r in vec_init_r.chunks(8) {
         let mut cur_byte = 0xff;
-        let mut cur_bitmask = 0x80;
-        for &init_r in chunk_init_r.iter() {
-            let mut cur_r = init_r;
-            let mut cur_i = init_i;
+        let mut i = 0;
+
+        while i < 8 {
+            let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]);
+            let mut cur_r = v_init_r;
+            let mut cur_i = v_init_i;
+            let mut r_sq = v_init_r * v_init_r;
+            let mut i_sq = v_init_i * v_init_i;
+
+            let mut b = 0;
             for _ in range(0, ITER) {
                 let r = cur_r;
                 let i = cur_i;
-                cur_r = r * r - i * i + init_r;
-                cur_i = 2.0 * r * i + init_i;
 
-                if r * r + i * i > LIMIT * LIMIT {
-                    cur_byte &= !cur_bitmask;
-                    break;
+                cur_i = v_2 * r * i + v_init_i;
+                cur_r = r_sq - i_sq + v_init_r;
+
+                let f64x2(bit1, bit2) = r_sq + i_sq;
+
+                if bit1 > LIMIT_SQUARED {
+                    b |= 2;
+                    if b == 3 { break; }
+                }
+
+                if bit2 > LIMIT_SQUARED {
+                    b |= 1;
+                    if b == 3 { break; }
                 }
+
+                r_sq = cur_r * cur_r;
+                i_sq = cur_i * cur_i;
             }
-            cur_bitmask >>= 1;
-        }
-        res.push(cur_byte);
-    }
-}
 
-fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
-    // Ensure w and h are multiples of 8.
-    let w = (w + 7) / 8 * 8;
-    let h = w;
-    let chunk_size = h / 8;
-
-    let data: Vec<Future<Vec<u8>>> = range(0u, 8).map(|i| Future::spawn(proc () {
-        let vec_init_r = Vec::from_fn(w, |x| 2.0 * (x as f64) / (w as f64) - 1.5);
-        let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
-        for y in range(i * chunk_size, (i + 1) * chunk_size) {
-            let init_i = 2.0 * (y as f64) / (h as f64) - 1.0;
-            write_line(init_i, vec_init_r.as_slice(), &mut res);
+            cur_byte = (cur_byte << 2) + b;
+            i += 2;
         }
-        res
-    })).collect();
 
-    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
-    for res in data.move_iter() {
-        try!(out.write(res.unwrap().as_slice()));
+        res.push(cur_byte^-1);
     }
-    out.flush()
 }
 
 fn main() {
-    let args = std::os::args();
+    let args = os::args();
     let args = args.as_slice();
     let res = if args.len() < 2 {
         println!("Test mode: do not dump the image because it's not utf8, \
                   which interferes with the test runner.");
-        mandelbrot(1000, std::io::util::NullWriter)
+        mandelbrot(1000, io::util::NullWriter)
     } else {
-        mandelbrot(from_str(args[1]).unwrap(), std::io::stdout())
+        mandelbrot(from_str(args[1]).unwrap(), io::stdout())
     };
     res.unwrap();
 }
diff --git a/src/test/run-make/graphviz-flowgraph/Makefile b/src/test/run-make/graphviz-flowgraph/Makefile
new file mode 100644 (file)
index 0000000..fedcc89
--- /dev/null
@@ -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 (file)
index 0000000..f699771
--- /dev/null
@@ -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 (file)
index 0000000..4e7fc7e
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..9d8411c
--- /dev/null
@@ -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 (file)
index 0000000..231aab6
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..ada3f09
--- /dev/null
@@ -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 (file)
index 0000000..3cdd73a
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..aff4304
--- /dev/null
@@ -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 (file)
index 0000000..8b172c0
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..adcc582
--- /dev/null
@@ -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 (file)
index 0000000..2a0ac8a
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..2d52c14
--- /dev/null
@@ -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 (file)
index 0000000..616d822
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..61b40d6
--- /dev/null
@@ -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 (file)
index 0000000..c914409
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..c99af17
--- /dev/null
@@ -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 (file)
index 0000000..39f71d3
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..61a708c
--- /dev/null
@@ -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 (file)
index 0000000..6ba7b03
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..892b9fc
--- /dev/null
@@ -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 (file)
index 0000000..a78ccb8
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..2cef122
--- /dev/null
@@ -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 (file)
index 0000000..0ca7cc5
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..59d65e5
--- /dev/null
@@ -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 (file)
index 0000000..d0f3452
--- /dev/null
@@ -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 <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.
+
+#[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 (file)
index 0000000..9c0f25d
--- /dev/null
@@ -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 (file)
index 0000000..90b1463
--- /dev/null
@@ -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 <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.
+
+#[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 (file)
index 0000000..2be43dc
--- /dev/null
@@ -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 (file)
index 0000000..0817a32
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..0fa4e9b
--- /dev/null
@@ -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 (file)
index 0000000..98ff095
--- /dev/null
@@ -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 <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.
+
+#[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 (file)
index 0000000..f0278fb
--- /dev/null
@@ -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 (file)
index 0000000..44c038d
--- /dev/null
@@ -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 <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.
+
+#[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 (file)
index 0000000..3f999ae
--- /dev/null
@@ -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 (file)
index 0000000..f4f23a6
--- /dev/null
@@ -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 <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.
+
+#[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 (file)
index 0000000..e9bccda
--- /dev/null
@@ -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 (file)
index 0000000..23f5bb8
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..6345b4e
--- /dev/null
@@ -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 (file)
index 0000000..0ace542
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..5fad185
--- /dev/null
@@ -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 (file)
index 0000000..092f689
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..593ad6f
--- /dev/null
@@ -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 (file)
index 0000000..d734993
--- /dev/null
@@ -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 <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.
+
+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 (file)
index 0000000..0798c4a
--- /dev/null
@@ -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 (file)
index 0000000..70083ed
--- /dev/null
@@ -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 <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.
+
+#[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 (file)
index 0000000..9ad731b
--- /dev/null
@@ -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 (file)
index 0000000..b35aac9
--- /dev/null
@@ -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 <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.
+
+#[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";
+}
index b56847b2da0d61b5b779136f71445640ae19f137..989c09146b7d5c54fae100ea06ae3c80d37413af 100644 (file)
@@ -11,7 +11,7 @@
 extern crate libc;
 
 use std::mem;
-use std::unstable::run_in_bare_thread;
+use std::rt::thread::Thread;
 
 #[link(name = "rustrt")]
 extern {
@@ -21,10 +21,10 @@ fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
 
 pub fn main() {
     unsafe {
-        run_in_bare_thread(proc() {
+        Thread::start(proc() {
             let i = &100;
             rust_dbg_call(callback, mem::transmute(i));
-        });
+        }).join();
     }
 }
 
index 437d6faea3854cea53a480763648168522fc7eee..387a454542adf3cb694dbcd6333b8dbf35f1184f 100644 (file)
@@ -74,6 +74,50 @@ fn test_rm_tempdir() {
     assert!(!path.exists());
 }
 
+fn test_rm_tempdir_close() {
+    let (tx, rx) = channel();
+    let f: proc():Send = proc() {
+        let tmp = TempDir::new("test_rm_tempdir").unwrap();
+        tx.send(tmp.path().clone());
+        tmp.close();
+        fail!("fail to unwind past `tmp`");
+    };
+    task::try(f);
+    let path = rx.recv();
+    assert!(!path.exists());
+
+    let tmp = TempDir::new("test_rm_tempdir").unwrap();
+    let path = tmp.path().clone();
+    let f: proc():Send = proc() {
+        let tmp = tmp;
+        tmp.close();
+        fail!("fail to unwind past `tmp`");
+    };
+    task::try(f);
+    assert!(!path.exists());
+
+    let path;
+    {
+        let f = proc() {
+            TempDir::new("test_rm_tempdir").unwrap()
+        };
+        let tmp = task::try(f).ok().expect("test_rm_tmdir");
+        path = tmp.path().clone();
+        assert!(path.exists());
+        tmp.close();
+    }
+    assert!(!path.exists());
+
+    let path;
+    {
+        let tmp = TempDir::new("test_rm_tempdir").unwrap();
+        path = tmp.unwrap();
+    }
+    assert!(path.exists());
+    fs::rmdir_recursive(&path);
+    assert!(!path.exists());
+}
+
 // Ideally these would be in std::os but then core would need
 // to depend on std
 fn recursive_mkdir_rel() {
@@ -130,6 +174,19 @@ pub fn test_rmdir_recursive_ok() {
     assert!(!root.join("bar").join("blat").exists());
 }
 
+pub fn dont_double_fail() {
+    let r: Result<(), _> = task::try(proc() {
+        let tmpdir = TempDir::new("test").unwrap();
+        // Remove the temporary directory so that TempDir sees
+        // an error on drop
+        fs::rmdir(tmpdir.path());
+        // Trigger failure. If TempDir fails *again* due to the rmdir
+        // error then the process will abort.
+        fail!();
+    });
+    assert!(r.is_err());
+}
+
 fn in_tmpdir(f: ||) {
     let tmpdir = TempDir::new("test").expect("can't make tmpdir");
     assert!(os::change_dir(tmpdir.path()));
@@ -140,8 +197,10 @@ fn in_tmpdir(f: ||) {
 pub fn main() {
     in_tmpdir(test_tempdir);
     in_tmpdir(test_rm_tempdir);
+    in_tmpdir(test_rm_tempdir_close);
     in_tmpdir(recursive_mkdir_rel);
     in_tmpdir(recursive_mkdir_dot);
     in_tmpdir(recursive_mkdir_rel_2);
     in_tmpdir(test_rmdir_recursive_ok);
+    in_tmpdir(dont_double_fail);
 }