about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liballoc/alloc.rs1
-rw-r--r--src/librustc_codegen_llvm/attributes.rs29
-rw-r--r--src/librustc_codegen_llvm/callee.rs11
-rw-r--r--src/test/codegen/vec-iter-collect-len.rs21
4 files changed, 46 insertions, 16 deletions
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index 79607b06f94..4ae8fc649dd 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -133,6 +133,7 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
     }
 }
 
+#[rustc_allocator_nounwind]
 pub fn oom() -> ! {
     extern {
         #[lang = "oom"]
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index b64e102ba78..d6806e7afd3 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -20,7 +20,9 @@ use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_target::spec::PanicStrategy;
 
+use attributes;
 use llvm::{self, Attribute, ValueRef};
 use llvm::AttributePlace::Function;
 use llvm_util;
@@ -135,11 +137,28 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
         Attribute::NoAlias.apply_llfn(
             llvm::AttributePlace::ReturnValue, llfn);
     }
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
-        unwind(llfn, true);
-    }
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
-        unwind(llfn, false);
+
+    let can_unwind = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
+        Some(true)
+    } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
+        Some(false)
+
+    // Perhaps questionable, but we assume that anything defined
+    // *in Rust code* may unwind. Foreign items like `extern "C" {
+    // fn foo(); }` are assumed not to unwind **unless** they have
+    // a `#[unwind]` attribute.
+    } else if !cx.tcx.is_foreign_item(id) {
+        Some(true)
+    } else {
+        None
+    };
+
+    match can_unwind {
+        Some(false) => attributes::unwind(llfn, false),
+        Some(true) if cx.tcx.sess.panic_strategy() == PanicStrategy::Unwind => {
+            attributes::unwind(llfn, true);
+        }
+        Some(true) | None => {}
     }
 
     let features = llvm_target_features(cx.tcx.sess)
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index a3dbc450ce7..2c01bd42cc7 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -26,7 +26,6 @@ use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TypeFoldable};
 use rustc::ty::layout::LayoutOf;
 use rustc::ty::subst::Substs;
-use rustc_target::spec::PanicStrategy;
 
 /// Codegens a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
@@ -102,16 +101,6 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         let instance_def_id = instance.def_id();
 
-        // Perhaps questionable, but we assume that anything defined
-        // *in Rust code* may unwind. Foreign items like `extern "C" {
-        // fn foo(); }` are assumed not to unwind **unless** they have
-        // a `#[unwind]` attribute.
-        if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
-            if !tcx.is_foreign_item(instance_def_id) {
-                attributes::unwind(llfn, true);
-            }
-        }
-
         // Apply an appropriate linkage/visibility value to our item that we
         // just declared.
         //
diff --git a/src/test/codegen/vec-iter-collect-len.rs b/src/test/codegen/vec-iter-collect-len.rs
new file mode 100644
index 00000000000..efb384d0afb
--- /dev/null
+++ b/src/test/codegen/vec-iter-collect-len.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 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.
+
+// no-system-llvm
+// compile-flags: -O
+#![crate_type="lib"]
+
+#[no_mangle]
+pub fn get_len() -> usize {
+    // CHECK-LABEL: @get_len
+    // CHECK-NOT: call
+    // CHECK-NOT: invoke
+    [1, 2, 3].iter().collect::<Vec<_>>().len()
+}