fmtlib / fmt

A modern formatting library
https://fmt.dev
Other
20.74k stars 2.49k forks source link

NVCC error with -std=c++20 #3543

Closed alexeedm closed 1 year ago

alexeedm commented 1 year ago

The repro code is very simple:

// test.cu
#include <format.h>
int main() { return 0; }

By default NVCC 12.2 compiles this code just fine, but when c++20 standard is used a few errors are thrown:

fmt/include/fmt/core.h: In function 'constexpr bool fmt::v10::detail::is_constant_evaluated(bool)':
fmt/include/fmt/core.h:314:14: error: call to non-'constexpr' function 'void fmt::v10::detail::ignore_unused(const T& ...) [with T = {bool}]'
  314 |   ignore_unused(default_value);
      |   ~~~~~~~~~~~^~~~~~~~~~~~~~~
fmt/include/fmt/core.h:301:28: note: 'void fmt::v10::detail::ignore_unused(const T& ...) [with T = {bool}]' declared here
  301 | template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
      |                            ^~~~~~~~~~~~~
fmt/include/fmt/format.h: In function 'constexpr int fmt::v10::detail::count_digits(uint64_t)':
fmt/include/fmt/format.h:1228:29: error: call to non-'constexpr' function 'int fmt::v10::detail::count_digits_fallback(T) [with T = long unsigned int]'
 1228 |   return count_digits_fallback(n);
      |        ~~~~~~~~~~~~~~~~~~~~~^~~
fmt/include/fmt/format.h:1179:25: note: 'int fmt::v10::detail::count_digits_fallback(T) [with T = long unsigned int]' declared here
 1179 | template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
      |                         ^~~~~~~~~~~~~~~~~~~~~
fmt/include/fmt/format.h: In function 'constexpr int fmt::v10::detail::count_digits(uint32_t)':
fmt/include/fmt/format.h:1280:29: error: call to non-'constexpr' function 'int fmt::v10::detail::count_digits_fallback(T) [with T = unsigned int]'
 1280 |   return count_digits_fallback(n);

The issue apparently is resolved when the NVCC-specific workaround is just removed from here: https://github.com/fmtlib/fmt/blob/master/include/fmt/core.h#L95

vitaut commented 1 year ago

Removing the NVCC workaround might have some other negative effects so I think a better solution is to make ignore_unused always constexpr:

template <typename... T> constexpr int ignore_unused(const T&...) { return 0; }

(we need a non-void return type for C++11)

A PR would be welcome.

alexeedm commented 1 year ago

Yeah, I believe this workaround was introduced for a reason. Maybe then remove it if C++ standard is >= 20? Because there are actually more similar errors for different functions. The full error output is like this:

fmt/include/fmt/core.h: In function 'constexpr bool fmt::v10::detail::is_constant_evaluated(bool)':
fmt/include/fmt/core.h:314:14: error: call to non-'constexpr' function 'void fmt::v10::detail::ignore_unused(const T& ...) [with T = {bool}]'
  314 |   ignore_unused(default_value);
      |   ~~~~~~~~~~~^~~~~~~~~~~~~~~
fmt/include/fmt/core.h:301:28: note: 'void fmt::v10::detail::ignore_unused(const T& ...) [with T = {bool}]' declared here
  301 | template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
      |                            ^~~~~~~~~~~~~
fmt/include/fmt/format.h: In function 'constexpr int fmt::v10::detail::count_digits(uint64_t)':
fmt/include/fmt/format.h:1228:29: error: call to non-'constexpr' function 'int fmt::v10::detail::count_digits_fallback(T) [with T = long unsigned int]'
 1228 |   return count_digits_fallback(n);
      |        ~~~~~~~~~~~~~~~~~~~~~^~~
fmt/include/fmt/format.h:1179:25: note: 'int fmt::v10::detail::count_digits_fallback(T) [with T = long unsigned int]' declared here
 1179 | template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
      |                         ^~~~~~~~~~~~~~~~~~~~~
fmt/include/fmt/format.h: In function 'constexpr int fmt::v10::detail::count_digits(uint32_t)':
fmt/include/fmt/format.h:1280:29: error: call to non-'constexpr' function 'int fmt::v10::detail::count_digits_fallback(T) [with T = unsigned int]'
 1280 |   return count_digits_fallback(n);
      |        ~~~~~~~~~~~~~~~~~~~~~^~~
