llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.47k stars 11.77k forks source link

Clang fails to compile consteval because of conflicting rule for variable arrays (?) #105796

Open socketpair opened 1 month ago

socketpair commented 1 month ago

https://godbolt.org/z/dKE6sa4PW

#include <algorithm>
#include <array>

template <std::size_t N>
struct CompTimeStr {
    std::array<char, N> store;

    consteval CompTimeStr(const char (&str)[N]) {
        std::copy_n(str, store.size(), store.data());
    }

    template <std::size_t N2>
    consteval CompTimeStr<N + N2 - 1> operator+(
        const CompTimeStr<N2> str) const {
        char newchar[size() + str.size() + 1];
        std::copy_n(data(), size(), newchar);
        std::copy_n(str.data(), str.size() + 1, newchar + size());
        return newchar;
    }

    consteval std::size_t size() const { return store.size() - 1; }
    consteval const char* data() const { return store.data(); }
};

template <CompTimeStr str>
consteval auto addBar() {
    return str + str;
}

int main() {
    constexpr CompTimeStr str = addBar<"foo">();

    return str.size();
}
frederick-vs-ja commented 1 month ago

At this time you can write char newchar[N + N2 - 1]; instead, which is shorter.

Slightly reduced example (Godbolt link):

#include <cstddef>
#include <type_traits>

template <std::size_t N>
struct record {
    consteval record(std::integral_constant<std::size_t, N>) {}

    template <std::size_t N2>
    consteval std::size_t test_with(const record<N2> other) const {
        constexpr auto len = size() + other.size() + 1; // HERE
        return len;
    }

    consteval std::size_t size() const { return N - 1; }
};

template <record Foo>
consteval auto test_two_records() {
    return Foo.test_with(Foo);
}

int main() {
    constexpr auto n = test_two_records<std::integral_constant<std::size_t, 42>{}>();
}

I believe this is P2280R4 which is tracked in #63139 and will be fixed by #95474.

socketpair commented 1 month ago

@frederick-vs-ja Thank you, I already know how to fix. I just reported obvious bug in Clang.

llvmbot commented 1 month ago

@llvm/issue-subscribers-clang-frontend

Author: Коренберг Марк (socketpair)

https://godbolt.org/z/dKE6sa4PW ```cpp #include <algorithm> #include <array> template <std::size_t N> struct CompTimeStr { std::array<char, N> store; consteval CompTimeStr(const char (&str)[N]) { std::copy_n(str, store.size(), store.data()); } template <std::size_t N2> consteval CompTimeStr<N + N2 - 1> operator+( const CompTimeStr<N2> str) const { char newchar[size() + str.size() + 1]; std::copy_n(data(), size(), newchar); std::copy_n(str.data(), str.size() + 1, newchar + size()); return newchar; } consteval std::size_t size() const { return store.size() - 1; } consteval const char* data() const { return store.data(); } }; template <CompTimeStr str> consteval auto addBar() { return str + str; } int main() { constexpr CompTimeStr str = addBar<"foo">(); return str.size(); } ```
AaronBallman commented 1 month ago

Related: #102970

cor3ntin commented 1 month ago

@shafik