rmaprath updated this revision to Diff 42977.
rmaprath added a comment.

Two minor additions:

- Introduced a `TEST_THROW` macro for those tests that need to throw exceptions 
(Note:- not using the `_LIBCPP_THROW` macro here as we want to keep the tests 
independent of the standard library implementation).
- Updated `tests/support/test_allocator.h` to use the `_LIBCPP_THROW` macro 
rather than terminate the test when exceptions are disabled.


http://reviews.llvm.org/D14653

Files:
  include/__config
  include/array
  test/std/containers/sequences/array/at.pass.cpp
  test/support/noexcept.h
  test/support/test_allocator.h

Index: test/support/test_allocator.h
===================================================================
--- test/support/test_allocator.h
+++ test/support/test_allocator.h
@@ -65,13 +65,8 @@
     pointer allocate(size_type n, const void* = 0)
         {
             assert(data_ >= 0);
-            if (time_to_throw >= throw_after) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
-                throw std::bad_alloc();
-#else
-                std::terminate();
-#endif
-            }
+            if (time_to_throw >= throw_after)
+                _LIBCPP_THROW(std::bad_alloc(), "std::bad_alloc");
             ++time_to_throw;
             ++alloc_count;
             return (pointer)::operator new(n * sizeof(T));
@@ -125,13 +120,8 @@
     pointer allocate(size_type n, const void* = 0)
         {
             assert(data_ >= 0);
-            if (time_to_throw >= throw_after) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
-                throw std::bad_alloc();
-#else
-                std::terminate();
-#endif
-            }
+            if (time_to_throw >= throw_after)
+                _LIBCPP_THROW(std::bad_alloc(), "std::bad_alloc");
             ++time_to_throw;
             ++alloc_count;
             return (pointer)::operator new (n * sizeof(T));
Index: test/support/noexcept.h
===================================================================
--- /dev/null
+++ test/support/noexcept.h
@@ -0,0 +1,60 @@
+// -*- 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.
+//
+//===----------------------------------------------------------------------===//
+#ifndef NOEXCEPT_H
+#define NOEXCEPT_H
+
+#ifdef _LIBCPP_NO_EXCEPTIONS
+
+#include <setjmp.h>
+#include <cstdio>
+#include "test_macros.h"
+
+#ifndef _LIBCPP_HAS_NO_THREADS
+# if TEST_STD_VER >= 11
+#   define TLS_SPEC thread_local
+# elif defined(_LIBCPP_MSVC)
+#   define TLS_SPEC __declspec(thread)
+# else
+#   define TLS_SPEC __thread
+# endif
+#else
+# define TLS_SPEC
+#endif
+
+// Some tests launch multiple threads, in which case we need to make sure that
+// try_buf is maintained per-thread, otherwise setjmp()/longjmp() will attempt
+// to jump between threads!
+TLS_SPEC jmp_buf try_buf;
+#undef TLS_SPEC
+
+// 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
+
+// Jump back to the catch (now else) clause.
+void __libcxx_noexceptions_abort(const char *msg) {
+  fprintf(stderr, "%s\n", msg);
+  longjmp(try_buf, 1);
+}
+
+#endif // _LIBCPP_NO_EXCEPTIONS
+
+// A throw helper macro for the use of tests.
+#ifndef _LIBCPP_NO_EXCEPTIONS
+#define TEST_THROW(E) throw E
+#else
+#define TEST_THROW(E) __libcxx_noexceptions_abort("exception")
+#endif
+
+#endif // NOEXCEPT_H
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
 // <array>
 
 // reference operator[] (size_type)
@@ -19,6 +18,7 @@
 #include <cassert>
 
 #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: include/array
===================================================================
--- include/array
+++ include/array
@@ -201,11 +201,8 @@
 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
+        _LIBCPP_THROW(out_of_range("array::at out_of_range"),
+                      "array::at out_of_range");
     return __elems_[__n];
 }
 
@@ -215,11 +212,8 @@
 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
+        _LIBCPP_THROW(out_of_range("array::at out_of_range"),
+                      "array::at out_of_range");
     return __elems_[__n];
 }
 
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -281,7 +281,7 @@
 typedef __char32_t char32_t;
 #endif
 
-#if !(__has_feature(cxx_exceptions))
+#if !(__has_feature(cxx_exceptions)) && !defined(_LIBCPP_NO_EXCEPTIONS)
 #define _LIBCPP_NO_EXCEPTIONS
 #endif
 
@@ -825,6 +825,20 @@
 #define _LIBCPP_HAS_NO_ATOMIC_HEADER
 #endif
 
+#ifdef _LIBCPP_NO_EXCEPTIONS
+_LIBCPP_NORETURN _LIBCPP_WEAK void __libcxx_noexceptions_abort(const char *msg);
+extern "C++" {
+inline void __libcxx_noexceptions_report(const char *msg = nullptr)
+{
+    if (__libcxx_noexceptions_abort)
+        __libcxx_noexceptions_abort(msg);
+}
+}
+#define _LIBCPP_THROW(E, MSG) __libcxx_noexceptions_report(MSG)
+#else  // !_LIBCPP_NO_EXCEPTIONS
+#define _LIBCPP_THROW(E, MSG) throw E
+#endif // _LIBCPP_NO_EXCEPTIONS
+
 #endif // __cplusplus
 
 #endif // _LIBCPP_CONFIG
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to