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

Tidied up the patch a bit:

- Got rid of the different variants of the throw_helper function, can do with 
one in almost all the cases (the exceptional case will be submitted for review 
separately).
- Modified __config a little to make the compiler not complain about 
re-defining _LIBCPP_NO_EXCEPTIONS macro when compiling with -fno-exceptions 
(NFC).


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,41 @@
+// -*- 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>
+
+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
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,39 @@
+// -*- 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>
+#endif
+
+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");
+    abort();
+#endif
+}
+
+#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