From a0b50c56d15273dc8e6475e826cac7f03c39d51f Mon Sep 17 00:00:00 2001 From: Arthur O'Dwyer Date: Fri, 26 Nov 2021 15:17:21 -0500 Subject: [PATCH] [libc++] [test] C++03-friendly MAKE_STRING macro. Reviewed as part of D114658. --- libcxx/test/support/make_string.h | 121 ++++++++++++++++++------------ 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/libcxx/test/support/make_string.h b/libcxx/test/support/make_string.h index d417d7e1b4df..00c2a48e3d00 100644 --- a/libcxx/test/support/make_string.h +++ b/libcxx/test/support/make_string.h @@ -11,69 +11,92 @@ #include "test_macros.h" -#if TEST_STD_VER < 11 -#error This header requires C++11 or greater -#endif - #include #include -#if TEST_STD_VER > 17 && defined(__cpp_char8_t) -#define CHAR8_ONLY(x) x, -#else -#define CHAR8_ONLY(x) -#endif - #ifndef TEST_HAS_NO_WIDE_CHARACTERS -# define IF_WIDE_CHARACTERS(...) __VA_ARGS__ +# define MKSTR_WCHAR_ONLY(...) __VA_ARGS__ +# define MKSTR_AS_WCHAR_LITERAL(x) TEST_CONCAT(L, x), sizeof(TEST_CONCAT(L, x)) / sizeof(wchar_t) - 1 #else -# define IF_WIDE_CHARACTERS(...) /* nothing */ +# define MKSTR_WCHAR_ONLY(...) #endif -#define MKSTR(Str) \ - { \ - Str, IF_WIDE_CHARACTERS(TEST_CONCAT(L, Str),) \ - CHAR8_ONLY(TEST_CONCAT(u8, Str)) TEST_CONCAT(u, Str), \ - TEST_CONCAT(U, Str) \ - } +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) +#define MKSTR_CHAR8_ONLY(...) __VA_ARGS__ +#define MKSTR_AS_U8_LITERAL(x) TEST_CONCAT(u8, x), sizeof(TEST_CONCAT(u8, x)) / sizeof(char8_t) - 1 +#else +#define MKSTR_CHAR8_ONLY(...) +#endif + +#if TEST_STD_VER >= 11 +#define MKSTR_CXX11_ONLY(...) __VA_ARGS__ +#define MKSTR_AS_U16_LITERAL(x) TEST_CONCAT(u, x), sizeof(TEST_CONCAT(u, x)) / sizeof(char16_t) - 1 +#define MKSTR_AS_U32_LITERAL(x) TEST_CONCAT(U, x), sizeof(TEST_CONCAT(U, x)) / sizeof(char32_t) - 1 +#else +#define MKSTR_CXX11_ONLY(...) +#endif + +#define MKSTR(Str) MultiStringType( \ + MKSTR_WCHAR_ONLY(MKSTR_AS_WCHAR_LITERAL(Str),) \ + MKSTR_CHAR8_ONLY(MKSTR_AS_U8_LITERAL(Str),) \ + MKSTR_CXX11_ONLY(MKSTR_AS_U16_LITERAL(Str), \ + MKSTR_AS_U32_LITERAL(Str),) \ + Str, sizeof(Str) - 1 \ + ) + +#define MKSTR_LEN(CharT, Str) MKSTR(Str).length((const CharT*)0) struct MultiStringType { - const char* s; -#ifndef TEST_HAS_NO_WIDE_CHARACTERS - const wchar_t* w; -#endif -#if TEST_STD_VER > 17 && defined(__cpp_char8_t) - const char8_t* u8; -#endif - const char16_t* u16; - const char32_t* u32; + MKSTR_WCHAR_ONLY(const wchar_t* w_; size_t wn_; ) + MKSTR_CHAR8_ONLY(const char8_t* u8_; size_t u8n_; ) + MKSTR_CXX11_ONLY(const char16_t* u16_; size_t u16n_; ) + MKSTR_CXX11_ONLY(const char32_t* u32_; size_t u32n_; ) + const char* s_; size_t sn_; - constexpr operator const char*() const { return s; } -#ifndef TEST_HAS_NO_WIDE_CHARACTERS - constexpr operator const wchar_t*() const { return w; } -#endif -#if TEST_STD_VER > 17 && defined(__cpp_char8_t) - constexpr operator const char8_t*() const { return u8; } -#endif - constexpr operator const char16_t*() const { return u16; } - constexpr operator const char32_t*() const { return u32; } + TEST_CONSTEXPR MultiStringType( + MKSTR_WCHAR_ONLY(const wchar_t *w, size_t wn,) + MKSTR_CHAR8_ONLY(const char8_t *u8, size_t u8n,) + MKSTR_CXX11_ONLY(const char16_t *u16, size_t u16n,) + MKSTR_CXX11_ONLY(const char32_t *u32, size_t u32n,) + const char *s, size_t sn) + : MKSTR_WCHAR_ONLY(w_(w), wn_(wn),) + MKSTR_CHAR8_ONLY(u8_(u8), u8n_(u8n),) + MKSTR_CXX11_ONLY(u16_(u16), u16n_(u16n),) + MKSTR_CXX11_ONLY(u32_(u32), u32n_(u32n),) + s_(s), sn_(sn) {} + + TEST_CONSTEXPR const char *as_ptr(const char*) const { return s_; } + MKSTR_WCHAR_ONLY(TEST_CONSTEXPR const wchar_t *as_ptr(const wchar_t*) const { return w_; }) + MKSTR_CHAR8_ONLY(constexpr const char8_t *as_ptr(const char8_t*) const { return u8_; }) + MKSTR_CXX11_ONLY(constexpr const char16_t *as_ptr(const char16_t*) const { return u16_; }) + MKSTR_CXX11_ONLY(constexpr const char32_t *as_ptr(const char32_t*) const { return u32_; }) + + TEST_CONSTEXPR size_t length(const char*) const { return sn_; } + MKSTR_WCHAR_ONLY(TEST_CONSTEXPR size_t length(const wchar_t*) const { return wn_; }) + MKSTR_CHAR8_ONLY(constexpr size_t length(const char8_t*) const { return u8n_; }) + MKSTR_CXX11_ONLY(constexpr size_t length(const char16_t*) const { return u16n_; }) + MKSTR_CXX11_ONLY(constexpr size_t length(const char32_t*) const { return u32n_; }) + + // These implicit conversions are used by some tests. TODO: maybe eliminate them? + TEST_CONSTEXPR operator const char*() const { return s_; } + MKSTR_WCHAR_ONLY(TEST_CONSTEXPR operator const wchar_t*() const { return w_; }) + MKSTR_CHAR8_ONLY(constexpr operator const char8_t*() const { return u8_; }) + MKSTR_CXX11_ONLY(constexpr operator const char16_t*() const { return u16_; }) + MKSTR_CXX11_ONLY(constexpr operator const char32_t*() const { return u32_; }) }; -// Helper to convert a const char* string to a basic_string. +// Helper to convert a const char* string to a const CharT*. // This helper is used in unit tests to make them generic. The input should be // valid ASCII which means the input is also valid UTF-8. -#define MAKE_STRING(CharT, Str) \ - std::basic_string { \ - static_cast(MultiStringType MKSTR(Str)) \ - } - -#define MAKE_STRING_VIEW(CharT, Str) \ - std::basic_string_view { \ - static_cast(MultiStringType MKSTR(Str)) \ - } - -// Like MAKE_STRING but converts to a const CharT*. #define MAKE_CSTRING(CharT, Str) \ - static_cast(MultiStringType MKSTR(Str)) + MKSTR(Str).as_ptr((const CharT*)0) + +// Like MAKE_CSTRING but makes a basic_string. Embedded nulls are OK. +#define MAKE_STRING(CharT, Str) \ + std::basic_string(MAKE_CSTRING(CharT, Str), MKSTR_LEN(CharT, Str)) + +// Like MAKE_CSTRING but makes a basic_string_view. Embedded nulls are OK. +#define MAKE_STRING_VIEW(CharT, Str) \ + std::basic_string_view(MAKE_CSTRING(CharT, Str), MKSTR_LEN(CharT, Str)) #endif