From fb3487a9975ed321b48fad5c71dd655d66b68087 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 3 Feb 2015 21:47:45 +0100 Subject: [PATCH] Features: Fix C90 feature detection. This bug caused c_function_prototypes to not be recorded at configure time when compiling with -std=gnu99 or similar. In the case of feature recording, that was not a problem, because the logic in CMakeDetermineCompileFeatures.cmake currently assumes that a feature present for an earlier standard is present for a later standard. However, the detection strings are also used in WriteCompilerDetectionHeader, so the feature macro has been defined to '0' when using a later language dialect. Fix that by not checking the existence of the __STDC_VERSION__ macro at all when detecting C90 features. --- .../Compiler/AppleClang-C-FeatureTests.cmake | 2 +- Modules/Compiler/Clang-C-FeatureTests.cmake | 2 +- Modules/Compiler/GNU-C-FeatureTests.cmake | 2 +- Tests/CompileFeatures/CMakeLists.txt | 32 ++++++++++++++++ Tests/CompileFeatures/genex_test.c | 38 +++++++++++++++++++ .../CMakeLists.txt | 22 +++++++++++ .../WriteCompilerDetectionHeader/main.c | 29 ++++++++++++++ .../WriteCompilerDetectionHeader/main_multi.c | 29 ++++++++++++++ 8 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 Tests/CompileFeatures/genex_test.c create mode 100644 Tests/Module/WriteCompilerDetectionHeader/main.c create mode 100644 Tests/Module/WriteCompilerDetectionHeader/main_multi.c diff --git a/Modules/Compiler/AppleClang-C-FeatureTests.cmake b/Modules/Compiler/AppleClang-C-FeatureTests.cmake index 6f3d6a73f..e80b526f1 100644 --- a/Modules/Compiler/AppleClang-C-FeatureTests.cmake +++ b/Modules/Compiler/AppleClang-C-FeatureTests.cmake @@ -7,5 +7,5 @@ set(AppleClang_C99 "${_cmake_oldestSupported} && defined(__STDC_VERSION__) && __ set(_cmake_feature_test_c_restrict "${AppleClang_C99}") set(_cmake_feature_test_c_variadic_macros "${AppleClang_C99}") -set(AppleClang_C90 "${_cmake_oldestSupported} && !defined(__STDC_VERSION__)") +set(AppleClang_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${AppleClang_C90}") diff --git a/Modules/Compiler/Clang-C-FeatureTests.cmake b/Modules/Compiler/Clang-C-FeatureTests.cmake index 2d8673d51..99c2252c8 100644 --- a/Modules/Compiler/Clang-C-FeatureTests.cmake +++ b/Modules/Compiler/Clang-C-FeatureTests.cmake @@ -7,5 +7,5 @@ set(Clang_C99 "${_cmake_oldestSupported} && defined(__STDC_VERSION__) && __STDC_ set(_cmake_feature_test_c_restrict "${Clang_C99}") set(_cmake_feature_test_c_variadic_macros "${Clang_C99}") -set(Clang_C90 "${_cmake_oldestSupported} && !defined(__STDC_VERSION__)") +set(Clang_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${Clang_C90}") diff --git a/Modules/Compiler/GNU-C-FeatureTests.cmake b/Modules/Compiler/GNU-C-FeatureTests.cmake index d8e456c17..b3fe33f14 100644 --- a/Modules/Compiler/GNU-C-FeatureTests.cmake +++ b/Modules/Compiler/GNU-C-FeatureTests.cmake @@ -13,5 +13,5 @@ set(GNU44_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSIO set(_cmake_feature_test_c_restrict "${GNU44_C99}") set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}") -set(GNU_C90 "${_cmake_oldestSupported} && !defined(__STDC_VERSION__)") +set(GNU_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 38c44c870..3ba1e0a55 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -164,6 +164,38 @@ if (CMAKE_C_COMPILE_FEATURES) ) endif() endif() + + add_executable(CompileFeaturesGenex_C genex_test.c) + set_property(TARGET CompileFeaturesGenex_C PROPERTY C_STANDARD 11) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) + list(APPEND expected_defs + EXPECT_C_STATIC_ASSERT=1 + ) + else() + list(APPEND expected_defs + EXPECT_C_STATIC_ASSERT=0 + ) + endif() + elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" + OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") + list(APPEND expected_defs + EXPECT_C_STATIC_ASSERT=1 + ) + endif() + + list(APPEND expected_defs + EXPECT_C_FUNCTION_PROTOTYPES=1 + EXPECT_C_RESTRICT=1 + ) + + target_compile_definitions(CompileFeaturesGenex_C PRIVATE + HAVE_C_FUNCTION_PROTOTYPES=$ + HAVE_C_RESTRICT=$ + HAVE_C_STATIC_ASSERT=$ + ${expected_defs} + ) endif() if (CMAKE_CXX_COMPILE_FEATURES) diff --git a/Tests/CompileFeatures/genex_test.c b/Tests/CompileFeatures/genex_test.c new file mode 100644 index 000000000..b1215bd21 --- /dev/null +++ b/Tests/CompileFeatures/genex_test.c @@ -0,0 +1,38 @@ +#ifndef EXPECT_C_STATIC_ASSERT +# error EXPECT_C_STATIC_ASSERT not defined +#endif +#ifndef EXPECT_C_FUNCTION_PROTOTYPES +# error EXPECT_C_FUNCTION_PROTOTYPES not defined +#endif +#ifndef EXPECT_C_RESTRICT +# error EXPECT_C_RESTRICT not defined +#endif + +#if !EXPECT_C_STATIC_ASSERT +#if EXPECT_C_STATIC_ASSERT +#error "Expect c_static_assert feature" +#endif +#else +#if !EXPECT_C_STATIC_ASSERT +#error "Expect no c_static_assert feature" +#endif +#endif + +#if !EXPECT_C_FUNCTION_PROTOTYPES +# error Expect c_function_prototypes support +#endif + +#if !EXPECT_C_RESTRICT +# if EXPECT_C_RESTRICT +# error Expect c_restrict support +# endif +#else +# if !EXPECT_C_RESTRICT +# error Expect no c_restrict support +# endif +#endif + +int main() +{ + +} diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index e70a977ab..c53828074 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -84,6 +84,15 @@ if (CMAKE_C_COMPILER_ID STREQUAL "GNU" add_executable(C_undefined c_undefined.c) set_property(TARGET C_undefined PROPERTY C_STANDARD 90) target_compile_options(C_undefined PRIVATE -Werror=undef) + + add_executable(WriteCompilerDetectionHeader_C main.c) + set_property(TARGET WriteCompilerDetectionHeader_C PROPERTY C_STANDARD 90) + set_defines(WriteCompilerDetectionHeader_C "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT") + + add_executable(WriteCompilerDetectionHeader_C_multi main_multi.c) + set_property(TARGET WriteCompilerDetectionHeader_C_multi PROPERTY C_STANDARD 90) + set_defines(WriteCompilerDetectionHeader_C_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES" "EXPECTED_COMPILER_C_RESTRICT") + target_include_directories(WriteCompilerDetectionHeader_C_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) endif() add_executable(WriteCompilerDetectionHeader main.cpp) @@ -130,3 +139,16 @@ add_executable(multi_files_11 multi_files.cpp) set_property(TARGET multi_files_11 PROPERTY CXX_STANDARD 11) target_include_directories(multi_files_11 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) set_defines(multi_files_11 "${true_defs}" "${false_defs}") + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" + OR CMAKE_C_COMPILER_ID STREQUAL "Clang" + OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") + add_executable(WriteCompilerDetectionHeader_C11 main.c) + set_property(TARGET WriteCompilerDetectionHeader_C11 PROPERTY C_STANDARD 11) + set_defines(WriteCompilerDetectionHeader_C11 "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "") + + add_executable(WriteCompilerDetectionHeader_C11_multi main_multi.c) + set_property(TARGET WriteCompilerDetectionHeader_C11_multi PROPERTY C_STANDARD 11) + set_defines(WriteCompilerDetectionHeader_C11_multi "EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES;EXPECTED_COMPILER_C_RESTRICT" "") + target_include_directories(WriteCompilerDetectionHeader_C11_multi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) +endif() diff --git a/Tests/Module/WriteCompilerDetectionHeader/main.c b/Tests/Module/WriteCompilerDetectionHeader/main.c new file mode 100644 index 000000000..9023b0f53 --- /dev/null +++ b/Tests/Module/WriteCompilerDetectionHeader/main.c @@ -0,0 +1,29 @@ + +#include "test_compiler_detection.h" + +#if !defined(TEST_COMPILER_C_FUNCTION_PROTOTYPES) || !TEST_COMPILER_C_FUNCTION_PROTOTYPES +# error Expected TEST_COMPILER_C_FUNCTION_PROTOTYPES +#endif + +#if !EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES +# error Expected EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES +#endif + +#if !defined(TEST_COMPILER_C_RESTRICT) || !TEST_COMPILER_C_RESTRICT +# if EXPECTED_COMPILER_C_RESTRICT +# error Expected TEST_COMPILER_C_RESTRICT +# endif +#else +# if !EXPECTED_COMPILER_C_RESTRICT +# error Expect no TEST_COMPILER_C_RESTRICT +# endif +#endif + +#ifdef TEST_COMPILER_CXX_STATIC_ASSERT +#error Expect no CXX features defined +#endif + +int main() +{ + return 0; +} diff --git a/Tests/Module/WriteCompilerDetectionHeader/main_multi.c b/Tests/Module/WriteCompilerDetectionHeader/main_multi.c new file mode 100644 index 000000000..6f4573f77 --- /dev/null +++ b/Tests/Module/WriteCompilerDetectionHeader/main_multi.c @@ -0,0 +1,29 @@ + +#include "multi_file_compiler_detection.h" + +#if !defined(MULTI_COMPILER_C_FUNCTION_PROTOTYPES) || !MULTI_COMPILER_C_FUNCTION_PROTOTYPES +# error Expected MULTI_COMPILER_C_FUNCTION_PROTOTYPES +#endif + +#if !EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES +# error Expected EXPECTED_COMPILER_C_FUNCTION_PROTOTYPES +#endif + +#if !defined(MULTI_COMPILER_C_RESTRICT) || !MULTI_COMPILER_C_RESTRICT +# if EXPECTED_COMPILER_C_RESTRICT +# error Expected MULTI_COMPILER_C_RESTRICT +# endif +#else +# if !EXPECTED_COMPILER_C_RESTRICT +# error Expect no MULTI_COMPILER_C_RESTRICT +# endif +#endif + +#ifdef MULTI_COMPILER_CXX_STATIC_ASSERT +#error Expect no CXX features defined +#endif + +int main() +{ + return 0; +}