public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/106889] New: __builtin_strlen fails for some constexpr constructs
@ 2022-09-08  9:46 m.cencora at gmail dot com
  2022-09-08 16:48 ` [Bug c++/106889] " redi at gcc dot gnu.org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: m.cencora at gmail dot com @ 2022-09-08  9:46 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 106889
           Summary: __builtin_strlen fails for some constexpr constructs
           Product: gcc
           Version: 10.4.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: m.cencora at gmail dot com
  Target Milestone: ---

Compiling following program on any gcc version, with C++14 or newer standard
fails with
"'__builtin_strlen(...)' is not a constant expression" for some of the static
asserts.

It compiles successfuly on clang.


g++ -std=c++14

constexpr unsigned constexpr_strlen(const char* str)
{
#ifdef WORKAROUND
    if (!__builtin_constant_p(str))
    {
        unsigned i = 0;
        while (str[i] != '\0')
        {
           ++i;
        }
        return i;
    }
#endif
    return __builtin_strlen(str);
}

struct StaticString
{
    constexpr StaticString(const char (&src)[4])
        : buf{src[0], src[1], src[2], src[3]}
    {}

    constexpr const char* data() const
    {
        return &buf[0];
    }

    char buf[4];
};

constexpr StaticString createStaticString()
{
    return {"foo"};
}

constexpr const char *s1 = "foo";
constexpr const char s2[] = "foo";
constexpr StaticString s3{"foo"};
constexpr StaticString s4 = s2;
constexpr StaticString s5 = s4;
constexpr StaticString s6 = createStaticString();

void test()
{
    constexpr const char *s7 = "foo";
    constexpr const char s8[] = "foo";
    constexpr StaticString s9{"foo"};
    constexpr StaticString s10 = s8;
    constexpr StaticString s11 = s10;
    constexpr StaticString s12 = createStaticString();

    static constexpr const char *s13 = "foo";
    static constexpr const char s14[] = "foo";
    static constexpr StaticString s15{"foo"};
    static constexpr StaticString s16 = s14;
    static constexpr StaticString s17 = s6;
    static constexpr StaticString s18 = createStaticString();

    static_assert(constexpr_strlen(s1) == 3, "");
    static_assert(constexpr_strlen(s2) == 3, "");
    static_assert(constexpr_strlen(s3.data()) == 3, "");
    static_assert(constexpr_strlen(s4.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s5.data()) == 3, ""); // ERROR 
    static_assert(constexpr_strlen(s6.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s7) == 3, "");
    static_assert(constexpr_strlen(s8) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s9.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s10.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s11.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s12.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s13) == 3, "");
    static_assert(constexpr_strlen(s14) == 3, "");
    static_assert(constexpr_strlen(s15.data()) == 3, "");
    static_assert(constexpr_strlen(s16.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s17.data()) == 3, ""); // ERROR
    static_assert(constexpr_strlen(s18.data()) == 3, ""); // ERROR
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/106889] __builtin_strlen fails for some constexpr constructs
  2022-09-08  9:46 [Bug c++/106889] New: __builtin_strlen fails for some constexpr constructs m.cencora at gmail dot com
@ 2022-09-08 16:48 ` redi at gcc dot gnu.org
  2022-09-08 16:54 ` jakub at gcc dot gnu.org
  2022-09-08 18:28 ` redi at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: redi at gcc dot gnu.org @ 2022-09-08 16:48 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
You can either use char_traits<char>::length (which is actually required to
work in constexpr) or use __builtin_is_constant_evaluated() instead of your
workaround.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/106889] __builtin_strlen fails for some constexpr constructs
  2022-09-08  9:46 [Bug c++/106889] New: __builtin_strlen fails for some constexpr constructs m.cencora at gmail dot com
  2022-09-08 16:48 ` [Bug c++/106889] " redi at gcc dot gnu.org
@ 2022-09-08 16:54 ` jakub at gcc dot gnu.org
  2022-09-08 18:28 ` redi at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-09-08 16:54 UTC (permalink / raw)
  To: gcc-bugs

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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
__builtin_strlen like many other string/memory builtins simply tries the
middle-end folding and gives up otherwise.  So if it is called on a string
literal, it is folded, but if it would require reading the bytes of the string
one by one, it will most likely fail.
This has been discussed in some other PR that we should have a helper that
allows constexpr.cc to read a single character and as fallback for the string
builtins call those in a loop and essentially evaluate the builtins as a
non-optimized trivial C++ implementation of those builtins.
I think std::strlen isn't constexpr even in latest C++, so all of this is
permitted by the standard...

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/106889] __builtin_strlen fails for some constexpr constructs
  2022-09-08  9:46 [Bug c++/106889] New: __builtin_strlen fails for some constexpr constructs m.cencora at gmail dot com
  2022-09-08 16:48 ` [Bug c++/106889] " redi at gcc dot gnu.org
  2022-09-08 16:54 ` jakub at gcc dot gnu.org
@ 2022-09-08 18:28 ` redi at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: redi at gcc dot gnu.org @ 2022-09-08 18:28 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #2)
> I think std::strlen isn't constexpr even in latest C++, so all of this is
> permitted by the standard...

Right, which is why I recommend using char_traits::length instead.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-09-08 18:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-08  9:46 [Bug c++/106889] New: __builtin_strlen fails for some constexpr constructs m.cencora at gmail dot com
2022-09-08 16:48 ` [Bug c++/106889] " redi at gcc dot gnu.org
2022-09-08 16:54 ` jakub at gcc dot gnu.org
2022-09-08 18:28 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).