Use FormatMessageA instead of th FormatMessage macro.
Add FORMAT_MESSAGE_IGNORE_INSERTS flag to FormatMessageA avoids
ERROR_INVALID_PARAMETER (error code 87), which is recommended in:
https://devblogs.microsoft.com/oldnewthing/20071128-00/?p=24353
To ensure that the trailing "\r\n" is correctly removed when using other
periods (other than U+002E, such as Idengraphic FullStop(U+3002))
at the end of error message.
Before testing std::system_category().message(int), set the thread preferred
language to en-US so that the returned string can meet expectations in
various language environments.
libstdc++-v3/ChangeLog:
* src/c++11/system_error.cc (system_error_category) [_WIN32]:
Fix typo in __MINGW32__ macro name.
Fix behavioral issus in some situations.
* testsuite/19_diagnostics/error_category/system_category.cc:
Adujust for behaviour on Windows.
---
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 b9a0b2c158f..dec65081b8e 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 196a15347a6..6c90f0f730c 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