Library interface improvements
This commit is contained in:
parent
216246332c
commit
209ce45157
26
README.md
26
README.md
@ -122,6 +122,7 @@ namespace cpptrace {
|
|||||||
object_trace resolve_object_trace() const;
|
object_trace resolve_object_trace() const;
|
||||||
stacktrace resolve() const;
|
stacktrace resolve() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
bool empty() const noexcept;
|
||||||
/* iterators exist for this object */
|
/* iterators exist for this object */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -141,6 +142,7 @@ namespace cpptrace {
|
|||||||
explicit object_trace(std::vector<object_frame>&& frames);
|
explicit object_trace(std::vector<object_frame>&& frames);
|
||||||
stacktrace resolve() const;
|
stacktrace resolve() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
bool empty() const noexcept;
|
||||||
/* iterators exist for this object */
|
/* iterators exist for this object */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -155,17 +157,21 @@ namespace cpptrace {
|
|||||||
std::string symbol;
|
std::string symbol;
|
||||||
bool operator==(const stacktrace_frame& other) const;
|
bool operator==(const stacktrace_frame& other) const;
|
||||||
bool operator!=(const stacktrace_frame& other) const;
|
bool operator!=(const stacktrace_frame& other) const;
|
||||||
|
std::string to_string() const;
|
||||||
|
/* operator<<(ostream, ..) and std::format support exist for this object */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stacktrace {
|
struct stacktrace {
|
||||||
std::vector<stacktrace_frame> frames;
|
std::vector<stacktrace_frame> frames;
|
||||||
|
explicit stacktrace();
|
||||||
explicit stacktrace(std::vector<stacktrace_frame>&& frames);
|
explicit stacktrace(std::vector<stacktrace_frame>&& frames);
|
||||||
void print() const;
|
void print() const;
|
||||||
void print(std::ostream& stream) const;
|
void print(std::ostream& stream) const;
|
||||||
void print(std::ostream& stream, bool color) const;
|
void print(std::ostream& stream, bool color) const;
|
||||||
std::string to_string() const;
|
std::string to_string() const;
|
||||||
void clear();
|
void clear();
|
||||||
/* iterators exist for this object */
|
bool empty() const noexcept;
|
||||||
|
/* operator<<(ostream, ..), std::format support, and iterators exist for this object */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -183,17 +189,29 @@ namespace cpptrace {
|
|||||||
// Traced exception class
|
// Traced exception class
|
||||||
// Extending classes should call the exception constructor with a skip value of 1.
|
// Extending classes should call the exception constructor with a skip value of 1.
|
||||||
class exception : public std::exception {
|
class exception : public std::exception {
|
||||||
explicit exception(uint32_t skip)
|
protected:
|
||||||
|
mutable raw_trace trace;
|
||||||
|
mutable stacktrace resolved_trace;
|
||||||
|
mutable std::string resolved_what;
|
||||||
|
explicit exception(uint32_t skip) noexcept;
|
||||||
|
const stacktrace& get_resolved_trace() const noexcept;
|
||||||
|
virtual const std::string& get_resolved_what() const noexcept;
|
||||||
public:
|
public:
|
||||||
explicit exception();
|
explicit exception() noexcept;
|
||||||
const char* what() const noexcept override;
|
const char* what() const noexcept override;
|
||||||
|
const std::string& get_what() const noexcept; // what(), but not a C-string
|
||||||
|
const raw_trace& get_raw_trace() const noexcept;
|
||||||
|
const stacktrace& get_trace() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
class exception_with_message : public exception {
|
class exception_with_message : public exception {
|
||||||
explicit exception_with_message(std::string&& message_arg, uint32_t skip)
|
mutable std::string message;
|
||||||
|
explicit exception_with_message(std::string&& message_arg, uint32_t skip) noexcept;
|
||||||
|
const std::string& get_resolved_what() const noexcept override;
|
||||||
public:
|
public:
|
||||||
explicit exception_with_message(std::string&& message_arg);
|
explicit exception_with_message(std::string&& message_arg);
|
||||||
const char* what() const noexcept override;
|
const char* what() const noexcept override;
|
||||||
|
const std::string& get_message() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
// All stdexcept errors have analogs here. Same constructor as exception_with_message.
|
// All stdexcept errors have analogs here. Same constructor as exception_with_message.
|
||||||
|
|||||||
@ -7,6 +7,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_format
|
||||||
|
#include <format>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
#define CPPTRACE_API __declspec(dllexport)
|
#define CPPTRACE_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
@ -23,6 +27,7 @@ namespace cpptrace {
|
|||||||
CPPTRACE_API object_trace resolve_object_trace() const;
|
CPPTRACE_API object_trace resolve_object_trace() const;
|
||||||
CPPTRACE_API stacktrace resolve() const;
|
CPPTRACE_API stacktrace resolve() const;
|
||||||
CPPTRACE_API void clear();
|
CPPTRACE_API void clear();
|
||||||
|
CPPTRACE_API bool empty() const noexcept;
|
||||||
|
|
||||||
using iterator = std::vector<uintptr_t>::iterator;
|
using iterator = std::vector<uintptr_t>::iterator;
|
||||||
using const_iterator = std::vector<uintptr_t>::const_iterator;
|
using const_iterator = std::vector<uintptr_t>::const_iterator;
|
||||||
@ -44,6 +49,7 @@ namespace cpptrace {
|
|||||||
explicit object_trace(std::vector<object_frame>&& frames_) : frames(frames_) {}
|
explicit object_trace(std::vector<object_frame>&& frames_) : frames(frames_) {}
|
||||||
CPPTRACE_API stacktrace resolve() const;
|
CPPTRACE_API stacktrace resolve() const;
|
||||||
CPPTRACE_API void clear();
|
CPPTRACE_API void clear();
|
||||||
|
CPPTRACE_API bool empty() const noexcept;
|
||||||
|
|
||||||
using iterator = std::vector<object_frame>::iterator;
|
using iterator = std::vector<object_frame>::iterator;
|
||||||
using const_iterator = std::vector<object_frame>::const_iterator;
|
using const_iterator = std::vector<object_frame>::const_iterator;
|
||||||
@ -69,16 +75,21 @@ namespace cpptrace {
|
|||||||
bool operator!=(const stacktrace_frame& other) const {
|
bool operator!=(const stacktrace_frame& other) const {
|
||||||
return !operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
CPPTRACE_API std::string to_string() const;
|
||||||
|
CPPTRACE_API friend std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stacktrace {
|
struct stacktrace {
|
||||||
std::vector<stacktrace_frame> frames;
|
std::vector<stacktrace_frame> frames;
|
||||||
|
explicit stacktrace() {}
|
||||||
explicit stacktrace(std::vector<stacktrace_frame>&& frames_) : frames(frames_) {}
|
explicit stacktrace(std::vector<stacktrace_frame>&& frames_) : frames(frames_) {}
|
||||||
CPPTRACE_API void print() const;
|
CPPTRACE_API void print() const;
|
||||||
CPPTRACE_API void print(std::ostream& stream) const;
|
CPPTRACE_API void print(std::ostream& stream) const;
|
||||||
CPPTRACE_API void print(std::ostream& stream, bool color) const;
|
CPPTRACE_API void print(std::ostream& stream, bool color) const;
|
||||||
CPPTRACE_API std::string to_string() const;
|
|
||||||
CPPTRACE_API void clear();
|
CPPTRACE_API void clear();
|
||||||
|
CPPTRACE_API bool empty() const noexcept;
|
||||||
|
CPPTRACE_API std::string to_string() const;
|
||||||
|
CPPTRACE_API friend std::ostream& operator<<(std::ostream& stream, const stacktrace& trace);
|
||||||
|
|
||||||
using iterator = std::vector<stacktrace_frame>::iterator;
|
using iterator = std::vector<stacktrace_frame>::iterator;
|
||||||
using const_iterator = std::vector<stacktrace_frame>::const_iterator;
|
using const_iterator = std::vector<stacktrace_frame>::const_iterator;
|
||||||
@ -96,91 +107,150 @@ namespace cpptrace {
|
|||||||
|
|
||||||
// utilities:
|
// utilities:
|
||||||
CPPTRACE_API std::string demangle(const std::string& name);
|
CPPTRACE_API std::string demangle(const std::string& name);
|
||||||
|
CPPTRACE_API void absorb_trace_exceptions(bool absorb);
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
CPPTRACE_API bool should_absorb_trace_exceptions();
|
||||||
|
}
|
||||||
|
|
||||||
class exception : public std::exception {
|
class exception : public std::exception {
|
||||||
protected:
|
protected:
|
||||||
mutable raw_trace trace;
|
mutable raw_trace trace;
|
||||||
mutable std::string resolved_message;
|
mutable stacktrace resolved_trace;
|
||||||
explicit exception(uint32_t skip) : trace(generate_raw_trace(skip + 1)) {}
|
mutable std::string resolved_what;
|
||||||
virtual const std::string& get_resolved_message() const {
|
explicit exception(uint32_t skip) noexcept
|
||||||
if(resolved_message.empty()) {
|
try : trace(generate_raw_trace(skip + 1)) {}
|
||||||
resolved_message = "cpptrace::exception:\n" + trace.resolve().to_string();
|
catch(const std::exception& e) {
|
||||||
|
if(!detail::should_absorb_trace_exceptions()) {
|
||||||
|
std::rethrow_exception(std::current_exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const stacktrace& get_resolved_trace() const noexcept {
|
||||||
|
// I think a non-empty raw trace can never resolve as empty, so this will accurately prevent resolving more
|
||||||
|
// than once. Either way the raw trace is cleared.
|
||||||
|
try {
|
||||||
|
if(resolved_trace.empty() && !trace.empty()) {
|
||||||
|
resolved_trace = trace.resolve();
|
||||||
trace.clear();
|
trace.clear();
|
||||||
}
|
}
|
||||||
return resolved_message;
|
} catch(const std::exception& e) {
|
||||||
|
if(!detail::should_absorb_trace_exceptions()) {
|
||||||
|
std::rethrow_exception(std::current_exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resolved_trace;
|
||||||
|
}
|
||||||
|
virtual const std::string& get_resolved_what() const noexcept {
|
||||||
|
if(resolved_what.empty()) {
|
||||||
|
resolved_what = "cpptrace::exception:\n" + get_resolved_trace().to_string();
|
||||||
|
}
|
||||||
|
return resolved_what;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
explicit exception() : exception(1) {}
|
explicit exception() noexcept : exception(1) {}
|
||||||
const char* what() const noexcept override {
|
const char* what() const noexcept override {
|
||||||
return get_resolved_message().c_str();
|
return get_resolved_what().c_str();
|
||||||
|
}
|
||||||
|
// what(), but not a C-string
|
||||||
|
const std::string& get_what() const noexcept {
|
||||||
|
return resolved_what;
|
||||||
|
}
|
||||||
|
const raw_trace& get_raw_trace() const noexcept {
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
const stacktrace& get_trace() const noexcept {
|
||||||
|
return resolved_trace;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class exception_with_message : public exception {
|
class exception_with_message : public exception {
|
||||||
protected:
|
protected:
|
||||||
mutable std::string message;
|
mutable std::string message;
|
||||||
explicit exception_with_message(std::string&& message_arg, uint32_t skip)
|
explicit exception_with_message(std::string&& message_arg, uint32_t skip) noexcept
|
||||||
: exception(skip + 1), message(std::move(message_arg)) {}
|
: exception(skip + 1), message(std::move(message_arg)) {}
|
||||||
const std::string& get_resolved_message() const override {
|
const std::string& get_resolved_what() const noexcept override {
|
||||||
if(resolved_message.empty()) {
|
if(resolved_what.empty()) {
|
||||||
resolved_message = message + "\n" + trace.resolve().to_string();
|
resolved_what = message + "\n" + get_resolved_trace().to_string();
|
||||||
trace.clear();
|
|
||||||
message.clear();
|
|
||||||
}
|
}
|
||||||
return resolved_message;
|
return resolved_what;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
explicit exception_with_message(std::string&& message_arg)
|
explicit exception_with_message(std::string&& message_arg) noexcept
|
||||||
: exception_with_message(std::move(message_arg), 1) {}
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
const char* what() const noexcept override {
|
const std::string& get_message() const noexcept {
|
||||||
return get_resolved_message().c_str();
|
return message;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class logic_error : public exception_with_message {
|
class logic_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit logic_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit logic_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class domain_error : public exception_with_message {
|
class domain_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit domain_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit domain_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class invalid_argument : public exception_with_message {
|
class invalid_argument : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit invalid_argument(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit invalid_argument(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class length_error : public exception_with_message {
|
class length_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit length_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit length_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class out_of_range : public exception_with_message {
|
class out_of_range : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit out_of_range(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit out_of_range(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class runtime_error : public exception_with_message {
|
class runtime_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit runtime_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit runtime_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class range_error : public exception_with_message {
|
class range_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit range_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit range_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class overflow_error : public exception_with_message {
|
class overflow_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit overflow_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit overflow_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class underflow_error : public exception_with_message {
|
class underflow_error : public exception_with_message {
|
||||||
public:
|
public:
|
||||||
explicit underflow_error(std::string&& message_arg) : exception_with_message(std::move(message_arg), 1) {}
|
explicit underflow_error(std::string&& message_arg) noexcept
|
||||||
|
: exception_with_message(std::move(message_arg), 1) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_format
|
||||||
|
template <>
|
||||||
|
struct std::formatter<cpptrace::stacktrace_frame> : std::formatter<std::string> {
|
||||||
|
auto format(cpptrace::stacktrace_frame frame, format_context& ctx) const {
|
||||||
|
return formatter<string>::format(frame.to_string(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct std::formatter<cpptrace::stacktrace> : std::formatter<std::string> {
|
||||||
|
auto format(cpptrace::stacktrace trace, format_context& ctx) const {
|
||||||
|
return formatter<string>::format(trace.to_string(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <cpptrace/cpptrace.hpp>
|
#include <cpptrace/cpptrace.hpp>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -25,6 +26,10 @@
|
|||||||
#define CYAN ESC "36m"
|
#define CYAN ESC "36m"
|
||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
|
namespace detail {
|
||||||
|
std::atomic_bool absorb_trace_exceptions = true;
|
||||||
|
}
|
||||||
|
|
||||||
CPPTRACE_API
|
CPPTRACE_API
|
||||||
object_trace raw_trace::resolve_object_trace() const {
|
object_trace raw_trace::resolve_object_trace() const {
|
||||||
return object_trace(detail::get_frames_object_info(frames));
|
return object_trace(detail::get_frames_object_info(frames));
|
||||||
@ -44,6 +49,11 @@ namespace cpptrace {
|
|||||||
frames.clear();
|
frames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API
|
||||||
|
bool raw_trace::empty() const noexcept {
|
||||||
|
return frames.empty();
|
||||||
|
}
|
||||||
|
|
||||||
CPPTRACE_API
|
CPPTRACE_API
|
||||||
stacktrace object_trace::resolve() const {
|
stacktrace object_trace::resolve() const {
|
||||||
return stacktrace(detail::resolve_frames(frames));
|
return stacktrace(detail::resolve_frames(frames));
|
||||||
@ -54,6 +64,41 @@ namespace cpptrace {
|
|||||||
frames.clear();
|
frames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API
|
||||||
|
bool object_trace::empty() const noexcept {
|
||||||
|
return frames.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API std::string stacktrace_frame::to_string() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << *this;
|
||||||
|
return std::move(oss).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame) {
|
||||||
|
stream
|
||||||
|
<< std::hex
|
||||||
|
<< "0x"
|
||||||
|
<< std::setw(2 * sizeof(uintptr_t))
|
||||||
|
<< std::setfill('0')
|
||||||
|
<< frame.address
|
||||||
|
<< std::dec
|
||||||
|
<< std::setfill(' ')
|
||||||
|
<< " in "
|
||||||
|
<< frame.symbol
|
||||||
|
<< " at "
|
||||||
|
<< frame.filename;
|
||||||
|
if(frame.line != 0) {
|
||||||
|
stream
|
||||||
|
<< ":"
|
||||||
|
<< frame.line;
|
||||||
|
if(frame.column != UINT_LEAST32_MAX) {
|
||||||
|
stream << frame.column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
CPPTRACE_API
|
CPPTRACE_API
|
||||||
void stacktrace::print() const {
|
void stacktrace::print() const {
|
||||||
print(std::cerr, true);
|
print(std::cerr, true);
|
||||||
@ -113,11 +158,9 @@ namespace cpptrace {
|
|||||||
<< frame.line
|
<< frame.line
|
||||||
<< (color ? RESET : "");
|
<< (color ? RESET : "");
|
||||||
if(frame.column != UINT_LEAST32_MAX) {
|
if(frame.column != UINT_LEAST32_MAX) {
|
||||||
stream << (
|
stream << (color ? ":" BLUE : ":")
|
||||||
frame.column > 0
|
<< std::to_string(frame.column)
|
||||||
? (color ? ":" BLUE : ":") + std::to_string(frame.column) + (color ? RESET : "")
|
<< (color ? RESET : "");
|
||||||
: ""
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(newline_at_end || &frame != &frames.back()) {
|
if(newline_at_end || &frame != &frames.back()) {
|
||||||
@ -126,6 +169,16 @@ namespace cpptrace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API
|
||||||
|
void stacktrace::clear() {
|
||||||
|
frames.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API
|
||||||
|
bool stacktrace::empty() const noexcept {
|
||||||
|
return frames.empty();
|
||||||
|
}
|
||||||
|
|
||||||
CPPTRACE_API
|
CPPTRACE_API
|
||||||
std::string stacktrace::to_string() const {
|
std::string stacktrace::to_string() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
@ -133,9 +186,8 @@ namespace cpptrace {
|
|||||||
return std::move(oss).str();
|
return std::move(oss).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_API
|
CPPTRACE_API std::ostream& operator<<(std::ostream& stream, const stacktrace& trace) {
|
||||||
void stacktrace::clear() {
|
return stream << trace.to_string();
|
||||||
frames.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||||
@ -162,4 +214,14 @@ namespace cpptrace {
|
|||||||
std::string demangle(const std::string& name) {
|
std::string demangle(const std::string& name) {
|
||||||
return detail::demangle(name);
|
return detail::demangle(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPPTRACE_API void absorb_trace_exceptions(bool absorb) {
|
||||||
|
detail::absorb_trace_exceptions = absorb;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
CPPTRACE_API bool should_absorb_trace_exceptions() {
|
||||||
|
return detail::absorb_trace_exceptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user