diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1449,6 +1449,13 @@ # define _LIBCPP_INIT_PRIORITY_MAX #endif +#ifdef __GNUC__ +# define _LIBCPP_PRINTFILE(fmtarg, firstvararg) \ + __attribute__((__format__(__printf__, fmtarg, firstvararg))) +#else +# define _LIBCPP_PRINTFILE(fmtarg, firstvararg) +#endif + #endif // __cplusplus #endif // _LIBCPP_CONFIG diff --git a/libcxx/src/filesystem/directory_iterator.cpp b/libcxx/src/filesystem/directory_iterator.cpp --- a/libcxx/src/filesystem/directory_iterator.cpp +++ b/libcxx/src/filesystem/directory_iterator.cpp @@ -272,7 +272,7 @@ path root = move(__imp_->__root_); __imp_.reset(); if (m_ec) - err.report(m_ec, "at root \"%s\"", root); + err.report(m_ec, "at root \"%s\"", root.c_str()); } return *this; } @@ -359,7 +359,7 @@ if (m_ec) { path root = move(stack.top().__root_); __imp_.reset(); - err.report(m_ec, "at root \"%s\"", root); + err.report(m_ec, "at root \"%s\"", root.c_str()); } else { __imp_.reset(); } @@ -404,7 +404,7 @@ } else { path at_ent = move(curr_it.__entry_.__p_); __imp_.reset(); - err.report(m_ec, "attempting recursion into \"%s\"", at_ent); + err.report(m_ec, "attempting recursion into \"%s\"", at_ent.c_str()); } } return false; diff --git a/libcxx/src/filesystem/filesystem_common.h b/libcxx/src/filesystem/filesystem_common.h --- a/libcxx/src/filesystem/filesystem_common.h +++ b/libcxx/src/filesystem/filesystem_common.h @@ -57,8 +57,8 @@ namespace { -static string format_string_imp(const char* msg, ...) { - // we might need a second shot at this, so pre-emptivly make a copy +static _LIBCPP_PRINTFILE(1, 0) string + format_string_impl(const char* msg, va_list& args) { struct GuardVAList { va_list& target; bool active = true; @@ -73,10 +73,9 @@ va_end(target); } }; - va_list args; - va_start(args, msg); - GuardVAList args_guard(args); + GuardVAList args_guard(args); + // we might need a second shot at this, so pre-emptivly make a copy va_list args_cp; va_copy(args_cp, args); GuardVAList args_copy_guard(args_cp); @@ -103,22 +102,16 @@ size_with_null = static_cast(ret) + 1; result.__resize_default_init(size_with_null - 1); ret = ::vsnprintf(&result[0], size_with_null, msg, args); + args_guard.clear(); _LIBCPP_ASSERT(static_cast(ret) == (size_with_null - 1), "TODO"); return result; } -const path::value_type* unwrap(path::string_type const& s) { return s.c_str(); } -const path::value_type* unwrap(path const& p) { return p.native().c_str(); } -template -Arg const& unwrap(Arg const& a) { - static_assert(!is_class::value, "cannot pass class here"); - return a; -} - -template -string format_string(const char* fmt, Args const&... args) { - return format_string_imp(fmt, unwrap(args)...); +static _LIBCPP_PRINTFILE(1, 2) string format_string(const char* msg, ...) { + va_list args; + va_start(args, msg); + return format_string_impl(msg, args); } error_code capture_errno() { @@ -190,14 +183,15 @@ _LIBCPP_UNREACHABLE(); } - template - T report(const error_code& ec, const char* msg, Args const&... args) const { + _LIBCPP_PRINTFILE(3, 0) + T report_impl(const error_code& ec, const char* msg, va_list& args) const { if (ec_) { + va_end(args); *ec_ = ec; return error_value(); } string what = - string("in ") + func_name_ + ": " + format_string(msg, args...); + string("in ") + func_name_ + ": " + format_string_impl(msg, args); switch (bool(p1_) + bool(p2_)) { case 0: __throw_filesystem_error(what, ec); @@ -209,11 +203,20 @@ _LIBCPP_UNREACHABLE(); } + _LIBCPP_PRINTFILE(3, 4) + T report(const error_code& ec, const char* msg, ...) const { + va_list args; + va_start(args, msg); + return report_impl(ec, msg, args); + } + T report(errc const& err) const { return report(make_error_code(err)); } - template - T report(errc const& err, const char* msg, Args const&... args) const { - return report(make_error_code(err), msg, args...); + _LIBCPP_PRINTFILE(3, 4) + T report(errc const& err, const char* msg, ...) const { + va_list args; + va_start(args, msg); + return report_impl(make_error_code(err), msg, args); } private: diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -1447,11 +1447,11 @@ error_code m_ec; file_status st = detail::posix_stat(p, &m_ec); if (!status_known(st)) - return err.report(m_ec, "cannot access path \"" PS_FMT "\"", p); + return err.report(m_ec, "cannot access path \"" PS_FMT "\"", p.c_str()); if (!exists(st) || !is_directory(st)) - return err.report(errc::not_a_directory, "path \"" PS_FMT "\" is not a directory", - p); + return err.report(errc::not_a_directory, + "path \"" PS_FMT "\" is not a directory", p.c_str()); return p; }