Index: include/__noexcept =================================================================== --- /dev/null +++ include/__noexcept @@ -0,0 +1,59 @@ +// -*- C++ -*- +//===--------------------------- __noexcept ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===-------------------------------------------------------------------------===// + +#ifndef _LIBCPP_NOEXCEPT_H +#define _LIBCPP_NOEXCEPT_H + +#include <__config> + +#ifdef _LIBCPP_NO_EXCEPTIONS +#include +#include +#endif + +/* Variants of the throw_helper() function for different exception throwing + needs. */ + +template +inline void throw_helper1(const char *msg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw T(); +#else + if (msg) + fprintf(stderr, "%s\n", msg); + abort(); +#endif +} + +template +inline void throw_helper2(const char *msg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw T(msg); +#else + fprintf(stderr, "%s\n", msg); + abort(); +#endif +} + +template +inline void throw_helper3(K k, const char *msg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw T(k); +#else + if (msg) + fprintf(stderr, "%s\n", msg); + abort(); +#endif +} + +#endif // _LIBCPP_NOEXCEPT_H Index: include/array =================================================================== --- include/array +++ include/array @@ -110,6 +110,7 @@ #if defined(_LIBCPP_NO_EXCEPTIONS) #include #endif +#include <__noexcept> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -201,11 +202,7 @@ array<_Tp, _Size>::at(size_type __n) { if (__n >= _Size) -#ifndef _LIBCPP_NO_EXCEPTIONS - throw out_of_range("array::at"); -#else - assert(!"array::at out_of_range"); -#endif + throw_helper1("array::at out_of_range"); return __elems_[__n]; } @@ -215,11 +212,7 @@ array<_Tp, _Size>::at(size_type __n) const { if (__n >= _Size) -#ifndef _LIBCPP_NO_EXCEPTIONS - throw out_of_range("array::at"); -#else - assert(!"array::at out_of_range"); -#endif + throw_helper1("array::at out_of_range"); return __elems_[__n]; } Index: test/std/containers/sequences/array/at.pass.cpp =================================================================== --- test/std/containers/sequences/array/at.pass.cpp +++ test/std/containers/sequences/array/at.pass.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// XFAIL: libcpp-no-exceptions // // reference operator[] (size_type) @@ -19,6 +18,7 @@ #include #include "test_macros.h" +#include "noexcept.h" // std::array is explicitly allowed to be initialized with A a = { init-list };. // Disable the missing braces warning for this reason. Index: test/support/noexcept.h =================================================================== --- /dev/null +++ test/support/noexcept.h @@ -0,0 +1,40 @@ +// -*- C++ -*- +//===----------------------------- noexcept.h -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifdef _LIBCPP_NO_EXCEPTIONS + +#include +#include + +jmp_buf try_buf; + +// Re-write try/catch with if/else to mimic a similar control flow when testing +// the no-exceptions library variant. The idea is to save as much of the usual +// with-exceptions assertions as possible. This of course does not work when +// there are multiple catch statements, in those cases we have to use the +// _LIBCPP_NO_EXCEPTIONS macro as appropriate; such cases are rare. +#define try if(!setjmp(try_buf)) +#define catch(ex) else + +// The default assert macro calls abort(), we don't want that. +#undef assert + +static void noexcept_assert_failed(const char *exp, const char *file, int line) { + fprintf(stderr, "Assertion failed: (%s), at %s line %d.\n", exp, file, line); + exit(-1); +} + +#define assert(e) (e) ? (void) 0 : noexcept_assert_failed(#e, __FILE__, __LINE__); + +// Jump back to the catch (now else) clause. +extern "C" void abort(void) { + longjmp(try_buf, 1); +} + +#endif // _LIBCPP_NO_EXCEPTIONS