On the mingw32 target, std::system_category().message(int) uses
FormatMessage api to format error messages. When the error message contains
insert sequences, it is unsafe not to use the FORMAT_MESSAGE_OGNORE_INSERTS
flag, as seen at:
https://devblogs.microsoft.com/oldnewthing/20071128-00/?p=24353
The output of FormatMessage ends with "\r\n" and includes a Full stop character
used by the current thread's UI language. Now, we will remove "\r\n" and
any trailing '.' from the output in any language environment.
In the testsuite for std::system_category().message(int), we first switch the
thread UI language to en-US tomeet expectations in any language environment.
libstdc++-v3/ChangeLog:
* src/c++11/system_error.cc (system_error_category) [_WIN32]:
Fix typo in __MINGW32__ macro name.
Adjust behavior on the mingw32 target.
Use FormatMessageA function instead of FormatMessage macro.
* testsuite/19_diagnostics/error_category/system_category.cc:
Adjust behavior on the mingw32 target.
---
libstdc++-v3/src/c++11/system_error.cc | 21 ++++++++++---------
.../error_category/system_category.cc | 18 +++++++++++++---
2 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/libstdc++-v3/src/c++11/system_error.cc
b/libstdc++-v3/src/c++11/system_error.cc
index 548c88fcfde..7e3a3a0c904 100644
--- a/libstdc++-v3/src/c++11/system_error.cc
+++ b/libstdc++-v3/src/c++11/system_error.cc
@@ -161,22 +161,23 @@ namespace
#if defined(_WIN32) && !defined(__CYGWIN__)
char* buf = nullptr;
auto len
- = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
- | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- nullptr,
- i,
- LANG_USER_DEFAULT,
- reinterpret_cast<LPTSTR>(&buf),
- 0,
- nullptr);
+ = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr,
+ i,
+ LANG_USER_DEFAULT,
+ reinterpret_cast<LPTSTR>(&buf),
+ 0,
+ nullptr);
if (len > 0)
{
struct deleter {
void operator()(void* p) const { ::LocalFree(p); }
};
std::unique_ptr<char[], deleter> guard(buf);
- if (len > 3 && !__builtin_memcmp(buf + len - 3, ".\r\n", 3)) [[likely]]
- len -= 3;
+ if (len > 2 && !__builtin_memcmp (buf + len - 2, "\r\n", 2)) [[likely]]
+ len -= 2 + (buf[len - 3] == '.');
return string(buf, len);
}
return string("Unknown error code");
diff --git
a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
index 250d34f9bb5..03577234c43 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
@@ -21,6 +21,11 @@
#include <locale>
#include <testsuite_hooks.h>
+#if defined __MINGW32__ || defined __MINGW64__
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
void
test01()
{
@@ -34,7 +39,7 @@ test02()
const std::error_category& cat = std::system_category();
std::error_condition cond;
-#if defined __MING32__ || defined __MINGW64__
+#if defined __MINGW32__ || defined __MINGW64__
cond = cat.default_error_condition(8); // ERROR_NOT_ENOUGH_MEMORY
VERIFY( cond.value() == ENOMEM );
VERIFY( cond.category() == std::generic_category() );
@@ -112,9 +117,16 @@ test03()
// set "C" locale to get expected message
auto loc = std::locale::global(std::locale::classic());
-#if defined __MING32__ || defined __MINGW64__
+#if defined __MINGW32__ || defined __MINGW64__
+ // On Windows, set thread preferred UI languages to "en-US"
+ // to get expected message
+ ULONG num_langs = 1;
+ SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, L"en-US\0", &num_langs);
+
std::string msg = std::system_category().message(5); // ERROR_ACCESS_DENIED
- VERIFY(msg == "Access denied");
+ VERIFY(msg == "Access is denied");
+
+ SetThreadPreferredUILanguages(MUI_RESET_FILTERS, nullptr, nullptr);
#else
std::string msg = std::system_category().message(EBADF);
VERIFY( msg.find("file") != std::string::npos );
--
2.52.0