https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108269

            Bug ID: 108269
           Summary: Incorrect __PRETTY_FUNCTION__ with std::array<char> in
                    C++20 NTTP literal
           Product: gcc
           Version: 13.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: camden.mannett at gmail dot com
  Target Milestone: ---

Created attachment 54176
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54176&action=edit
Source code

When std::array<char, N> is used within a literal type that is used as an NTTP,
it _looks_ like the __PRETTY_FUNCTION__ output always assumes that it is a
null-terminated string which is then displayed without the last character - but
it is not always a null!

It is simplest to demonstrate with a compile-time string implementation
(https://godbolt.org/z/8EnPfeWq7):

#include <algorithm>
#include <array>
#include <iostream>

namespace {
template<typename T>
class type_string_t
{
    [[nodiscard]] constexpr static std::string_view generate() noexcept
    {
        constexpr auto sig =
          std::string_view{ static_cast<const char*>(__PRETTY_FUNCTION__) };
        return sig;
    }

  public:
    constexpr static auto value = generate();
};

template<typename T>
constexpr auto type_string = type_string_t<T>::value;

template<std::size_t N>
class str_storage
{
  public:
    constexpr str_storage(const char (&str)[N])
    {
        std::copy_n(&str[0], N, value.begin());
    }

    constexpr str_storage(char c)
      : value{ c }
    {
    }

    std::array<char, N> value;
};
str_storage(char) -> str_storage<1>;

template<str_storage S>
struct str
{};
}

int
main()
{
    std::cout << type_string<str<'a'>> << "\n"
              << type_string<str<"a">> << "\n"
              << type_string<str<"hello">> << std::endl;
    return 0;
}

This yields pretty much what you would expect when built via Clang (after
removal of cruft):

(anonymous namespace)::str<{{{97}}}>
(anonymous namespace)::str<{{"a"}}>
(anonymous namespace)::str<{{"hello"}}>

However gcc does something different when the std::array contains only a single
char:

{anonymous}::str<{anonymous}::str_storage<1>{std::array<char, 1>{""}}>
{anonymous}::str<{anonymous}::str_storage<2>{std::array<char, 2>{"a"}}>
{anonymous}::str<{anonymous}::str_storage<6>{std::array<char, 6>{"hello"}}>

It seems to always represent the char array as a null-terminated string
literal, which isn't always true.

Reply via email to