From 93b4ad40a4b07ddfa0f855ee8731d6b3287d55b0 Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang Date: Thu, 1 Aug 2024 18:32:56 -0700 Subject: [PATCH] Do not define AVIF_ENABLE_NODISCARD for avif.h Make the AVIF_ENABLE_NODISCARD cmake option require C23 so that avif.h can define the AVIF_NODISCARD macro as [[nodiscard]] without checking the AVIF_ENABLE_NODISCARD macro. This requires changing avif.h to test __STDC_VERSION__ >= 202000L, which is the value of __STDC_VERSION__ in recent versions of GCC and Clang when -std=c2x or -std=gnu2x is specified. In general avif.h should only test compiler predefined macros. The only exception is AVIF_DLL (ignoring the experimental feature macros.) Fix https://github.com/AOMediaCodec/libavif/issues/2352. --- CMakeLists.txt | 32 ++++++++++++++------------------ include/avif/avif.h | 10 ++++++++-- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c31f14ef11..65d11e6be0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,8 +33,19 @@ include(FetchContent) include(FindPkgConfig) include(AvifExternalProjectUtils) +option(AVIF_ENABLE_NODISCARD "Add [[nodiscard]] to some functions. CMake must be at least 3.21 to force C23." OFF) + # Set C99 as the default -set(CMAKE_C_STANDARD 99) +if(AVIF_ENABLE_NODISCARD) + # [[nodiscard]] requires C23. + if(CMAKE_VERSION VERSION_LESS 3.21.0) + message(FATAL_ERROR "CMake must be at least 3.21 to force C23, bailing out") + endif() + set(CMAKE_C_STANDARD 23) + set(CMAKE_C_STANDARD_REQUIRED ON) +else() + set(CMAKE_C_STANDARD 99) +endif() # SOVERSION scheme: MAJOR.MINOR.PATCH # If there was an incompatible interface change: @@ -52,7 +63,6 @@ set(LIBRARY_SOVERSION ${LIBRARY_VERSION_MAJOR}) option(BUILD_SHARED_LIBS "Build shared avif library" ON) option(AVIF_ENABLE_WERROR "Treat all compiler warnings as errors" OFF) -option(AVIF_ENABLE_NODISCARD "Add [[nodiscard]] to some functions. CMake must be at least 3.21 to force C23" OFF) option(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R "Enable experimental YCgCo-R matrix code" OFF) option(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP @@ -334,22 +344,6 @@ endif() target_link_libraries(avif_obj PRIVATE avif_enable_warnings) -if(AVIF_ENABLE_NODISCARD) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21.0) - set(CMAKE_C_STANDARD 23) - set_property(TARGET avif_obj PROPERTY C_STANDARD 23) - else() - unset(CMAKE_C_STANDARD) - set_property(TARGET avif_obj PROPERTY C_STANDARD) - if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU") - target_compile_options(avif_obj PUBLIC $:-std=gnu2x>>) - elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC") - target_compile_options(avif_obj PUBLIC $:/std:clatest>>) - endif() - endif() - target_compile_definitions(avif_obj PUBLIC $) -endif() - if(AVIF_ENABLE_COVERAGE) if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU") message(STATUS "libavif: Enabling coverage for Clang") @@ -592,7 +586,9 @@ if(AVIF_LIB_USE_CXX OR (AVIF_BUILD_APPS AND AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP) O ) enable_language(CXX) if(AVIF_ENABLE_NODISCARD) + # [[nodiscard]] requires C++17. set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) else() set(CMAKE_CXX_STANDARD 14) endif() diff --git a/include/avif/avif.h b/include/avif/avif.h index 25e16f6639..c9f19149d2 100644 --- a/include/avif/avif.h +++ b/include/avif/avif.h @@ -48,8 +48,14 @@ extern "C" { #define AVIF_API #endif // defined(AVIF_DLL) -#if defined(AVIF_ENABLE_NODISCARD) || (defined(__cplusplus) && __cplusplus >= 201703L) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +// [[nodiscard]] requires C++17 and C23. +// +// If the -std=c2x or -std=gnu2x option is specified, __STDC_VERSION__ is +// * 202000L in GCC 13.2.0, Clang 16.0.6, and Apple Clang 15.0.0; or +// * 202311L in Clang 19.0.0git. +// If the /std:clatest option is specified, __STDC_VERSION__ is +// * 202312L in Microsoft Visual Studio 17.10.5. +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L) #define AVIF_NODISCARD [[nodiscard]] #else // Starting with 3.9, clang allows defining the warn_unused_result attribute for enums.