fmt/include/fmt/format.h:1179:25: note: 'int fmt::v10::detail::count_digits_fallback(T) [with T = unsigned int]' declared here
 1179 | template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
      |                         ^~~~~~~~~~~~~~~~~~~~~
fmt/include/fmt/format.h: In member function 'constexpr fmt::v10::detail::bigint::bigit fmt::v10::detail::bigint::operator[](int) const':
fmt/include/fmt/format.h:2809:36: error: call to non-'constexpr' function 'const T& fmt::v10::detail::buffer<T>::operator[](Idx) const [with Idx = unsigned int; T = unsigned int]'
 2809 |     return bigits_[to_unsigned(index)];
      |                                    ^
fmt/include/fmt/core.h:873:1: note: 'const T& fmt::v10::detail::buffer<T>::operator[](Idx) const [with Idx = unsigned int; T = unsigned int]' declared here
  873 |   FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
      | ^ ~~~~~~
fmt/include/fmt/format.h: In member function 'constexpr fmt::v10::detail::bigint::bigit& fmt::v10::detail::bigint::operator[](int)':
fmt/include/fmt/format.h:2812:36: error: call to non-'constexpr' function 'T& fmt::v10::detail::buffer<T>::operator[](Idx) [with Idx = unsigned int; T = unsigned int]'
 2812 |     return bigits_[to_unsigned(index)];
      |                                    ^
fmt/include/fmt/core.h:869:27: note: 'T& fmt::v10::detail::buffer<T>::operator[](Idx) [with Idx = unsigned int; T = unsigned int]' declared here
  869 |   template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
      |                           ^~~~~~~~
fmt/include/fmt/format.h: In member function 'constexpr void fmt::v10::detail::bigint::remove_leading_zeros()':
fmt/include/fmt/format.h:2828:29: error: call to non-'constexpr' function 'typename std::make_unsigned<Int>::type fmt::v10::detail::to_unsigned(Int) [with Int = int; typename std::make_unsigned<Int>::type = unsigned int]'
 2828 |     bigits_.resize(to_unsigned(num_bigits + 1));
      |                  ~~~~~~~~~~~^~~~~~~~~~~~~~~~
fmt/include/fmt/core.h:373:1: note: 'typename std::make_unsigned<Int>::type fmt::v10::detail::to_unsigned(Int) [with Int = int; typename std::make_unsigned<Int>::type = unsigned int]' declared here
  373 | FMT_CONSTEXPR auto to_unsigned(Int value) ->
      | ^~~~~~~~~~~
fmt/include/fmt/format.h: In member function 'constexpr void fmt::v10::detail::bigint::assign(const fmt::v10::detail::bigint&)':
fmt/include/fmt/format.h:2897:33: error: call to non-'constexpr' function 'const T* fmt::v10::detail::buffer<T>::data() const [with T = unsigned int]'
 2897 |     auto data = other.bigits_.data();
      |             ~~~~~~~~~~~~~~~~~~~~^~
fmt/include/fmt/core.h:841:6: note: 'const T* fmt::v10::detail::buffer<T>::data() const [with T = unsigned int]' declared here
  841 |   FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
      |      ^~~~
fmt/include/fmt/format.h: In member function 'constexpr void fmt::v10::detail::bigint::square()':
fmt/include/fmt/format.h:2998:29: error: call to non-'constexpr' function 'typename std::make_unsigned<Int>::type fmt::v10::detail::to_unsigned(Int) [with Int = int; typename std::make_unsigned<Int>::type = unsigned int]'
 2998 |     bigits_.resize(to_unsigned(num_result_bigits));
      |                  ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
fmt/include/fmt/core.h:373:1: note: 'typename std::make_unsigned<Int>::type fmt::v10::detail::to_unsigned(Int) [with Int = int; typename std::make_unsigned<Int>::type = unsigned int]' declared here
  373 | FMT_CONSTEXPR auto to_unsigned(Int value) ->
      | ^~~~~~~~~~~
vitaut commented 1 year ago

Fine with me. You are in a better position to test NVCC anyway =).

alexeedm commented 1 year ago

Right :) I'm not the biggest C++ expert out there though... Anyway, I've tested this fix with NVCC 12.2 and it works with all the c++ standards supported. Submitted PR #3544