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

Addressing review comments:

- Fixed a couple of typos.
- Made the use of the thread-local storage specifier a bit more flexible to 
allow testing on few other configurations.


http://reviews.llvm.org/D14653

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

Index: test/support/noexcept.h
===================================================================
--- /dev/null
+++ test/support/noexcept.h
@@ -0,0 +1,48 @@
+// -*- 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 <setjmp.h>
+#include <cstdio>
+#include <cstdlib>
+#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(void) {
+  longjmp(try_buf, 1);
+}
+
+#endif // _LIBCPP_NO_EXCEPTIONS
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
@@ -110,6 +110,7 @@
 #if defined(_LIBCPP_NO_EXCEPTIONS)
     #include <cassert>
 #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_helper(out_of_range("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_helper(out_of_range("array::at out_of_range"));
     return __elems_[__n];
 }
 
Index: include/__noexcept
===================================================================
--- /dev/null
+++ include/__noexcept
@@ -0,0 +1,45 @@
+// -*- 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 <cstdlib>
+#include <cstdio>
+
+void _LIBCPP_WEAK __libcxx_noexceptions_abort();
+#endif // _LIBCPP_NO_EXCEPTIONS
+
+template<typename T>
+inline void __throw_helper(T t, const char *msg = nullptr)
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    throw t;
+#else
+    if (msg) // explicit error message provided
+      fprintf(stderr, "%s\n", msg);
+    // FIXME: instead of using the default what() string of the std::exception
+    // class, make all the exception classes return a meaningful error message.
+    else if (t.what())
+      fprintf(stderr, "%s\n", t.what());
+    else // use a generic error message
+      fprintf(stderr, "exception raised, cannot propagate. Aborting.\n");
+
+    if (__libcxx_noexceptions_abort)
+      __libcxx_noexceptions_abort();
+    else
+      abort();
+#endif // _LIBCPP_NO_EXCEPTIONS
+}
+
+#endif // _LIBCPP_NOEXCEPT_H
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
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to