abort with a descriptive message on bad HintFmt usage
Change-Id: Ic2f05572042343a8160fd971394372f5f2706fc4
This commit is contained in:
parent
80bbfe2034
commit
4e68deef80
2 changed files with 26 additions and 15 deletions
|
@ -1,8 +1,15 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <boost/format.hpp>
|
||||
// Darwin stdenv does not define _GNU_SOURCE but does have _Unwind_Backtrace.
|
||||
#ifdef __APPLE__
|
||||
#define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
|
||||
#endif
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include "ansicolor.hh"
|
||||
|
||||
namespace nix {
|
||||
|
@ -157,23 +164,27 @@ public:
|
|||
*/
|
||||
template<typename... Args>
|
||||
HintFmt(const std::string & format, const Args &... args)
|
||||
: HintFmt(boost::format(format), args...)
|
||||
// Note the function try block.
|
||||
try : fmt(fmt_internal::HintFmt(boost::format(format), args...).into_format())
|
||||
{
|
||||
if (this->fmt.remaining_args() != 0) {
|
||||
// Abort. I don't want anything to catch this, I want a coredump.
|
||||
std::cerr << "HintFmt received incorrect number of format args. Original format string: '";
|
||||
std::cerr << format << "'; number of arguments: " << sizeof...(args) << "\n";
|
||||
// And regardless of the coredump give me a damn stacktrace.
|
||||
std::cerr << boost::stacktrace::stacktrace() << std::endl;
|
||||
abort();
|
||||
}
|
||||
} catch (boost::io::format_error & ex) {
|
||||
// Same thing, but for anything that happens in the member initializers.
|
||||
std::cerr << "HintFmt received incorrect format string. Original format string: '";
|
||||
std::cerr << format << "'; number of arguments: " << sizeof...(args) << "\n";
|
||||
std::cerr << boost::stacktrace::stacktrace() << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
HintFmt(const HintFmt & hf) : fmt(hf.fmt) {}
|
||||
|
||||
template<typename... Args>
|
||||
HintFmt(boost::format && fmt, const Args &... args)
|
||||
: fmt(fmt_internal::HintFmt(std::move(fmt), args...).into_format())
|
||||
{
|
||||
if (this->fmt.remaining_args() != 0) {
|
||||
throw boost::io::too_few_args(
|
||||
this->fmt.bound_args() + this->fmt.fed_args(), this->fmt.expected_args()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
return fmt.str();
|
||||
|
|
|
@ -15,9 +15,9 @@ TEST(HintFmt, arg_count)
|
|||
ASSERT_EQ(HintFmt("%1%", "hello").str(), ANSI_MAGENTA "hello" ANSI_NORMAL);
|
||||
|
||||
// Argument counts are detected at construction.
|
||||
ASSERT_THROW(HintFmt("%s %s", 1), boost::io::too_few_args);
|
||||
ASSERT_DEATH(HintFmt("%s %s", 1), "HintFmt received incorrect");
|
||||
|
||||
ASSERT_THROW(HintFmt("%s", 1, 2), boost::io::too_many_args);
|
||||
ASSERT_DEATH(HintFmt("%s", 1, 2), "HintFmt received incorrect");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue