Skip to content

consteval and constexpr static variable do not work well together #141563

Closed as duplicate of#82994
@fekir

Description

@fekir

Consider following example (https://godbolt.org/z/cdTfehb3e)

#include <iostream>
#include <string_view>

#define USECONSTEVAL
#ifdef USECONSTEVAL
#define CEXPR consteval
#else
#define CEXPR constexpr
#endif

CEXPR std::string_view name(){
    return __PRETTY_FUNCTION__;
}

CEXPR std::string_view name2(){
  constexpr auto function = std::string_view(__PRETTY_FUNCTION__);
  constexpr static auto value = [] <std::size_t...Idxs>(std::string_view str, std::index_sequence<Idxs...>)
  {
    return std::array{str[Idxs]..., '\0'};
  }(function, std::make_index_sequence<function.size()>{});
  static_assert(!std::string_view(value).empty());
  return std::string_view(value);
}


template <std::size_t...Idxs>
constexpr auto substring_as_array(std::string_view str, std::index_sequence<Idxs...>)
{
  return std::array{str[Idxs]..., '\0'};
}

CEXPR std::string_view name3(){
  constexpr auto function = std::string_view(__PRETTY_FUNCTION__);
  constexpr static auto value = substring_as_array(function, std::make_index_sequence<function.size()>{});
  static_assert(!std::string_view(value).empty());
  return std::string_view(value);
}

struct helper {
  static constexpr std::string_view value = name();
};
CEXPR std::string_view name4(){
  constexpr auto value = helper::value;
  return std::string_view{value.data(), value.size()};
}

int main(){
    static_assert(not name().empty());
    std::cout << "__PRETTY_FUNCTION__: \"" << name() << "\"\n";
    static_assert(not name2().empty());
    std::cout << "__PRETTY_FUNCTION__: \"" << name2() << "\"\n";
    static_assert(not name3().empty());
    std::cout << "__PRETTY_FUNCTION__: \"" << name3() << "\"\n";
    static_assert(not name4().empty());
    std::cout << "__PRETTY_FUNCTION__: \"" << name4() << "\"\n";
}

by toggling the macro USECONSTEVAL, the output of this sample program changes from

__PRETTY_FUNCTION__: "std::string_view name()"
__PRETTY_FUNCTION__: "std::string_view name2()"
__PRETTY_FUNCTION__: "std::string_view name3()"
__PRETTY_FUNCTION__: "std::string_view name()"

to

__PRETTY_FUNCTION__: "std::string_view name()"
__PRETTY_FUNCTION__: ""
__PRETTY_FUNCTION__: ""
__PRETTY_FUNCTION__: "std::string_view name()"

To the best of my knowledge, there is no reason why consteval instead of constexpr should change the meaning of the functions name2 and name3.

Confusingly, none of the static_assert that check for emptiness fail, even when the return value is in fact empty.

In case it is relevant, GCC is not affected by this issue, the behavior between constexpr and consteval is consistent

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++23clang:codegenIR generation bugs: mangling, exceptions, etc.clang:frontendLanguage frontend issues, e.g. anything involving "Sema"constevalC++20 constevalduplicateResolved as duplicate

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions