Browse Source

Features: Extend concept to C language.

Add properties and variables corresponding to CXX equivalents.

Add features for c_function_prototypes (C90), c_restrict (C99),
c_variadic_macros (C99) and c_static_assert (C11). This feature
set can be extended later.

Add a <PREFIX>_RESTRICT symbol define to WriteCompilerDetectionHeader
to conditionally represent the c_restrict feature.
Stephen Kelly 12 years ago
parent
commit
e0890d03a4
57 changed files with 630 additions and 27 deletions
  1. 2 1
      Help/command/target_compile_features.rst
  2. 4 0
      Help/manual/cmake-properties.7.rst
  3. 4 0
      Help/manual/cmake-variables.7.rst
  4. 25 0
      Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
  5. 8 0
      Help/prop_tgt/C_EXTENSIONS.rst
  6. 27 0
      Help/prop_tgt/C_STANDARD.rst
  7. 14 0
      Help/prop_tgt/C_STANDARD_REQUIRED.rst
  8. 6 0
      Help/release/dev/compile-language-features.rst
  9. 8 0
      Help/variable/CMAKE_C_COMPILE_FEATURES.rst
  10. 8 0
      Help/variable/CMAKE_C_EXTENSIONS.rst
  11. 8 0
      Help/variable/CMAKE_C_STANDARD.rst
  12. 8 0
      Help/variable/CMAKE_C_STANDARD_REQUIRED.rst
  13. 5 0
      Modules/CMakeCCompiler.cmake.in
  14. 39 1
      Modules/CMakeDetermineCompileFeatures.cmake
  15. 3 0
      Modules/CMakeTestCCompiler.cmake
  16. 12 0
      Modules/Compiler/GNU-C-FeatureTests.cmake
  17. 32 0
      Modules/Compiler/GNU-C.cmake
  18. 20 4
      Modules/WriteCompilerDetectionHeader.cmake
  19. 4 0
      Source/cmLocalGenerator.cxx
  20. 114 2
      Source/cmMakefile.cxx
  21. 6 0
      Source/cmMakefile.h
  22. 3 0
      Source/cmTarget.cxx
  23. 6 2
      Source/cmake.cxx
  24. 6 0
      Source/cmake.h
  25. 31 11
      Tests/CMakeCommands/target_compile_features/CMakeLists.txt
  26. 9 0
      Tests/CMakeCommands/target_compile_features/lib_restrict.c
  27. 7 0
      Tests/CMakeCommands/target_compile_features/lib_restrict.h
  28. 12 0
      Tests/CMakeCommands/target_compile_features/main.c
  29. 14 0
      Tests/CMakeCommands/target_compile_features/restrict_user.c
  30. 8 2
      Tests/CompileFeatures/CMakeLists.txt
  31. 9 0
      Tests/CompileFeatures/c_function_prototypes.c
  32. 7 0
      Tests/CompileFeatures/c_restrict.c
  33. 2 0
      Tests/CompileFeatures/c_static_assert.c
  34. 15 0
      Tests/CompileFeatures/c_variadic_macros.c
  35. 12 0
      Tests/CompileFeatures/main.c
  36. 4 1
      Tests/ExportImport/Export/Interface/CMakeLists.txt
  37. 21 0
      Tests/ExportImport/Import/Interface/CMakeLists.txt
  38. 3 2
      Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
  39. 1 0
      Tests/RunCMake/CompileFeatures/NoSupportedCFeatures-result.txt
  40. 8 0
      Tests/RunCMake/CompileFeatures/NoSupportedCFeatures-stderr.txt
  41. 5 0
      Tests/RunCMake/CompileFeatures/NoSupportedCFeatures.cmake
  42. 1 0
      Tests/RunCMake/CompileFeatures/NoSupportedCFeaturesGenex-result.txt
  43. 6 0
      Tests/RunCMake/CompileFeatures/NoSupportedCFeaturesGenex-stderr.txt
  44. 5 0
      Tests/RunCMake/CompileFeatures/NoSupportedCFeaturesGenex.cmake
  45. 9 0
      Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
  46. 7 0
      Tests/RunCMake/CompileFeatures/empty.c
  47. 6 0
      Tests/RunCMake/CompileFeatures/generate_feature_list.cmake
  48. 1 1
      Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt
  49. 2 0
      Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
  50. 7 0
      Tests/RunCMake/target_compile_features/empty.c
  51. 1 0
      Tests/RunCMake/target_compile_features/no_matching_c_feature-result.txt
  52. 8 0
      Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt
  53. 15 0
      Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake
  54. 1 0
      Tests/RunCMake/target_compile_features/not_a_c_feature-result.txt
  55. 5 0
      Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt
  56. 6 0
      Tests/RunCMake/target_compile_features/not_a_c_feature.cmake
  57. 10 0
      Tests/SystemInformation/SystemInformation.in

+ 2 - 1
Help/command/target_compile_features.rst

@@ -8,7 +8,8 @@ Add expected compiler features to a target.
   target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
 
 Specify compiler features required when compiling a given target.  If the
-feature is not listed in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable,
+feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable
+or :variable:`CMAKE_CXX_COMPILE_FEATURES` variable,
 then an error will be reported by CMake.  If the use of the feature requires
 an additional compiler flag, such as ``-std=c++11``, the flag will be added
 automatically.

+ 4 - 0
Help/manual/cmake-properties.7.rst

@@ -16,6 +16,7 @@ Properties of Global Scope
    /prop_gbl/ALLOW_DUPLICATE_CUSTOM_TARGETS
    /prop_gbl/AUTOGEN_TARGETS_FOLDER
    /prop_gbl/AUTOMOC_TARGETS_FOLDER
+   /prop_gbl/CMAKE_C_KNOWN_FEATURES
    /prop_gbl/CMAKE_CXX_KNOWN_FEATURES
    /prop_gbl/DEBUG_CONFIGURATIONS
    /prop_gbl/DISABLED_FEATURES
@@ -93,6 +94,9 @@ Properties on Targets
    /prop_tgt/BUILD_WITH_INSTALL_RPATH
    /prop_tgt/BUNDLE_EXTENSION
    /prop_tgt/BUNDLE
+   /prop_tgt/C_EXTENSIONS
+   /prop_tgt/C_STANDARD
+   /prop_tgt/C_STANDARD_REQUIRED
    /prop_tgt/COMPATIBLE_INTERFACE_BOOL
    /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MAX
    /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MIN

+ 4 - 0
Help/manual/cmake-variables.7.rst

@@ -260,6 +260,10 @@ Variables for Languages
    :maxdepth: 1
 
    /variable/CMAKE_COMPILER_IS_GNULANG
+   /variable/CMAKE_C_COMPILE_FEATURES
+   /variable/CMAKE_C_EXTENSIONS
+   /variable/CMAKE_C_STANDARD
+   /variable/CMAKE_C_STANDARD_REQUIRED
    /variable/CMAKE_CXX_COMPILE_FEATURES
    /variable/CMAKE_CXX_EXTENSIONS
    /variable/CMAKE_CXX_STANDARD

+ 25 - 0
Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst

@@ -0,0 +1,25 @@
+CMAKE_C_KNOWN_FEATURES
+----------------------
+
+List of C features known to this version of CMake.
+
+The features listed in this global property may be known to be available to the
+C compiler.  If the feature is available with the C compiler, it will
+be listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable.
+
+The features listed here may be used with the :command:`target_compile_features`
+command.
+
+The features known to this version of CMake are:
+
+``c_function_prototypes``
+  Function prototypes, as defined in ``ISO/IEC 9899:1990``.
+
+``c_restrict``
+  ``restrict`` keyword, as defined in ``ISO/IEC 9899:1999``.
+
+``c_static_assert``
+  Static assert, as defined in ``ISO/IEC 9899:2011``.
+
+``c_variadic_macros``
+  Variadic macros, as defined in ``ISO/IEC 9899:1999``.

+ 8 - 0
Help/prop_tgt/C_EXTENSIONS.rst

@@ -0,0 +1,8 @@
+C_EXTENSIONS
+------------
+
+Boolean specifying whether compiler specific extensions are requested.
+
+This property specifies whether compiler specific extensions should be
+used.  For some compilers, this results in adding a flag such
+as ``-std=gnu11`` instead of ``-std=c11`` to the compile line.

+ 27 - 0
Help/prop_tgt/C_STANDARD.rst

@@ -0,0 +1,27 @@
+C_STANDARD
+----------
+
+The C standard whose features are requested to build this target.
+
+This property specifies the C standard whose features are requested
+to build this target.  For some compilers, this results in adding a
+flag such as ``-std=c11`` to the compile line.
+
+Supported values are ``90``, ``99`` and ``11``.
+
+If the value requested does not result in a compile flag being added for
+the compiler in use, a previous standard flag will be added instead.  This
+means that using:
+
+.. code-block:: cmake
+
+  set_property(TARGET tgt PROPERTY C_STANDARD 11)
+
+with a compiler which does not support ``-std=c11`` or an equivalent
+flag will not result in an error or warning, but will instead add the
+``-std=c99`` or ``-std=c90`` flag if supported.  This "decay" behavior may
+be controlled with the :prop_tgt:`C_STANDARD_REQUIRED` target property.
+
+This property is initialized by the value of
+the :variable:`CMAKE_C_STANDARD` variable if it is set when a target
+is created.

+ 14 - 0
Help/prop_tgt/C_STANDARD_REQUIRED.rst

@@ -0,0 +1,14 @@
+C_STANDARD_REQUIRED
+-------------------
+
+Boolean describing whether the value of :prop_tgt:`C_STANDARD` is a requirement.
+
+If this property is set to ``ON``, then the value of the
+:prop_tgt:`C_STANDARD` target property is treated as a requirement.  If this
+property is ``OFF`` or unset, the :prop_tgt:`C_STANDARD` target property is
+treated as optional and may "decay" to a previous standard if the requested is
+not available.
+
+This property is initialized by the value of
+the :variable:`CMAKE_C_STANDARD_REQUIRED` variable if it is set when a
+target is created.

+ 6 - 0
Help/release/dev/compile-language-features.rst

@@ -7,6 +7,12 @@ target-language-features
   :variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_EXTENSIONS`
   variables may be set to initialize the target properties.
 
+* New :prop_tgt:`C_STANDARD` and :prop_tgt:`C_EXTENSIONS` target
+  properties may specify values which CMake uses to compute required
+  compile options such as ``-std=c11`` or ``-std=gnu11``. The
+  :variable:`CMAKE_C_STANDARD` and :variable:`CMAKE_C_EXTENSIONS`
+  variables may be set to initialize the target properties.
+
 * New :prop_tgt:`COMPILE_FEATURES` target property may contain a list
   of features required to compile a target.  CMake uses this
   information to ensure that the compiler in use is capable of building

+ 8 - 0
Help/variable/CMAKE_C_COMPILE_FEATURES.rst

@@ -0,0 +1,8 @@
+CMAKE_C_COMPILE_FEATURES
+------------------------
+
+List of features known to the C compiler
+
+These features are known to be available for use with the C compiler. This
+list is a subset of the features listed in the :prop_gbl:`CMAKE_C_KNOWN_FEATURES`
+global property.

+ 8 - 0
Help/variable/CMAKE_C_EXTENSIONS.rst

@@ -0,0 +1,8 @@
+CMAKE_C_EXTENSIONS
+------------------
+
+Default value for ``C_EXTENSIONS`` property of targets.
+
+This variable is used to initialize the :prop_tgt:`C_EXTENSIONS`
+property on all targets.  See that target property for additional
+information.

+ 8 - 0
Help/variable/CMAKE_C_STANDARD.rst

@@ -0,0 +1,8 @@
+CMAKE_C_STANDARD
+----------------
+
+Default value for ``C_STANDARD`` property of targets.
+
+This variable is used to initialize the :prop_tgt:`C_STANDARD`
+property on all targets.  See that target property for additional
+information.

+ 8 - 0
Help/variable/CMAKE_C_STANDARD_REQUIRED.rst

@@ -0,0 +1,8 @@
+CMAKE_C_STANDARD_REQUIRED
+-------------------------
+
+Default value for ``C_STANDARD_REQUIRED`` property of targets.
+
+This variable is used to initialize the :prop_tgt:`C_STANDARD_REQUIRED`
+property on all targets.  See that target property for additional
+information.

+ 5 - 0
Modules/CMakeCCompiler.cmake.in

@@ -2,6 +2,11 @@ set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@")
 set(CMAKE_C_COMPILER_ARG1 "@CMAKE_C_COMPILER_ARG1@")
 set(CMAKE_C_COMPILER_ID "@CMAKE_C_COMPILER_ID@")
 set(CMAKE_C_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@")
+set(CMAKE_C_COMPILE_FEATURES "@CMAKE_C_COMPILE_FEATURES@")
+set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@")
+set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@")
+set(CMAKE_C11_COMPILE_FEATURES "@CMAKE_C11_COMPILE_FEATURES@")
+
 set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@")
 set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@")
 set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@")

+ 39 - 1
Modules/CMakeDetermineCompileFeatures.cmake

@@ -14,7 +14,45 @@
 
 function(cmake_determine_compile_features lang)
 
-  if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
+  if(lang STREQUAL C AND COMMAND cmake_record_c_compile_features)
+    message(STATUS "Detecting ${lang} compile features")
+
+    set(CMAKE_C90_COMPILE_FEATURES)
+    set(CMAKE_C99_COMPILE_FEATURES)
+    set(CMAKE_C11_COMPILE_FEATURES)
+
+    include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
+
+    cmake_record_c_compile_features()
+
+    if(NOT _result EQUAL 0)
+      message(STATUS "Detecting ${lang} compile features - failed")
+      return()
+    endif()
+
+    if (CMAKE_C99_COMPILE_FEATURES AND CMAKE_C11_COMPILE_FEATURES)
+      list(REMOVE_ITEM CMAKE_C11_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES})
+    endif()
+    if (CMAKE_C90_COMPILE_FEATURES AND CMAKE_C99_COMPILE_FEATURES)
+      list(REMOVE_ITEM CMAKE_C99_COMPILE_FEATURES ${CMAKE_C90_COMPILE_FEATURES})
+    endif()
+
+    if(NOT CMAKE_C_COMPILE_FEATURES)
+      set(CMAKE_C_COMPILE_FEATURES
+        ${CMAKE_C90_COMPILE_FEATURES}
+        ${CMAKE_C99_COMPILE_FEATURES}
+        ${CMAKE_C11_COMPILE_FEATURES}
+      )
+    endif()
+
+    set(CMAKE_C_COMPILE_FEATURES ${CMAKE_C_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_C90_COMPILE_FEATURES ${CMAKE_C90_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_C99_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_C11_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES} PARENT_SCOPE)
+
+    message(STATUS "Detecting ${lang} compile features - done")
+
+  elseif(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
     message(STATUS "Detecting ${lang} compile features")
 
     set(CMAKE_CXX98_COMPILE_FEATURES)

+ 3 - 0
Modules/CMakeTestCCompiler.cmake

@@ -73,6 +73,9 @@ else()
   # Try to identify the ABI and configure it into CMakeCCompiler.cmake
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
   CMAKE_DETERMINE_COMPILER_ABI(C ${CMAKE_ROOT}/Modules/CMakeCCompilerABI.c)
+  # Try to identify the compiler features
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+  CMAKE_DETERMINE_COMPILE_FEATURES(C)
 
   # Re-configure to save learned information.
   configure_file(

+ 12 - 0
Modules/Compiler/GNU-C-FeatureTests.cmake

@@ -0,0 +1,12 @@
+
+set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407")
+
+set(GNU46_C11 "${_cmake_oldestSupported} && __STDC_VERSION__ >= 201112L")
+set(_cmake_feature_test_c_static_assert "${GNU46_C11}")
+# Since 4.4 at least:
+set(GNU44_C99 "${_cmake_oldestSupported} && __STDC_VERSION__ >= 199901L")
+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(_cmake_feature_test_c_function_prototypes "${GNU_C90}")

+ 32 - 0
Modules/Compiler/GNU-C.cmake

@@ -1,2 +1,34 @@
 include(Compiler/GNU)
 __compiler_gnu(C)
+
+if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.7)
+  set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
+  set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+
+  set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
+  set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+
+  set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
+  set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+endif()
+
+# This may change in a future GNU version.
+set(CMAKE_C_STANDARD_DEFAULT 90)
+
+macro(cmake_record_c_compile_features)
+  macro(_get_gcc_features std_version list)
+    record_compiler_features(C "-std=${std_version}" ${list})
+  endmacro()
+
+  if (UNIX AND NOT APPLE AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.7)
+    _get_gcc_features(c90 CMAKE_C90_COMPILE_FEATURES)
+    if (_result EQUAL 0)
+      _get_gcc_features(c99 CMAKE_C99_COMPILE_FEATURES)
+    endif()
+    if (_result EQUAL 0)
+      _get_gcc_features(c11 CMAKE_C11_COMPILE_FEATURES)
+    endif()
+  else()
+    set(_result 0)
+  endif()
+endmacro()

+ 20 - 4
Modules/WriteCompilerDetectionHeader.cmake

@@ -43,7 +43,8 @@
 # Possible compiler identifiers are documented with the
 # :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
 # Available features in this version of CMake are listed in the
-# :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global property.
+# :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
+# :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties.
 #
 # Feature Test Macros
 # ===================
@@ -102,6 +103,7 @@
 # ========================== =================================== =================
 #         Feature                          Define                      Symbol
 # ========================== =================================== =================
+# ``c_restrict``              ``<PREFIX>_RESTRICT``               ``restrict``
 # ``cxx_constexpr``           ``<PREFIX>_CONSTEXPR``              ``constexpr``
 # ``cxx_deleted_functions``   ``<PREFIX>_DELETED_FUNCTION``       ``= delete``
 # ``cxx_extern_templates``    ``<PREFIX>_EXTERN_TEMPLATE``        ``extern``
@@ -221,6 +223,9 @@ function(write_compiler_detection_header
     if (feature MATCHES "^cxx_")
       list(APPEND _langs CXX)
       list(APPEND CXX_features ${feature})
+    elseif (feature MATCHES "^c_")
+      list(APPEND _langs C)
+      list(APPEND C_features ${feature})
     else()
       message(FATAL_ERROR "Unsupported feature ${feature}.")
     endif()
@@ -239,6 +244,8 @@ function(write_compiler_detection_header
 
     if(_lang STREQUAL CXX)
       set(file_content "${file_content}\n#ifdef __cplusplus\n")
+    else()
+      set(file_content "${file_content}\n#ifndef __cplusplus\n")
     endif()
 
     compiler_id_detection(ID_CONTENT ${_lang} PREFIX ${prefix_arg}_
@@ -279,6 +286,16 @@ function(write_compiler_detection_header
       string(TOUPPER ${feature} feature_upper)
       set(feature_PP "COMPILER_${feature_upper}")
       set(def_name ${prefix_arg}_${feature_PP})
+      if (feature STREQUAL c_restrict)
+        set(def_value "${prefix_arg}_RESTRICT")
+        set(file_content "${file_content}
+#  if ${def_name}
+#    define ${def_value} restrict
+#  else
+#    define ${def_value}
+#  endif
+\n")
+      endif()
       if (feature STREQUAL cxx_constexpr)
         set(def_value "${prefix_arg}_DECL_${feature_upper}")
         set(file_content "${file_content}
@@ -382,9 +399,8 @@ function(write_compiler_detection_header
 \n")
       endif()
     endforeach()
-    if(_lang STREQUAL CXX)
-      set(file_content "${file_content}#endif\n")
-    endif()
+
+    set(file_content "${file_content}#endif\n")
 
   endforeach()
 

+ 4 - 0
Source/cmLocalGenerator.cxx

@@ -2201,6 +2201,10 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
     // Maintain sorted order, most recent first.
     langStdMap["CXX"].push_back("11");
     langStdMap["CXX"].push_back("98");
+
+    langStdMap["C"].push_back("11");
+    langStdMap["C"].push_back("99");
+    langStdMap["C"].push_back("90");
     }
 
   std::string standard(standardProp);

+ 114 - 2
Source/cmMakefile.cxx

@@ -4973,6 +4973,10 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
 }
 
 #define FEATURE_STRING(F) , #F
+static const char * const C_FEATURES[] = {
+  0
+  FOR_EACH_C_FEATURE(FEATURE_STRING)
+};
 
 static const char * const CXX_FEATURES[] = {
   0
@@ -4980,6 +4984,11 @@ static const char * const CXX_FEATURES[] = {
 };
 #undef FEATURE_STRING
 
+static const char * const C_STANDARDS[] = {
+    "90"
+  , "99"
+  , "11"
+};
 static const char * const CXX_STANDARDS[] = {
     "98"
   , "11"
@@ -4995,10 +5004,13 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
     target->AppendProperty("COMPILE_FEATURES", feature.c_str());
     return true;
     }
+  bool isCFeature = std::find_if(cmArrayBegin(C_FEATURES) + 1,
+              cmArrayEnd(C_FEATURES), cmStrCmp(feature))
+              != cmArrayEnd(C_FEATURES);
   bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1,
               cmArrayEnd(CXX_FEATURES), cmStrCmp(feature))
               != cmArrayEnd(CXX_FEATURES);
-  if (!isCxxFeature)
+  if (!isCFeature && !isCxxFeature)
     {
     cmOStringStream e;
     if (error)
@@ -5022,7 +5034,7 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
     return false;
     }
 
-  std::string lang = "CXX";
+  std::string lang = isCFeature ? "C" : "CXX";
 
   const char* featuresKnown =
     this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
@@ -5071,6 +5083,16 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
 
   target->AppendProperty("COMPILE_FEATURES", feature.c_str());
 
+  return isCFeature
+      ? this->AddRequiredTargetCFeature(target, feature)
+      : this->AddRequiredTargetCxxFeature(target, feature);
+}
+
+//----------------------------------------------------------------------------
+bool cmMakefile::
+AddRequiredTargetCxxFeature(cmTarget *target,
+                            const std::string& feature) const
+{
   bool needCxx98 = false;
   bool needCxx11 = false;
 
@@ -5136,3 +5158,93 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
     }
   return true;
 }
+
+//----------------------------------------------------------------------------
+bool cmMakefile::
+AddRequiredTargetCFeature(cmTarget *target, const std::string& feature) const
+{
+  bool needC90 = false;
+  bool needC99 = false;
+  bool needC11 = false;
+
+  if (const char *propC90 =
+          this->GetDefinition("CMAKE_C90_COMPILE_FEATURES"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propC90, props);
+    needC90 = std::find(props.begin(), props.end(), feature) != props.end();
+    }
+  if (const char *propC99 =
+          this->GetDefinition("CMAKE_C99_COMPILE_FEATURES"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propC99, props);
+    needC99 = std::find(props.begin(), props.end(), feature) != props.end();
+    }
+  if (const char *propC11 =
+          this->GetDefinition("CMAKE_C11_COMPILE_FEATURES"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propC11, props);
+    needC11 = std::find(props.begin(), props.end(), feature) != props.end();
+    }
+
+  const char *existingCStandard = target->GetProperty("C_STANDARD");
+  if (existingCStandard)
+    {
+    if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+                  cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS))
+      {
+      cmOStringStream e;
+      e << "The C_STANDARD property on target \"" << target->GetName()
+        << "\" contained an invalid value: \"" << existingCStandard << "\".";
+      this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+      return false;
+      }
+    }
+  const char * const *existingCIt = existingCStandard
+                                    ? std::find_if(cmArrayBegin(C_STANDARDS),
+                                      cmArrayEnd(C_STANDARDS),
+                                      cmStrCmp(existingCStandard))
+                                    : cmArrayEnd(C_STANDARDS);
+
+  bool setC90 = needC90 && !existingCStandard;
+  bool setC99 = needC99 && !existingCStandard;
+  bool setC11 = needC11 && !existingCStandard;
+
+  if (needC11 && existingCStandard && existingCIt <
+                                    std::find_if(cmArrayBegin(C_STANDARDS),
+                                      cmArrayEnd(C_STANDARDS),
+                                      cmStrCmp("11")))
+    {
+    setC11 = true;
+    }
+  else if(needC99 && existingCStandard && existingCIt <
+                                    std::find_if(cmArrayBegin(C_STANDARDS),
+                                      cmArrayEnd(C_STANDARDS),
+                                      cmStrCmp("99")))
+    {
+    setC99 = true;
+    }
+  else if(needC90 && existingCStandard && existingCIt <
+                                    std::find_if(cmArrayBegin(C_STANDARDS),
+                                      cmArrayEnd(C_STANDARDS),
+                                      cmStrCmp("90")))
+    {
+    setC90 = true;
+    }
+
+  if (setC11)
+    {
+    target->SetProperty("C_STANDARD", "11");
+    }
+  else if (setC99)
+    {
+    target->SetProperty("C_STANDARD", "99");
+    }
+  else if (setC90)
+    {
+    target->SetProperty("C_STANDARD", "90");
+    }
+  return true;
+}

+ 6 - 0
Source/cmMakefile.h

@@ -1098,6 +1098,12 @@ private:
   std::vector<cmSourceFile*> QtUiFilesWithOptions;
 
   unsigned int NumLastMatches;
+
+  bool AddRequiredTargetCFeature(cmTarget *target,
+                                 const std::string& feature) const;
+
+  bool AddRequiredTargetCxxFeature(cmTarget *target,
+                                   const std::string& feature) const;
 };
 
 //----------------------------------------------------------------------------

+ 3 - 0
Source/cmTarget.cxx

@@ -314,6 +314,9 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     this->SetPropertyDefault("MACOSX_BUNDLE", 0);
     this->SetPropertyDefault("MACOSX_RPATH", 0);
     this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0);
+    this->SetPropertyDefault("C_STANDARD", 0);
+    this->SetPropertyDefault("C_STANDARD_REQUIRED", 0);
+    this->SetPropertyDefault("C_EXTENSIONS", 0);
     this->SetPropertyDefault("CXX_STANDARD", 0);
     this->SetPropertyDefault("CXX_STANDARD_REQUIRED", 0);
     this->SetPropertyDefault("CXX_EXTENSIONS", 0);

+ 6 - 2
Source/cmake.cxx

@@ -2273,12 +2273,16 @@ const char *cmake::GetProperty(const std::string& prop,
       }
     this->SetProperty("ENABLED_LANGUAGES", lang.c_str());
     }
+#define STRING_LIST_ELEMENT(F) ";" #F
+  if (prop == "CMAKE_C_KNOWN_FEATURES")
+    {
+    return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
+    }
   if (prop == "CMAKE_CXX_KNOWN_FEATURES")
     {
-#define STRING_LIST_ELEMENT(F) ";" #F
     return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
-#undef STRING_LIST_ELEMENT
     }
+#undef STRING_LIST_ELEMENT
   return this->Properties.GetPropertyValue(prop, scope, chain);
 }
 

+ 6 - 0
Source/cmake.h

@@ -458,6 +458,12 @@ private:
   {"-Wno-dev", "Suppress developer warnings."},\
   {"-Wdev", "Enable developer warnings."}
 
+#define FOR_EACH_C_FEATURE(F) \
+  F(c_function_prototypes) \
+  F(c_restrict) \
+  F(c_static_assert) \
+  F(c_variadic_macros)
+
 #define FOR_EACH_CXX_FEATURE(F) \
   F(cxx_alias_templates) \
   F(cxx_alignas) \

+ 31 - 11
Tests/CMakeCommands/target_compile_features/CMakeLists.txt

@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.0)
 project(target_compile_features)
 
-if (NOT CMAKE_CXX_COMPILE_FEATURES)
+if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES)
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_dummy.cpp"
     "int main(int,char**) { return 0; }\n"
   )
@@ -11,15 +11,35 @@ endif()
 
 set(CMAKE_VERBOSE_MAKEFILE ON)
 
-add_executable(target_compile_features main.cpp)
-target_compile_features(target_compile_features
-  PRIVATE cxx_auto_type
-)
+if (CMAKE_C_COMPILE_FEATURES)
+  add_executable(target_compile_features main.c)
+  target_compile_features(target_compile_features
+    PRIVATE c_restrict
+  )
 
-add_library(lib_auto_type lib_auto_type.cpp)
-target_compile_features(lib_auto_type
-  PUBLIC cxx_auto_type
-)
+  add_library(lib_restrict lib_restrict.c)
+  target_compile_features(lib_restrict
+    PUBLIC c_restrict
+  )
 
-add_executable(lib_user lib_user.cpp)
-target_link_libraries(lib_user lib_auto_type)
+  add_executable(restrict_user restrict_user.c)
+  target_link_libraries(restrict_user lib_restrict)
+endif()
+
+if (CMAKE_CXX_COMPILE_FEATURES)
+  if (CMAKE_C_COMPILE_FEATURES)
+    set(target_suffix _cxx)
+  endif()
+  add_executable(target_compile_features${target_suffix} main.cpp)
+  target_compile_features(target_compile_features${target_suffix}
+    PRIVATE cxx_auto_type
+  )
+
+  add_library(lib_auto_type lib_auto_type.cpp)
+  target_compile_features(lib_auto_type
+    PUBLIC cxx_auto_type
+  )
+
+  add_executable(lib_user lib_user.cpp)
+  target_link_libraries(lib_user lib_auto_type)
+endif()

+ 9 - 0
Tests/CMakeCommands/target_compile_features/lib_restrict.c

@@ -0,0 +1,9 @@
+
+#include "lib_restrict.h"
+
+int foo(int * restrict a, int * restrict b)
+{
+  (void)a;
+  (void)b;
+  return 0;
+}

+ 7 - 0
Tests/CMakeCommands/target_compile_features/lib_restrict.h

@@ -0,0 +1,7 @@
+
+#ifndef LIB_RESTRICT_H
+#define LIB_RESTRICT_H
+
+int foo(int * restrict a, int * restrict b);
+
+#endif

+ 12 - 0
Tests/CMakeCommands/target_compile_features/main.c

@@ -0,0 +1,12 @@
+
+int foo(int * restrict a, int * restrict b)
+{
+  (void)a;
+  (void)b;
+  return 0;
+}
+
+int main()
+{
+  return 0;
+}

+ 14 - 0
Tests/CMakeCommands/target_compile_features/restrict_user.c

@@ -0,0 +1,14 @@
+
+#include "lib_restrict.h"
+
+int bar(int * restrict a, int * restrict b)
+{
+  (void)a;
+  (void)b;
+  return foo(a, b);
+}
+
+int main()
+{
+  return 0;
+}

+ 8 - 2
Tests/CompileFeatures/CMakeLists.txt

@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.0)
 
 project(CompileFeatures)
 
-if (NOT CMAKE_CXX_COMPILE_FEATURES)
+if (NOT CMAKE_C_COMPILE_FEATURES AND NOT CMAKE_CXX_COMPILE_FEATURES)
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
     "int main(int,char**) { return 0; }\n"
   )
@@ -22,6 +22,10 @@ macro(run_test feature lang)
   endif()
 endmacro()
 
+get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
+foreach(feature ${c_features})
+  run_test(${feature} C)
+endforeach()
 get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
 foreach(feature ${cxx_features})
   run_test(${feature} CXX)
@@ -34,9 +38,11 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL GNU
   )
 endif()
 
+set(C_ext c)
+set(C_standard_flag 11)
 set(CXX_ext cpp)
 set(CXX_standard_flag 11)
-foreach(lang CXX)
+foreach(lang CXX C)
   if (CMAKE_${lang}_COMPILE_FEATURES)
     foreach(feature ${${lang}_non_features})
       message("Testing feature : ${feature}")

+ 9 - 0
Tests/CompileFeatures/c_function_prototypes.c

@@ -0,0 +1,9 @@
+
+int someFunc(int a, int b);
+
+int someFunc(int a, int b)
+{
+  (void)a;
+  (void)b;
+  return 0;
+}

+ 7 - 0
Tests/CompileFeatures/c_restrict.c

@@ -0,0 +1,7 @@
+
+int f (int * restrict a, int * restrict b)
+{
+  (void)a;
+  (void)b;
+  return 0;
+}

+ 2 - 0
Tests/CompileFeatures/c_static_assert.c

@@ -0,0 +1,2 @@
+
+_Static_assert(1, "Static assert test");

+ 15 - 0
Tests/CompileFeatures/c_variadic_macros.c

@@ -0,0 +1,15 @@
+
+int someFunc(int i1, char c, int i2)
+{
+  (void)i1;
+  (void)c;
+  (void)i2;
+  return 0;
+}
+
+#define FUNC_WRAPPER(...) someFunc(__VA_ARGS__)
+
+void otherFunc()
+{
+  FUNC_WRAPPER(42, 'a', 7);
+}

+ 12 - 0
Tests/CompileFeatures/main.c

@@ -0,0 +1,12 @@
+
+int foo(int * restrict a, int * restrict b)
+{
+  (void)a;
+  (void)b;
+  return 0;
+}
+
+int main()
+{
+  return 0;
+}

+ 4 - 1
Tests/ExportImport/Export/Interface/CMakeLists.txt

@@ -26,7 +26,10 @@ target_link_libraries(sharediface INTERFACE sharedlib)
 add_library(use_auto_type INTERFACE)
 target_compile_features(use_auto_type INTERFACE cxx_auto_type)
 
-install(TARGETS headeronly sharediface use_auto_type
+add_library(use_c_restrict INTERFACE)
+target_compile_features(use_c_restrict INTERFACE c_restrict)
+
+install(TARGETS headeronly sharediface use_auto_type use_c_restrict
   EXPORT expInterface
 )
 install(TARGETS sharedlib

+ 21 - 0
Tests/ExportImport/Import/Interface/CMakeLists.txt

@@ -17,6 +17,7 @@ set_property(TARGET bld::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES de
 add_executable(interfacetest_bld interfacetest.cpp)
 target_link_libraries(interfacetest_bld bld::sharediface)
 
+include(CheckCSourceCompiles)
 include(CheckCXXSourceCompiles)
 
 macro(do_try_compile prefix)
@@ -41,6 +42,26 @@ macro(do_try_compile prefix)
     message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
   endif()
 
+  if (";${CMAKE_C_COMPILE_FEATURES};" MATCHES ";c_restrict;")
+    set(CMAKE_REQUIRED_LIBRARIES ${prefix}::use_c_restrict)
+    check_c_source_compiles(
+      "
+    int foo(int * restrict a, int * restrict b)
+    {
+      (void)a;
+      (void)b;
+      return 0;
+    }
+    int main()
+    {
+      return 0;
+    }
+    " ${prefix}IMPORTED_IFACE_C_RESTRICT)
+
+    if(NOT ${prefix}IMPORTED_IFACE_C_RESTRICT)
+      message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
+    endif()
+  endif()
   if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;")
     set(CMAKE_REQUIRED_LIBRARIES ${prefix}::use_auto_type)
     check_cxx_source_compiles(

+ 3 - 2
Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt

@@ -6,6 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
 include(WriteCompilerDetectionHeader)
 
 get_property(cxx_known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
+get_property(c_known_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
 
 write_compiler_detection_header(
   FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h"
@@ -15,10 +16,10 @@ write_compiler_detection_header(
   PROLOG "// something"
   EPILOG "// more"
   FEATURES
-    ${cxx_known_features}
+    ${cxx_known_features} ${c_known_features}
 )
 
-if (NOT CMAKE_CXX_COMPILE_FEATURES)
+if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES)
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
     "int main(int,char**) { return 0; }\n"
   )

+ 1 - 0
Tests/RunCMake/CompileFeatures/NoSupportedCFeatures-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/CompileFeatures/NoSupportedCFeatures-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at NoSupportedCFeatures.cmake:[0-9]+ \(target_compile_features\):
+  target_compile_features no known features for C compiler
+
+  "[^"]*"
+
+  version *[.0-9]+\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/CompileFeatures/NoSupportedCFeatures.cmake

@@ -0,0 +1,5 @@
+
+enable_language(C)
+
+add_library(no_features empty.c)
+target_compile_features(no_features PRIVATE c_static_assert)

+ 1 - 0
Tests/RunCMake/CompileFeatures/NoSupportedCFeaturesGenex-result.txt

@@ -0,0 +1 @@
+1

+ 6 - 0
Tests/RunCMake/CompileFeatures/NoSupportedCFeaturesGenex-stderr.txt

@@ -0,0 +1,6 @@
+CMake Error in CMakeLists.txt:
+  No known features for C compiler
+
+  "[^"]*"
+
+  version *[.0-9]+\.

+ 5 - 0
Tests/RunCMake/CompileFeatures/NoSupportedCFeaturesGenex.cmake

@@ -0,0 +1,5 @@
+
+enable_language(C)
+
+add_library(no_features empty.c)
+target_compile_features(no_features PRIVATE $<1:c_static_assert>)

+ 9 - 0
Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake

@@ -9,11 +9,20 @@ run_cmake(NotAFeature_OriginDebugTransitive)
 run_cmake(NotAFeature_OriginDebug_target_compile_features)
 
 run_cmake(generate_feature_list)
+file(READ
+  "${RunCMake_BINARY_DIR}/generate_feature_list-build/c_features.txt"
+  C_FEATURES
+)
 file(READ
   "${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx_features.txt"
   CXX_FEATURES
 )
 
+if (NOT C_FEATURES)
+  run_cmake(NoSupportedCFeatures)
+  run_cmake(NoSupportedCFeaturesGenex)
+endif()
+
 if (NOT CXX_FEATURES)
   run_cmake(NoSupportedCxxFeatures)
   run_cmake(NoSupportedCxxFeaturesGenex)

+ 7 - 0
Tests/RunCMake/CompileFeatures/empty.c

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}

+ 6 - 0
Tests/RunCMake/CompileFeatures/generate_feature_list.cmake

@@ -1,4 +1,10 @@
 
+enable_language(C)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/c_features.txt"
+  "${CMAKE_C_COMPILE_FEATURES}"
+)
+
 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_features.txt"
   "${CMAKE_CXX_COMPILE_FEATURES}"
 )

+ 1 - 1
Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt

@@ -1,4 +1,4 @@
 -- Detecting C compiler ABI info
--- Detecting C compiler ABI info - failed
+-- Detecting C compiler ABI info - failed.*
 -- Configuring done
 -- Generating done

+ 2 - 0
Tests/RunCMake/target_compile_features/RunCMakeTest.cmake

@@ -9,3 +9,5 @@ run_cmake(imported_target)
 run_cmake(no_target)
 run_cmake(not_a_cxx_feature)
 run_cmake(no_matching_cxx_feature)
+run_cmake(not_a_c_feature)
+run_cmake(no_matching_c_feature)

+ 7 - 0
Tests/RunCMake/target_compile_features/empty.c

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}

+ 1 - 0
Tests/RunCMake/target_compile_features/no_matching_c_feature-result.txt

@@ -0,0 +1 @@
+1

+ 8 - 0
Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt

@@ -0,0 +1,8 @@
+CMake Error at no_matching_c_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\):
+  The compiler feature "gnu_c_dummy" is not known to C compiler
+
+  "GNU"
+
+  version 4.8.1.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 15 - 0
Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake

@@ -0,0 +1,15 @@
+
+if (NOT ";${CMAKE_C_COMPILE_FEATURES};" MATCHES ";gnu_c_typeof;")
+  # Simulate passing the test.
+  message(SEND_ERROR
+    "The compiler feature \"gnu_c_dummy\" is not known to C compiler\n\"GNU\"\nversion 4.8.1."
+  )
+  return()
+endif()
+
+add_executable(main empty.c)
+
+target_compile_features(main
+  PRIVATE
+    gnu_c_typeof
+)

+ 1 - 0
Tests/RunCMake/target_compile_features/not_a_c_feature-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt

@@ -0,0 +1,5 @@
+CMake Error at not_a_c_feature.cmake:3 \(target_compile_features\):
+  target_compile_features specified unknown feature "c_not_a_feature" for
+  target "main".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/target_compile_features/not_a_c_feature.cmake

@@ -0,0 +1,6 @@
+
+add_executable(main empty.c)
+target_compile_features(main
+  PRIVATE
+    c_not_a_feature
+)

+ 10 - 0
Tests/SystemInformation/SystemInformation.in

@@ -19,6 +19,16 @@ CMAKE_COMPILER_IS_GNUCC == "${CMAKE_COMPILER_IS_GNUCC}"
 CMAKE_COMPILER_IS_GNUCXX == "${CMAKE_COMPILER_IS_GNUCXX}"
 CMAKE_C_COMPILER_ID == "${CMAKE_C_COMPILER_ID}"
 CMAKE_C_COMPILER_VERSION == "${CMAKE_C_COMPILER_VERSION}"
+CMAKE_C90_STANDARD_COMPILE_OPTION == "${CMAKE_C90_STANDARD_COMPILE_OPTION}"
+CMAKE_C99_STANDARD_COMPILE_OPTION == "${CMAKE_C99_STANDARD_COMPILE_OPTION}"
+CMAKE_C11_STANDARD_COMPILE_OPTION == "${CMAKE_C11_STANDARD_COMPILE_OPTION}"
+CMAKE_C90_EXTENSION_COMPILE_OPTION == "${CMAKE_C90_EXTENSION_COMPILE_OPTION}"
+CMAKE_C99_EXTENSION_COMPILE_OPTION == "${CMAKE_C99_EXTENSION_COMPILE_OPTION}"
+CMAKE_C11_EXTENSION_COMPILE_OPTION == "${CMAKE_C11_EXTENSION_COMPILE_OPTION}"
+CMAKE_C_COMPILE_FEATURES == "${CMAKE_C_COMPILE_FEATURES}"
+CMAKE_C90_COMPILE_FEATURES == "${CMAKE_C90_COMPILE_FEATURES}"
+CMAKE_C99_COMPILE_FEATURES == "${CMAKE_C99_COMPILE_FEATURES}"
+CMAKE_C11_COMPILE_FEATURES == "${CMAKE_C11_COMPILE_FEATURES}"
 CMAKE_CXX_COMPILER_ID == "${CMAKE_CXX_COMPILER_ID}"
 CMAKE_CXX_COMPILER_VERSION == "${CMAKE_CXX_COMPILER_VERSION}"
 CMAKE_CXX98_STANDARD_COMPILE_OPTION == "${CMAKE_CXX98_STANDARD_COMPILE_OPTION}"