On Mon, Mar 02, 2026 at 01:08:56AM +0200, Jean-Christian CÎRSTEA wrote:
> Before this commit, attempting to use non-ASCII characters in quoted
> words failed, even though the protocol allows the usage of such
> characters in quoted words. To fix this:
>
> 1. Remove `c >= 0x7f` comparison when parsing a quoted word.
> 2. Use `unsigned char` instead of `char` such that `c < 0x20` fails for
> non-ASCII characters.
>
> PR c++/120458
>
> libcody/ChangeLog:
>
> * buffer.cc (S2C): Allow non-ASCII chars in quoted words.
> * cody.hh: Use unsigned char for S2C().
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/README: Explain purpose of modules/ dir.
> * g++.dg/modules/pr120458_a.C: New test.
> * g++.dg/modules/pr120458_b.C: New test.
> * g++.dg/mdoules/pr120458.map: Module mapping for new test.
>
> Signed-off-by: Jean-Christian CÎRSTEA <[email protected]>
> ---
> Changelog v3:
>
> 1. Set test encoding to UTF-8
> 2. Use module mapper for tests instead of names
>
Sorry if I wasn't clear in my earlier message, I meant have two tests:
one using the implicit module mapper (no `-fmodule-mapper`), and the
other using an explicit one.
But otherwise this change LGTM. I've CC'd Jason to make the final call.
Nathaniel
> Changelog v2:
>
> 1. Fixed changelog entries
> 2. Use East-Asian characters for test
>
> gcc/testsuite/g++.dg/README | 1 +
> gcc/testsuite/g++.dg/modules/pr120458.map | 3 +++
> gcc/testsuite/g++.dg/modules/pr120458_a.C | 11 +++++++++++
> gcc/testsuite/g++.dg/modules/pr120458_b.C | 11 +++++++++++
> libcody/buffer.cc | 6 +++---
> libcody/cody.hh | 4 ++--
> 6 files changed, 31 insertions(+), 5 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/modules/pr120458.map
> create mode 100644 gcc/testsuite/g++.dg/modules/pr120458_a.C
> create mode 100644 gcc/testsuite/g++.dg/modules/pr120458_b.C
>
> diff --git a/gcc/testsuite/g++.dg/README b/gcc/testsuite/g++.dg/README
> index a7b3d5b783b..3301f17b4df 100644
> --- a/gcc/testsuite/g++.dg/README
> +++ b/gcc/testsuite/g++.dg/README
> @@ -15,6 +15,7 @@ inherit Tests for inheritance -- virtual functions,
> multiple inheritance, etc.
> init Tests for initialization semantics, constructors/destructors, etc.
> lookup Tests for lookup semantics, namespaces, using, etc.
> lto Tests for Link Time Optimization.
> +modules Tests for C++20 modules.
> opt Tests for fixes of bugs with particular optimizations.
> overload Tests for overload resolution and conversions.
> parse Tests for parsing.
> diff --git a/gcc/testsuite/g++.dg/modules/pr120458.map
> b/gcc/testsuite/g++.dg/modules/pr120458.map
> new file mode 100644
> index 00000000000..87574377400
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/pr120458.map
> @@ -0,0 +1,3 @@
> +$root .
> +汉字 pr120458_a.gcm
> +étrange pr120458_b.gcm
> diff --git a/gcc/testsuite/g++.dg/modules/pr120458_a.C
> b/gcc/testsuite/g++.dg/modules/pr120458_a.C
> new file mode 100644
> index 00000000000..525cf4d68f8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/pr120458_a.C
> @@ -0,0 +1,11 @@
> +// { dg-module-do run}
> +// { dg-additional-options "-fmodules -fmodule-mapper=[srcdir]/pr120458.map
> " }
> +// { dg-additional-options "-finput-charset=UTF-8"
> +// { dg-additional-files "pr120458.map" }
> +
> +export module 汉字;
> +// { dg-module-cmi "=pr120458_a.gcm" }
> +
> +export unsigned f(unsigned x) {
> + return x + 3;
> +}
> diff --git a/gcc/testsuite/g++.dg/modules/pr120458_b.C
> b/gcc/testsuite/g++.dg/modules/pr120458_b.C
> new file mode 100644
> index 00000000000..281422fb3ff
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/pr120458_b.C
> @@ -0,0 +1,11 @@
> +// { dg-additional-options "-fmodules -fmodule-mapper=[srcdir]/pr120458.map
> " }
> +// { dg-additional-options "-finput-charset=UTF-8"
> +
> +export module étrange;
> +// { dg-module-cmi "=pr120458_b.gcm" }
> +
> +import 汉字;
> +
> +export unsigned g(unsigned x) {
> + return f(x) * 7;
> +}
> diff --git a/libcody/buffer.cc b/libcody/buffer.cc
> index 85c066fef71..d27882b7d4a 100644
> --- a/libcody/buffer.cc
> +++ b/libcody/buffer.cc
> @@ -30,7 +30,7 @@
> namespace Cody {
> namespace Detail {
>
> -static const char CONTINUE = S2C(u8";");
> +static const unsigned char CONTINUE = S2C(u8";");
>
> void MessageBuffer::BeginLine ()
> {
> @@ -239,7 +239,7 @@ int MessageBuffer::Lex (std::vector<std::string> &result)
>
> for (std::string *word = nullptr;;)
> {
> - char c = *iter;
> + unsigned char c = *iter;
>
> ++iter;
> if (c == S2C(u8" ") || c == S2C(u8"\t"))
> @@ -292,7 +292,7 @@ int MessageBuffer::Lex (std::vector<std::string> &result)
> return EINVAL;
> }
>
> - if (c < S2C(u8" ") || c >= 0x7f)
> + if (c < S2C(u8" "))
> goto malformed;
>
> ++iter;
> diff --git a/libcody/cody.hh b/libcody/cody.hh
> index 93bce93aa94..7c852eb3aa1 100644
> --- a/libcody/cody.hh
> +++ b/libcody/cody.hh
> @@ -49,14 +49,14 @@ namespace Detail {
>
> #if __cpp_char8_t >= 201811
> template<unsigned I>
> -constexpr char S2C (char8_t const (&s)[I])
> +constexpr unsigned char S2C (char8_t const (&s)[I])
> {
> static_assert (I == 2, "only single octet strings may be converted");
> return s[0];
> }
> #else
> template<unsigned I>
> -constexpr char S2C (char const (&s)[I])
> +constexpr unsigned char S2C (char const (&s)[I])
> {
> static_assert (I == 2, "only single octet strings may be converted");
> return s[0];
> --
> 2.53.0
>