Add feature tests for C++20 constexpr and consteval This restores support for building pw_rpc with xtensa-esp32-elf-gcc (crosstool-NG esp-2020r3) 8.4.0. No-Docs-Update-Reason: bug fix Change-Id: Ia8af09844855f130e866c2c42f18230da7962118 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/48701 Commit-Queue: Michael Spang <spang@google.com> Reviewed-by: Wyatt Hepler <hepler@google.com>
diff --git a/pw_bytes/public/pw_bytes/array.h b/pw_bytes/public/pw_bytes/array.h index 453f9ea..5b81229 100644 --- a/pw_bytes/public/pw_bytes/array.h +++ b/pw_bytes/public/pw_bytes/array.h
@@ -20,6 +20,8 @@ #include <cstddef> #include <iterator> +#include "pw_polyfill/language_feature_macros.h" + namespace pw::bytes { namespace internal { @@ -30,7 +32,7 @@ // byte-sized elements or the underlying bytes of an integer (as little-endian). // std::memcpy cannot be used since it is not constexpr. template <typename B, typename T, typename... Args> -consteval void CopyBytes(B* array, T value, Args... args) { +PW_CONSTEVAL void CopyBytes(B* array, T value, Args... args) { static_assert(sizeof(B) == sizeof(std::byte)); if constexpr (UseBytesDirectly<T>) { @@ -56,7 +58,7 @@ // Evaluates to the size in bytes of an integer or byte array. template <typename T> -consteval size_t SizeOfBytes(const T& arg) { +PW_CONSTEVAL size_t SizeOfBytes(const T& arg) { if constexpr (UseBytesDirectly<T>) { return sizeof(arg); } else { @@ -66,12 +68,12 @@ } template <typename B, typename T, size_t... kIndex> -consteval auto String(const T& array, std::index_sequence<kIndex...>) { +PW_CONSTEVAL auto String(const T& array, std::index_sequence<kIndex...>) { return std::array{static_cast<B>(array[kIndex])...}; } template <typename T, typename U> -consteval bool CanBeRepresentedAsByteType(const U& value) { +PW_CONSTEVAL bool CanBeRepresentedAsByteType(const U& value) { return static_cast<U>(static_cast<T>(value)) == value; } @@ -80,7 +82,7 @@ // Concatenates arrays or integers as a byte array at compile time. Integer // values are copied little-endian. Spans are copied byte-for-byte. template <typename B = std::byte, typename... Args> -consteval auto Concat(Args... args) { +PW_CONSTEVAL auto Concat(Args... args) { std::array<B, (internal::SizeOfBytes(args) + ...)> bytes{}; internal::CopyBytes(bytes.begin(), args...); return bytes; @@ -90,27 +92,27 @@ template <typename B = std::byte, size_t kSize, typename Indices = std::make_index_sequence<kSize - 1>> -consteval auto String(const char (&str)[kSize]) { +PW_CONSTEVAL auto String(const char (&str)[kSize]) { return internal::String<B>(str, Indices{}); } // String overload for the empty string "". template <typename B = std::byte> -consteval auto String(const char (&)[1]) { +PW_CONSTEVAL auto String(const char (&)[1]) { return std::array<B, 0>{}; } // Creates an array of bytes from values passed as template parameters. The // values are guaranteed to be representable in the destination byte type. template <typename B, auto... values> -consteval auto Array() { +PW_CONSTEVAL auto Array() { static_assert((internal::CanBeRepresentedAsByteType<B>(values) && ...)); return std::array<B, sizeof...(values)>{static_cast<B>(values)...}; } // Array() defaults to using std::byte. template <auto... values> -consteval auto Array() { +PW_CONSTEVAL auto Array() { return Array<std::byte, values...>(); }
diff --git a/pw_polyfill/public/pw_polyfill/language_feature_macros.h b/pw_polyfill/public/pw_polyfill/language_feature_macros.h index 389493f..60f290c 100644 --- a/pw_polyfill/public/pw_polyfill/language_feature_macros.h +++ b/pw_polyfill/public/pw_polyfill/language_feature_macros.h
@@ -29,3 +29,17 @@ #else #define PW_CONSTEXPR_FUNCTION #endif // __cpp_constexpr >= 201304L + +// Mark functions as constexpr if C++20 or newer +#if __cplusplus >= 202002L +#define PW_CONSTEXPR_CPP20 constexpr +#else +#define PW_CONSTEXPR_CPP20 +#endif // __cpp_constexpr >= 201304L + +// Mark functions as consteval if supported. +#if defined(__cpp_consteval) && __cpp_consteval >= 201811L +#define PW_CONSTEVAL consteval +#else +#define PW_CONSTEVAL PW_CONSTEXPR_FUNCTION +#endif // __cpp_consteval >= 201811L
diff --git a/pw_string/public/pw_string/util.h b/pw_string/public/pw_string/util.h index 6b58308..0b81867 100644 --- a/pw_string/public/pw_string/util.h +++ b/pw_string/public/pw_string/util.h
@@ -73,8 +73,8 @@ // // Precondition: The destination and source shall not overlap. // Precondition: The source shall be a valid pointer. -constexpr StatusWithSize Copy(const std::string_view& source, - std::span<char> dest) { +PW_CONSTEXPR_CPP20 inline StatusWithSize Copy(const std::string_view& source, + std::span<char> dest) { if (dest.empty()) { return StatusWithSize::ResourceExhausted(); } @@ -87,12 +87,15 @@ copied); } -constexpr StatusWithSize Copy(const char* source, std::span<char> dest) { +PW_CONSTEXPR_CPP20 inline StatusWithSize Copy(const char* source, + std::span<char> dest) { PW_DASSERT(source != nullptr); return Copy(ClampedCString(source, dest.size()), dest); } -constexpr StatusWithSize Copy(const char* source, char* dest, size_t num) { +PW_CONSTEXPR_CPP20 inline StatusWithSize Copy(const char* source, + char* dest, + size_t num) { return Copy(source, std::span<char>(dest, num)); }