aboutsummaryrefslogtreecommitdiff
path: root/build/diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'build/diagnostics')
-rw-r--r--build/diagnostics54
1 files changed, 54 insertions, 0 deletions
diff --git a/build/diagnostics b/build/diagnostics
new file mode 100644
index 0000000..c8fb169
--- /dev/null
+++ b/build/diagnostics
@@ -0,0 +1,54 @@
+// file : build/diagnostics -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BUILD_DIAGNOSTICS
+#define BUILD_DIAGNOSTICS
+
+#include <tuple>
+#include <utility>
+#include <exception>
+
+namespace build
+{
+ // Throw this exception to terminate the build. The handler should
+ // assume that the diagnostics has already been issued.
+ //
+ class error: public std::exception {};
+
+ // Call a function if there is an exception.
+ //
+ template <typename F, typename T>
+ struct exception_guard;
+
+ template <typename F, typename... A>
+ inline exception_guard<F, std::tuple<A&&...>>
+ make_exception_guard (F f, A&&... a)
+ {
+ return exception_guard<F, std::tuple<A&&...>> (
+ std::move (f), std::forward_as_tuple (a...));
+ }
+
+ template <typename F, typename... A>
+ struct exception_guard<F, std::tuple<A...>>
+ {
+ typedef std::tuple<A...> T;
+
+ exception_guard (F f, T a): f_ (std::move (f)), a_ (std::move (a)) {}
+ ~exception_guard ()
+ {
+ if (std::uncaught_exception ())
+ call (std::index_sequence_for<A...> ());
+ }
+
+ private:
+ template <std::size_t... I>
+ void
+ call (std::index_sequence<I...>) {f_ (std::get<I> (a_)...);}
+
+ F f_;
+ T a_;
+ };
+}
+
+#endif // BUILD_DIAGNOSTICS