diff --git a/include/boost/static_string/config.hpp b/include/boost/static_string/config.hpp index 3c91f26..3d12242 100644 --- a/include/boost/static_string/config.hpp +++ b/include/boost/static_string/config.hpp @@ -35,12 +35,10 @@ // Can we use is_constant_evaluated? // Standard version #if __cpp_lib_is_constant_evaluated >= 201811L -#define BOOST_STATIC_STRING_USE_IS_CONST_EVAL #define BOOST_STATIC_STRING_IS_CONST_EVAL std::is_constant_evaluated() -#elif defined(__clang__) && (__clang_major__ > 8) +#elif defined(__clang__) && __has_builtin(__builtin_is_constant_evaluated) // If we have clang version 9+, we can use the intrinsic // While gcc also has this, we don't need it -#define BOOST_STATIC_STRING_USE_IS_CONST_EVAL #define BOOST_STATIC_STRING_IS_CONST_EVAL __builtin_is_constant_evaluated() #endif @@ -158,12 +156,13 @@ defined(__clang__) && \ #define BOOST_STATIC_STRING_CPP14_CONSTEXPR #endif -// These are for compiler/library configurations +// This is for compiler/library configurations // that cannot use the library comparison function // objects at all in constant expresssions. In these // cases, we use whatever will make more constexpr work. -#if defined(__clang__) && defined(__GLIBCXX__) && \ -((__GLIBCXX__ > 20181206) && (__GLIBCXX__ < 20190812)) +#if defined(__clang__) && defined(__GLIBCXX__) && ((__GLIBCXX__ > 20181206 && __GLIBCXX__ <= 20190812)) +#define BOOST_STATIC_STRING_NO_PTR_COMP_FUNCTIONS +#elif __has_builtin(__builtin_constant_p) || defined(BOOST_STATIC_STRING_IS_CONST_EVAL) #define BOOST_STATIC_STRING_NO_PTR_COMP_FUNCTIONS #endif diff --git a/include/boost/static_string/static_string.hpp b/include/boost/static_string/static_string.hpp index a4b6f4f..ad152a6 100644 --- a/include/boost/static_string/static_string.hpp +++ b/include/boost/static_string/static_string.hpp @@ -596,8 +596,9 @@ find_first_of( return last; } -// Check if a pointer lies within a range (inclusive) without unspecified behavior, -// allowing it to be used in a constant evaluation +// Check if a pointer lies within the range [src_first, src_last) +// without unspecified behavior, allowing it to be used +// in a constant evaluation. template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline @@ -615,7 +616,7 @@ is_inside( // no applications in constant expressions. #ifdef BOOST_STATIC_STRING_CPP14 #ifdef BOOST_STATIC_STRING_NO_PTR_COMP_FUNCTIONS -#ifdef BOOST_STATIC_STRING_USE_IS_CONST_EVAL +#ifdef BOOST_STATIC_STRING_IS_CONST_EVAL // Our second best option is to use is_constant_evaluated // and a loop that checks for equality, since equality for // pointer to object types is never unspecified in this case. @@ -626,18 +627,27 @@ is_inside( return true; return false; } +#elif defined(__clang__) && __has_builtin(__builtin_constant_p) + // We can also try using __builtin_constant_p + if (__builtin_constant_p((ptr, src_first, src_last))) + { + for (; src_first != src_last; ++src_first) + if (src_first == ptr) + return true; + return false; + } #else // If library comparison functions don't work, and - // we cannot use is_constant_evaluated, we can use - // the builtin comparison operators instead. - return ptr >= src_first && ptr <= src_last; + // we cannot use any of the above, we can use + // try builtin comparison operators instead. + return ptr >= src_first && ptr < src_last; #endif #endif #endif // Use the library comparison functions if we can't use // is_constant_evaluated or if we don't need to. return std::greater_equal()(ptr, src_first) && - std::less_equal()(ptr, src_last); + std::less()(ptr, src_last); } } // detail #endif