Try to require C++14. Now that we've dropped MSVC 2015, I believe we can rely on C++14 (which is now seven years old). This switches the build to require C++14. I've gone ahead and switched code in both public headers and within the library, but if the public headers are a problem, we can revert those separately. C++14 doesn't get us quite as much as C++17, but see if we can get to C++14 first. Still, std::enable_if_t and the less restricted constexpr are nice wins. Update-Note: C++14 is now required to build BoringSSL. If the build breaks, make sure your compiler is C++14-capable and is not passing -std=c++11. If this is causing problems for your project, let us know. Change-Id: If03a88e3f8a11980180781f95b806e7f3c3cb6c3 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52246 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/BUILDING.md b/BUILDING.md index e9a2b0c..d3446f3 100644 --- a/BUILDING.md +++ b/BUILDING.md
@@ -30,7 +30,7 @@ by CMake, it may be configured explicitly by setting `CMAKE_ASM_NASM_COMPILER`. - * C and C++ compilers with C++11 support are required. On Windows, MSVC from + * C and C++ compilers with C++14 support are required. On Windows, MSVC from Visual Studio 2017 or later with Platform SDK 8.1 or later are supported, but newer versions are recommended. Recent versions of GCC (6.1+) and Clang should work on non-Windows platforms, and maybe on Windows too.
diff --git a/CMakeLists.txt b/CMakeLists.txt index df2d630..dad27f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -163,7 +163,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CXX_FLAGS} -Wmissing-declarations") if(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif()
diff --git a/crypto/test/abi_test.h b/crypto/test/abi_test.h index ffe4479..1ba82b1 100644 --- a/crypto/test/abi_test.h +++ b/crypto/test/abi_test.h
@@ -380,9 +380,9 @@ // CheckImpl implementation. It must be specialized for void returns because we // call |func| directly. template <typename R, typename... Args> -inline typename std::enable_if<!std::is_void<R>::value, crypto_word_t>::type -CheckImpl(Result *out, bool /* unwind */, R (*func)(Args...), - typename DeductionGuard<Args>::Type... args) { +inline std::enable_if_t<!std::is_void<R>::value, crypto_word_t> CheckImpl( + Result *out, bool /* unwind */, R (*func)(Args...), + typename DeductionGuard<Args>::Type... args) { *out = Result(); return func(args...); }
diff --git a/include/openssl/span.h b/include/openssl/span.h index 38e9a96..67a1a5c 100644 --- a/include/openssl/span.h +++ b/include/openssl/span.h
@@ -99,12 +99,11 @@ // Heuristically test whether C is a container type that can be converted into // a Span by checking for data() and size() member functions. // - // TODO(davidben): Require C++14 support and switch to std::enable_if_t. - // Perhaps even C++17 now? + // TODO(davidben): Require C++17 support for std::is_convertible_v, etc. template <typename C> - using EnableIfContainer = typename std::enable_if< + using EnableIfContainer = std::enable_if_t< std::is_convertible<decltype(std::declval<C>().data()), T *>::value && - std::is_integral<decltype(std::declval<C>().size())>::value>::type; + std::is_integral<decltype(std::declval<C>().size())>::value>; public: constexpr Span() : Span(nullptr, 0) {} @@ -113,14 +112,12 @@ template <size_t N> constexpr Span(T (&array)[N]) : Span(array, N) {} - template < - typename C, typename = EnableIfContainer<C>, - typename = typename std::enable_if<std::is_const<T>::value, C>::type> + template <typename C, typename = EnableIfContainer<C>, + typename = std::enable_if_t<std::is_const<T>::value, C>> Span(const C &container) : data_(container.data()), size_(container.size()) {} - template < - typename C, typename = EnableIfContainer<C>, - typename = typename std::enable_if<!std::is_const<T>::value, C>::type> + template <typename C, typename = EnableIfContainer<C>, + typename = std::enable_if_t<!std::is_const<T>::value, C>> explicit Span(C &container) : data_(container.data()), size_(container.size()) {}
diff --git a/include/openssl/stack.h b/include/openssl/stack.h index 04e942c..df54713 100644 --- a/include/openssl/stack.h +++ b/include/openssl/stack.h
@@ -443,16 +443,14 @@ // Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|. template <typename Stack> -struct DeleterImpl< - Stack, typename std::enable_if<StackTraits<Stack>::kIsConst>::type> { +struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> { static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); } }; // Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the // corresponding type's deleter. template <typename Stack> -struct DeleterImpl< - Stack, typename std::enable_if<!StackTraits<Stack>::kIsConst>::type> { +struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> { static void Free(Stack *sk) { // sk_FOO_pop_free is defined by macros and bound by name, so we cannot // access it from C++ here. @@ -502,18 +500,17 @@ }; template <typename Stack> -using StackIterator = typename std::enable_if<StackTraits<Stack>::kIsStack, - StackIteratorImpl<Stack>>::type; +using StackIterator = + std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>; } // namespace internal // PushToStack pushes |elem| to |sk|. It returns true on success and false on // allocation failure. template <typename Stack> -inline - typename std::enable_if<!internal::StackTraits<Stack>::kIsConst, bool>::type - PushToStack(Stack *sk, - UniquePtr<typename internal::StackTraits<Stack>::Type> elem) { +inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool> +PushToStack(Stack *sk, + UniquePtr<typename internal::StackTraits<Stack>::Type> elem) { if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) { return false; }
diff --git a/ssl/internal.h b/ssl/internal.h index 0087e7f..110b221 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -216,7 +216,7 @@ // may be C structs which require a |BORINGSSL_MAKE_DELETER| registration. namespace internal { template <typename T> -struct DeleterImpl<T, typename std::enable_if<T::kAllowUniquePtr>::type> { +struct DeleterImpl<T, std::enable_if_t<T::kAllowUniquePtr>> { static void Free(T *t) { Delete(t); } }; } // namespace internal
diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc index 60b3e2c..628dddc 100644 --- a/ssl/ssl_cipher.cc +++ b/ssl/ssl_cipher.cc
@@ -1327,34 +1327,33 @@ using namespace bssl; -static constexpr int ssl_cipher_id_cmp_inner(const SSL_CIPHER *a, - const SSL_CIPHER *b) { - // C++11's constexpr functions must have a body consisting of just a - // return-statement. - return (a->id > b->id) ? 1 : ((a->id < b->id) ? -1 : 0); +static constexpr int ssl_cipher_id_cmp(const SSL_CIPHER *a, + const SSL_CIPHER *b) { + if (a->id > b->id) { + return 1; + } + if (a->id < b->id) { + return -1; + } + return 0; } -static int ssl_cipher_id_cmp(const void *in_a, const void *in_b) { - return ssl_cipher_id_cmp_inner(reinterpret_cast<const SSL_CIPHER *>(in_a), - reinterpret_cast<const SSL_CIPHER *>(in_b)); +static int ssl_cipher_id_cmp_void(const void *in_a, const void *in_b) { + return ssl_cipher_id_cmp(reinterpret_cast<const SSL_CIPHER *>(in_a), + reinterpret_cast<const SSL_CIPHER *>(in_b)); } -template <typename T, size_t N> -static constexpr size_t countof(T const (&)[N]) { - return N; +template <size_t N> +static constexpr bool ssl_ciphers_sorted(const SSL_CIPHER (&ciphers)[N]) { + for (size_t i = 1; i < N; i++) { + if (ssl_cipher_id_cmp(&ciphers[i - 1], &ciphers[i]) >= 0) { + return false; + } + } + return true; } -template <typename T, size_t I> -static constexpr int check_order(const T (&arr)[I], size_t N) { - // C++11's constexpr functions must have a body consisting of just a - // return-statement. - return N > 1 ? ((ssl_cipher_id_cmp_inner(&arr[N - 2], &arr[N - 1]) < 0) - ? check_order(arr, N - 1) - : 0) - : 1; -} - -static_assert(check_order(kCiphers, countof(kCiphers)) == 1, +static_assert(ssl_ciphers_sorted(kCiphers), "Ciphers are not sorted, bsearch won't work"); const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) { @@ -1363,7 +1362,7 @@ c.id = 0x03000000L | value; return reinterpret_cast<const SSL_CIPHER *>(bsearch( &c, kCiphers, OPENSSL_ARRAY_SIZE(kCiphers), sizeof(SSL_CIPHER), - ssl_cipher_id_cmp)); + ssl_cipher_id_cmp_void)); } uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
diff --git a/util/BUILD.toplevel b/util/BUILD.toplevel index cfa695a..1ec2bdf 100644 --- a/util/BUILD.toplevel +++ b/util/BUILD.toplevel
@@ -137,9 +137,9 @@ "//conditions:default": [], }) -# For C++ targets only (not C), compile with C++11 support. +# For C++ targets only (not C), compile with C++14 support. posix_copts_cxx = [ - "-std=c++11", + "-std=c++14", "-Wmissing-declarations", ]
diff --git a/util/generate_build_files.py b/util/generate_build_files.py index 3263d9b..186fb59 100644 --- a/util/generate_build_files.py +++ b/util/generate_build_files.py
@@ -437,7 +437,7 @@ endif() if(CMAKE_COMPILER_IS_GNUCXX OR CLANG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fvisibility=hidden -fno-common -fno-exceptions -fno-rtti") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fvisibility=hidden -fno-common -fno-exceptions -fno-rtti") if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif()