aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-02-02 08:59:22 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-02-02 09:19:19 +0200
commitd930b5205e277b522c2a7fe4a7c0e08c5a8afee1 (patch)
tree76d76d3ab31a1801e7992ba61cce1a0218cc672e
parent793e39564b25acc6283d1fd5a842c9799f1efdbe (diff)
Redo diagnostics without operator<< in namespace std
-rw-r--r--libbuild2/cc/lexer.test.cxx1
-rw-r--r--libbuild2/cc/types.hxx4
-rw-r--r--libbuild2/diagnostics.cxx24
-rw-r--r--libbuild2/diagnostics.hxx141
-rw-r--r--libbuild2/script/script.hxx4
-rw-r--r--libbuild2/types.hxx33
-rw-r--r--libbuild2/utility.cxx9
7 files changed, 103 insertions, 113 deletions
diff --git a/libbuild2/cc/lexer.test.cxx b/libbuild2/cc/lexer.test.cxx
index 0d7d12f..39e4279 100644
--- a/libbuild2/cc/lexer.test.cxx
+++ b/libbuild2/cc/lexer.test.cxx
@@ -6,6 +6,7 @@
#include <libbuild2/types.hxx>
#include <libbuild2/utility.hxx>
+#include <libbuild2/cc/types.hxx>
#include <libbuild2/cc/lexer.hxx>
#undef NDEBUG
diff --git a/libbuild2/cc/types.hxx b/libbuild2/cc/types.hxx
index c5b35f5..93f31bc 100644
--- a/libbuild2/cc/types.hxx
+++ b/libbuild2/cc/types.hxx
@@ -175,6 +175,10 @@ namespace build2
const target_type& bmi;
const target_type& hbmi;
};
+
+ // "Unhide" operator<< from the build2 namespace.
+ //
+ using build2::operator<<;
}
}
diff --git a/libbuild2/diagnostics.cxx b/libbuild2/diagnostics.cxx
index 4d2d7ce..a2a8444 100644
--- a/libbuild2/diagnostics.cxx
+++ b/libbuild2/diagnostics.cxx
@@ -77,30 +77,6 @@ namespace build2
dr << butl::process_args {args, n};
}
- // Diagnostics stack.
- //
- static
-#ifdef __cpp_thread_local
- thread_local
-#else
- __thread
-#endif
- const diag_frame* diag_frame_stack = nullptr;
-
- const diag_frame* diag_frame::
- stack () noexcept
- {
- return diag_frame_stack;
- }
-
- const diag_frame* diag_frame::
- stack (const diag_frame* f) noexcept
- {
- const diag_frame* r (diag_frame_stack);
- diag_frame_stack = f;
- return r;
- }
-
// Diagnostic facility, project specifics.
//
diff --git a/libbuild2/diagnostics.hxx b/libbuild2/diagnostics.hxx
index f3d9db4..c6c4344 100644
--- a/libbuild2/diagnostics.hxx
+++ b/libbuild2/diagnostics.hxx
@@ -14,7 +14,7 @@
namespace build2
{
- using butl::diag_record;
+ struct diag_record;
// Throw this exception to terminate the build. The handler should
// assume that the diagnostics has already been issued.
@@ -190,79 +190,97 @@ namespace build2
: stderr_term && verb >= 1 && verb <= max_verb;
}
- // Diagnostic facility, base infrastructure.
+ // Diagnostic facility.
+ //
+ // Note that this is the "complex" case we we derive from (rather than
+ // alias) a number of butl::diag_* types and provide custom operator<<
+ // "overrides" in order to make ADL look in the build2 rather than butl
+ // namespace.
//
using butl::diag_stream_lock;
using butl::diag_stream;
using butl::diag_epilogue;
+ using butl::diag_frame;
- // Diagnostics stack. Each frame is "applied" to the fail/error/warn/info
- // diag record.
- //
- // Unfortunately most of our use-cases don't fit into the 2-pointer small
- // object optimization of std::function. So we have to complicate things
- // a bit here.
- //
- struct LIBBUILD2_SYMEXPORT diag_frame
+ template <typename> struct diag_prologue;
+ template <typename> struct diag_mark;
+
+ struct diag_record: butl::diag_record
{
- explicit
- diag_frame (void (*f) (const diag_frame&, const diag_record&))
- : func_ (f)
+ template <typename T>
+ const diag_record&
+ operator<< (const T& x) const
{
- if (func_ != nullptr)
- prev_ = stack (this);
+ os << x;
+ return *this;
}
- diag_frame (diag_frame&& x)
- : func_ (x.func_)
- {
- if (func_ != nullptr)
- {
- prev_ = x.prev_;
- stack (this);
+ diag_record () = default;
- x.func_ = nullptr;
- }
- }
+ template <typename B>
+ explicit
+ diag_record (const diag_prologue<B>& p): diag_record () { *this << p;}
- diag_frame& operator= (diag_frame&&) = delete;
+ template <typename B>
+ explicit
+ diag_record (const diag_mark<B>& m): diag_record () { *this << m;}
+ };
- diag_frame (const diag_frame&) = delete;
- diag_frame& operator= (const diag_frame&) = delete;
+ template <typename B>
+ struct diag_prologue: butl::diag_prologue<B>
+ {
+ using butl::diag_prologue<B>::diag_prologue;
- ~diag_frame ()
+ template <typename T>
+ diag_record
+ operator<< (const T& x) const
{
- if (func_ != nullptr )
- stack (prev_);
+ diag_record r;
+ r.append (this->indent, this->epilogue);
+ B::operator() (r);
+ r << x;
+ return r;
}
- static void
- apply (const diag_record& r)
+ friend const diag_record&
+ operator<< (const diag_record& r, const diag_prologue& p)
{
- for (const diag_frame* f (stack ()); f != nullptr; f = f->prev_)
- f->func_ (*f, r);
+ r.append (p.indent, p.epilogue);
+ p (r);
+ return r;
}
+ };
- // Tip of the stack.
- //
- static const diag_frame*
- stack () noexcept;
+ template <typename B>
+ struct diag_mark: butl::diag_mark<B>
+ {
+ using butl::diag_mark<B>::diag_mark;
- // Set the new and return the previous tip of the stack.
- //
- static const diag_frame*
- stack (const diag_frame*) noexcept;
+ template <typename T>
+ diag_record
+ operator<< (const T& x) const
+ {
+ return B::operator() () << x;
+ }
- struct stack_guard
+ friend const diag_record&
+ operator<< (const diag_record& r, const diag_mark& m)
{
- explicit stack_guard (const diag_frame* s): s_ (stack (s)) {}
- ~stack_guard () {stack (s_);}
- const diag_frame* s_;
- };
+ return r << m ();
+ }
+ };
- private:
- void (*func_) (const diag_frame&, const diag_record&);
- const diag_frame* prev_;
+ template <typename B>
+ struct diag_noreturn_end: butl::diag_noreturn_end<B>
+ {
+ using butl::diag_noreturn_end<B>::diag_noreturn_end;
+
+ [[noreturn]] friend void
+ operator<< (const diag_record& r, const diag_noreturn_end& e)
+ {
+ assert (r.full ());
+ e.B::operator() (r);
+ }
};
template <typename F>
@@ -273,9 +291,10 @@ namespace build2
private:
static void
- thunk (const diag_frame& f, const diag_record& r)
+ thunk (const diag_frame& f, const butl::diag_record& r)
{
- static_cast<const diag_frame_impl&> (f).func_ (r);
+ static_cast<const diag_frame_impl&> (f).func_ (
+ static_cast<const diag_record&> (r));
}
const F func_;
@@ -288,8 +307,6 @@ namespace build2
return diag_frame_impl<F> (move (f));
}
- // Diagnostic facility, project specifics.
- //
struct LIBBUILD2_SYMEXPORT simple_prologue_base
{
explicit
@@ -352,8 +369,8 @@ namespace build2
struct basic_mark_base
{
- using simple_prologue = butl::diag_prologue<simple_prologue_base>;
- using location_prologue = butl::diag_prologue<location_prologue_base>;
+ using simple_prologue = diag_prologue<simple_prologue_base>;
+ using location_prologue = diag_prologue<location_prologue_base>;
explicit
basic_mark_base (const char* type,
@@ -427,7 +444,7 @@ namespace build2
const void* data_;
diag_epilogue* const epilogue_;
};
- using basic_mark = butl::diag_mark<basic_mark_base>;
+ using basic_mark = diag_mark<basic_mark_base>;
LIBBUILD2_SYMEXPORT extern const basic_mark error;
LIBBUILD2_SYMEXPORT extern const basic_mark warn;
@@ -452,7 +469,7 @@ namespace build2
mod,
name) {}
};
- using trace_mark = butl::diag_mark<trace_mark_base>;
+ using trace_mark = diag_mark<trace_mark_base>;
using tracer = trace_mark;
// fail
@@ -464,7 +481,7 @@ namespace build2
const void* data = nullptr)
: basic_mark_base (type,
data,
- [](const diag_record& r)
+ [](const butl::diag_record& r)
{
diag_frame::apply (r);
r.flush ();
@@ -474,7 +491,7 @@ namespace build2
nullptr,
nullptr) {}
};
- using fail_mark = butl::diag_mark<fail_mark_base>;
+ using fail_mark = diag_mark<fail_mark_base>;
struct fail_end_base
{
@@ -488,7 +505,7 @@ namespace build2
throw failed ();
}
};
- using fail_end = butl::diag_noreturn_end<fail_end_base>;
+ using fail_end = diag_noreturn_end<fail_end_base>;
LIBBUILD2_SYMEXPORT extern const fail_mark fail;
LIBBUILD2_SYMEXPORT extern const fail_end endf;
diff --git a/libbuild2/script/script.hxx b/libbuild2/script/script.hxx
index 81bc13c..5a39659 100644
--- a/libbuild2/script/script.hxx
+++ b/libbuild2/script/script.hxx
@@ -585,6 +585,10 @@ namespace build2
verify_environment_var_assignment (const string&,
const char* prefix,
const location&);
+
+ // "Unhide" operator<< from the build2 namespace.
+ //
+ using build2::operator<<;
}
}
diff --git a/libbuild2/types.hxx b/libbuild2/types.hxx
index af1a4de..7bc6b32 100644
--- a/libbuild2/types.hxx
+++ b/libbuild2/types.hxx
@@ -317,6 +317,14 @@ namespace build2
using paths = std::vector<path>;
using dir_paths = std::vector<dir_path>;
+ // Path printing potentially relative with trailing slash for directories.
+ //
+ LIBBUILD2_SYMEXPORT ostream&
+ operator<< (ostream&, const ::butl::path&); // utility.cxx
+
+ LIBBUILD2_SYMEXPORT ostream&
+ operator<< (ostream&, const ::butl::path_name_view&); // utility.cxx
+
// <libbutl/timestamp.hxx>
//
using butl::system_clock;
@@ -381,6 +389,11 @@ namespace build2
process_path_ex () = default;
};
+ // Print as recall[@effect].
+ //
+ LIBBUILD2_SYMEXPORT ostream&
+ operator<< (ostream&, const ::butl::process_path&); // utility.cxx
+
// <libbutl/fdstream.hxx>
//
using butl::auto_fd;
@@ -478,26 +491,6 @@ namespace build2
operator<< (ostream&, run_phase); // utility.cxx
}
-// In order to be found (via ADL) these have to be either in std:: or in
-// butl::. The latter is a bad idea since libbutl includes the default
-// implementation. They are defined in utility.cxx.
-//
-namespace std
-{
- // Path printing potentially relative with trailing slash for directories.
- //
- LIBBUILD2_SYMEXPORT ostream&
- operator<< (ostream&, const ::butl::path&);
-
- LIBBUILD2_SYMEXPORT ostream&
- operator<< (ostream&, const ::butl::path_name_view&);
-
- // Print as recall[@effect].
- //
- LIBBUILD2_SYMEXPORT ostream&
- operator<< (ostream&, const ::butl::process_path&);
-}
-
// <libbuild2/name.hxx>
//
#include <libbuild2/name.hxx>
diff --git a/libbuild2/utility.cxx b/libbuild2/utility.cxx
index f7f3d41..3f89def 100644
--- a/libbuild2/utility.cxx
+++ b/libbuild2/utility.cxx
@@ -19,7 +19,6 @@
using namespace std;
using namespace butl;
-//
// <libbuild2/types.hxx>
//
namespace build2
@@ -31,10 +30,7 @@ namespace build2
{
return os << run_phase_[static_cast<uint8_t> (p)];
}
-}
-namespace std
-{
ostream&
operator<< (ostream& os, const ::butl::path& p)
{
@@ -76,11 +72,10 @@ namespace std
}
}
+// <libbuild2/utility.hxx>
+//
namespace build2
{
- //
- // <libbuild2/utility.hxx>
- //
void (*terminate) (bool);
process_path argv0;