diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 79607b06f9468..4ae8fc649ddbf 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -133,6 +133,7 @@ pub(crate) unsafe fn box_free(ptr: Unique) { } } +#[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 b64e102ba7882..d6806e7afd306 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 a3dbc450ce72f..2c01bd42cc77a 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 0000000000000..efb384d0afbce --- /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 or the MIT license +// , 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::>().len() +}