[Cmake-commits] CMake branch, next, updated. v2.8.12.1-5930-ga13cc11

Stephen Kelly steveire at gmail.com
Thu Nov 28 15:15:13 EST 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  a13cc11d512f76d035e467276b1a8f9f6ce05575 (commit)
       via  c8605c913f82252eadd87d4eafeb4172d29628f9 (commit)
       via  531620ce8e2512fc7748e971e178d36624d697ca (commit)
       via  4bd4da690b34dfba444167fdaf7f6411368df94a (commit)
       via  0acfb5c50675aeaa3a23269a0815a6170083899b (commit)
       via  f2c14bd14ff399df4a3374eb210bd74649cd1e5f (commit)
       via  8bbbee3c0be8bbe573fed21fac30cc9b635b3ddb (commit)
       via  f84c532f94118f17512f6d1ed80a28862bfda122 (commit)
       via  91cdb7c9032297aa394b52e9ff4e3cc27695ec55 (commit)
       via  d438d5bb784a3651d7f2f4ddbbdec6a0c262e844 (commit)
       via  11e3ed692889017cb6ae9bf83723b944abe219b5 (commit)
       via  9a629418b831d0a8cf08f164f22e9c72cf020075 (commit)
       via  a7b356ba6abf4c740fd7af2d2da0165ae36edcac (commit)
       via  90ab0f03626960bda1ca2b56e2d4ad2d69083283 (commit)
       via  aea693e73f16977b708b3e32c3d3ac46fd598ecf (commit)
       via  89e36dffe0af0942dc9086a8b42754410b306cae (commit)
      from  b620f7b0d5f77106823d0a43d9334d68dbcfa0e4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a13cc11d512f76d035e467276b1a8f9f6ce05575
commit a13cc11d512f76d035e467276b1a8f9f6ce05575
Merge: b620f7b c8605c9
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Nov 28 15:15:04 2013 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Thu Nov 28 15:15:04 2013 -0500

    Merge topic 'target_compile_features' into next
    
    c8605c9 Add the WriteCompilerDetectionHeader module.
    531620c Add a cxx_binary_literals feature.
    4bd4da6 Genex: Add $<HAVE_COMPILER_FEATURE:LANG,FEATURE> genex.
    0acfb5c Add a cxx_variadic_templates feature.
    f2c14bd Remove version checks.
    8bbbee3 Base the target_compile_features command on cmTargetPropCommandBase.
    f84c532 cmTargetPropCommandBase: Change the interface to return bool.
    91cdb7c cmTarget: Transitively evaluate compiler features.
    d438d5b cmTarget: Allow populating COMPILE_FEATURES using generator expressions.
    11e3ed6 cmTarget: Make COMPILE_FEATURES available as a target property.
    9a62941 Add target_compile_features command.
    a7b356b Record compilers capable of msvcxx_sealed feature.
    90ab0f0 Record compilers capable of the gnuxx_typeof feature.
    aea693e Record the compilers capable of the cxx_delegating_constructors feature.
    89e36df cmTarget: Add CXX_STANDARD and CXX_EXTENSION target properties.


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c8605c913f82252eadd87d4eafeb4172d29628f9
commit c8605c913f82252eadd87d4eafeb4172d29628f9
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Oct 21 16:59:40 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    Add the WriteCompilerDetectionHeader module.
    
    Provide a function to write a portable header to detect compiler
    features.

diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
index f98f787..2fb6cd8 100644
--- a/Modules/Compiler/Clang-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
@@ -1,4 +1,6 @@
 
+set(_cmake_compiler_test_macro __clang__)
+
 set(testable_features
   cxx_delegating_constructors
   cxx_variadic_templates
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
index 68ac0c0..5f5426e 100644
--- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -1,4 +1,6 @@
 
+set(_cmake_compiler_test_macro __GNUC__)
+
 set(_cmake_feature_test_gnuxx_typeof "!defined(__STRICT_ANSI__)")
 
 # For GCC 4.7, we can test the standard __cplusplus macro, ...
diff --git a/Modules/Compiler/MSVC-CXX-FeatureTests.cmake b/Modules/Compiler/MSVC-CXX-FeatureTests.cmake
index 7a56acd..ea0a349 100644
--- a/Modules/Compiler/MSVC-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/MSVC-CXX-FeatureTests.cmake
@@ -1,2 +1,4 @@
 
+set(_cmake_compiler_test_macro _MSC_VER)
+
 set(_cmake_feature_test_msvcxx_sealed "_MSC_VER >= 1400")
diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake
new file mode 100644
index 0000000..c876301
--- /dev/null
+++ b/Modules/WriteCompilerDetectionHeader.cmake
@@ -0,0 +1,124 @@
+
+#=============================================================================
+# Copyright 2013 Stephen Kelly <steveire at gmail.com>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# Should we enable the highest supported lang flag?
+
+include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
+
+function(_load_compiler_variables CompilerId lang)
+  include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-${lang}-FeatureTests.cmake" OPTIONAL)
+  if (NOT _cmake_compiler_test_macro)
+    message(FATAL_ERROR "Compiler ${CompilerId} does not define _cmake_compiler_test_macro")
+  endif()
+  foreach(feature ${ARGN})
+    set(x ${_cmake_feature_tests_${feature}})
+    if (_cmake_feature_test_${feature})
+      set(n "defined (${_cmake_compiler_test_macro})")
+      if (NOT _cmake_feature_test_${feature} STREQUAL "1")
+        set(n "(${n} && ${_cmake_feature_test_${feature}})")
+      endif()
+      list(APPEND x ${n})
+      set(_cmake_feature_tests_${feature} ${x} PARENT_SCOPE)
+    endif()
+  endforeach()
+endfunction()
+
+function(write_compiler_detection_header
+    file_keyword file_arg
+    prefix_keyword prefix_arg
+    )
+  if (NOT file_keyword STREQUAL FILE)
+    message(FATAL_ERROR "Wrong parameters for function.")
+  endif()
+  if (NOT prefix_keyword STREQUAL PREFIX)
+    message(FATAL_ERROR "Wrong parameters for function.")
+  endif()
+  set(options)
+  set(oneValueArgs VERSION)
+  set(multiValueArgs COMPILERS FEATURES)
+  cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT _WCD_COMPILERS OR NOT _WCD_FEATURES)
+    message(FATAL_ERROR "Invalid arguments.")
+  endif()
+
+  if(_WCD_UNPARSED_ARGUMENTS)
+    message(FATAL_ERROR "Unparsed arguments: ${_WCD_UNPARSED_ARGUMENTS}")
+  endif()
+
+  if(NOT _WCD_VERSION)
+    set(_WCD_VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION})
+  endif()
+#   if (_WCD_VERSION VERSION_LESS 3.0.0) # Version which introduced this function
+#     message(FATAL_ERROR "VERSION parameter too low.")
+#   endif()
+
+  set(ordered_compilers
+    # Order is relevant here. We need to list the compilers which pretend to
+    # be GNU/MSVC before the actual GNU/MSVC compiler.
+    Clang
+    GNU
+    MSVC
+  )
+  foreach(_comp ${_WCD_COMPILERS})
+    list(FIND ordered_compilers ${_comp} idx)
+    if (idx EQUAL -1)
+      message(FATAL_ERROR "Unsupported compiler ${_comp}.")
+    endif()
+  endforeach()
+
+  file(WRITE ${file_arg} "
+// This is a generated file. Do not edit!
+
+#ifndef ${prefix_arg}_COMPILER_DETECTION_H
+#define ${prefix_arg}_COMPILER_DETECTION_H
+
+#if !defined (__clang__)
+#define __has_extension(ext) 0
+#endif
+")
+
+  foreach(_lang CXX)
+
+    foreach(ordered_compiler ${ordered_compilers})
+      list(FIND _WCD_COMPILERS ${ordered_compiler} idx)
+      if (NOT idx EQUAL -1)
+        _load_compiler_variables(${ordered_compiler} ${_lang} ${_WCD_FEATURES})
+      endif()
+    endforeach()
+
+    if(_lang STREQUAL CXX)
+      file(APPEND "${file_arg}" "\n#ifdef __cplusplus\n")
+    endif()
+    foreach(feature ${_WCD_FEATURES})
+      list(FIND CMAKE_${_lang}_KNOWN_FEATURES ${feature} idx)
+      if (NOT idx EQUAL -1)
+        set(_define_check "\n#define ${prefix_arg}_${CMAKE_PP_NAME_${feature}} 0\n")
+        if (_cmake_feature_tests_${feature} STREQUAL "1")
+          set(_define_check "\n#define ${prefix_arg}_${CMAKE_PP_NAME_${feature}} 1\n")
+        elseif (_cmake_feature_tests_${feature})
+          string(REPLACE ";" " \\\n    || " _cmake_feature_tests_${feature} "${_cmake_feature_tests_${feature}}")
+          set(_define_check "\n#if ${_cmake_feature_tests_${feature}}\n#define ${prefix_arg}_${CMAKE_PP_NAME_${feature}} 1\n#else${_define_check}#endif\n")
+        endif()
+        file(APPEND "${file_arg}" "${_define_check}")
+      endif()
+    endforeach()
+    if(_lang STREQUAL CXX)
+      file(APPEND "${file_arg}" "\n#endif\n")
+    endif()
+
+  endforeach()
+
+  file(APPEND ${file_arg} "\n#endif\n")
+endfunction()
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index cb89e36..2b8b504 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -412,6 +412,11 @@ if(BUILD_TESTING)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Module/ExternalData")
 
   ADD_TEST_MACRO(Module.GenerateExportHeader GenerateExportHeader)
+  if ((CMAKE_CXX_COMPILER_ID STREQUAL GNU AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
+      OR CMAKE_CXX_COMPILER_ID STREQUAL Clang
+      OR (x${CMAKE_CXX_COMPILER_ID} STREQUAL xMSVC AND NOT MSVC_VERSION VERSION_LESS 1400))
+    ADD_TEST_MACRO(Module.WriteCompilerDetectionHeader WriteCompilerDetectionHeader)
+  endif()
 
   if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
     include(CheckCXXCompilerFlag)
diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
new file mode 100644
index 0000000..a99dae9
--- /dev/null
+++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
@@ -0,0 +1,101 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(WriteCompilerDetectionHeader)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+include(WriteCompilerDetectionHeader)
+
+write_compiler_detection_header(
+  FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h"
+  PREFIX TEST
+  COMPILERS GNU Clang MSVC
+  FEATURES
+    ${CMAKE_CXX_KNOWN_FEATURES}
+)
+
+macro(set_defines target true_defs false_defs)
+  set(defines)
+  foreach(def ${true_defs})
+    list(APPEND defines ${def}=1)
+  endforeach()
+  foreach(def ${false_defs})
+    list(APPEND defines ${def}=0)
+  endforeach()
+  target_compile_definitions(${target}
+    PRIVATE
+      ${defines}
+  )
+endmacro()
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL GNU
+    OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+  list(APPEND true_defs EXPECTED_COMPILER_CXX_BINARY_LITERALS)
+  list(APPEND false_defs EXPECTED_COMPILER_MSVCXX_SEALED)
+elseif(x${CMAKE_CXX_COMPILER_ID} STREQUAL xMSVC)
+  list(APPEND false_defs EXPECTED_COMPILER_CXX_BINARY_LITERALS)
+  list(APPEND true_defs EXPECTED_COMPILER_MSVCXX_SEALED)
+else()
+  list(APPEND false_defs EXPECTED_COMPILER_CXX_BINARY_LITERALS)
+  list(APPEND false_defs EXPECTED_COMPILER_MSVCXX_SEALED)
+endif()
+
+list(APPEND false_defs EXPECTED_COMPILER_GNUXX_TYPEOF)
+list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
+list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
+
+add_executable(WriteCompilerDetectionHeader main.cpp)
+set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98)
+set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}")
+
+if(MSVC)
+  return() # MSVC has only one mode.
+endif()
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL GNU
+    OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+  list(APPEND true_defs EXPECTED_COMPILER_GNUXX_TYPEOF)
+  list(REMOVE_ITEM false_defs EXPECTED_COMPILER_GNUXX_TYPEOF)
+endif()
+
+add_executable(WriteCompilerDetectionHeader_98ext main.cpp)
+set_property(TARGET WriteCompilerDetectionHeader_98ext PROPERTY CXX_STANDARD 98)
+set_property(TARGET WriteCompilerDetectionHeader_98ext PROPERTY CXX_EXTENSIONS 1)
+set_defines(WriteCompilerDetectionHeader_98ext "${true_defs}" "${false_defs}")
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL GNU
+    OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+  list(APPEND false_defs  EXPECTED_COMPILER_GNUXX_TYPEOF)
+  list(REMOVE_ITEM true_defs EXPECTED_COMPILER_GNUXX_TYPEOF)
+endif()
+
+if ((CMAKE_CXX_COMPILER_ID STREQUAL GNU
+      AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7.0)
+    OR (CMAKE_CXX_COMPILER_ID STREQUAL Clang
+      AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.0.0))
+  list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
+  list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
+endif()
+
+if ((CMAKE_CXX_COMPILER_ID STREQUAL GNU
+      AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7.0)
+    OR (CMAKE_CXX_COMPILER_ID STREQUAL Clang
+      AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.0.0))
+  list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
+  list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
+endif()
+
+add_executable(WriteCompilerDetectionHeader_11 main.cpp)
+set_property(TARGET WriteCompilerDetectionHeader_11 PROPERTY CXX_STANDARD 11)
+set_defines(WriteCompilerDetectionHeader_11 "${true_defs}" "${false_defs}")
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL GNU
+    OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+  list(APPEND true_defs EXPECTED_COMPILER_GNUXX_TYPEOF)
+  list(REMOVE_ITEM false_defs EXPECTED_COMPILER_GNUXX_TYPEOF)
+endif()
+
+add_executable(WriteCompilerDetectionHeader_11ext main.cpp)
+set_property(TARGET WriteCompilerDetectionHeader_11ext PROPERTY CXX_STANDARD 11)
+set_property(TARGET WriteCompilerDetectionHeader_11ext PROPERTY CXX_EXTENSIONS 1)
+set_defines(WriteCompilerDetectionHeader_11ext "${true_defs}" "${false_defs}")
diff --git a/Tests/Module/WriteCompilerDetectionHeader/main.cpp b/Tests/Module/WriteCompilerDetectionHeader/main.cpp
new file mode 100644
index 0000000..cccd19d
--- /dev/null
+++ b/Tests/Module/WriteCompilerDetectionHeader/main.cpp
@@ -0,0 +1,31 @@
+
+#include "test_compiler_detection.h"
+
+#define JOIN_IMPL(A, B) A ## B
+#define JOIN(A, B) JOIN_IMPL(A, B)
+#define CHECK(FEATURE) (JOIN(TEST_COMPILER_, FEATURE) == JOIN(EXPECTED_COMPILER_, FEATURE))
+
+#if !CHECK(CXX_BINARY_LITERALS)
+#error cxx_binary_literals expected availability did not match.
+#endif
+
+#if !CHECK(CXX_DELEGATING_CONSTRUCTORS)
+#error cxx_delegating_constructors expected availability did not match.
+#endif
+
+#if !CHECK(CXX_VARIADIC_TEMPLATES)
+#error cxx_variadic_templates expected availability did not match.
+#endif
+
+#if !CHECK(GNUXX_TYPEOF)
+#error gnuxx_typeof expected availability did not match.
+#endif
+
+#if !CHECK(MSVCXX_SEALED)
+#error msvcxx_sealed expected availability did not match.
+#endif
+
+int main(int argc, char **argv)
+{
+  return 0;
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=531620ce8e2512fc7748e971e178d36624d697ca
commit 531620ce8e2512fc7748e971e178d36624d697ca
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 13 10:42:02 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    Add a cxx_binary_literals feature.
    
    Supported by GCC in c++98 mode, though it is a c++1y standard feature.

diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 28bd1cf..af911fb 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -3,6 +3,7 @@ set(CMAKE_CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@")
 set(CMAKE_CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@")
 set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@")
 set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@")
+set(CMAKE_CXX98_COMPILE_FEATURES "@CMAKE_CXX98_COMPILE_FEATURES@")
 set(CMAKE_CXX98_COMPILE_EXTENSIONS "@CMAKE_CXX98_COMPILE_EXTENSIONS@")
 set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
 set(CMAKE_CXX11_COMPILE_EXTENSIONS "@CMAKE_CXX11_COMPILE_EXTENSIONS@")
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
index 7950144..2a7f10b 100644
--- a/Modules/CMakeDetermineCompileFeatures.cmake
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -17,6 +17,7 @@ function(cmake_determine_compile_features lang)
   if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
     message(STATUS "Detecting ${lang} compile features")
 
+    set(CMAKE_CXX98_COMPILE_FEATURES)
     set(CMAKE_CXX98_COMPILE_EXTENSIONS)
     set(CMAKE_CXX11_COMPILE_FEATURES)
     set(CMAKE_CXX11_COMPILE_EXTENSIONS)
@@ -32,9 +33,11 @@ function(cmake_determine_compile_features lang)
 
     string(REPLACE "${CMAKE_CXX98_COMPILE_EXTENSIONS}" "" CMAKE_CXX11_COMPILE_EXTENSIONS "${CMAKE_CXX11_COMPILE_EXTENSIONS}")
     string(REPLACE "${CMAKE_CXX11_COMPILE_FEATURES}" "" CMAKE_CXX11_COMPILE_EXTENSIONS "${CMAKE_CXX11_COMPILE_EXTENSIONS}")
+    string(REPLACE "${CMAKE_CXX98_COMPILE_FEATURES}" "" CMAKE_CXX98_COMPILE_EXTENSIONS "${CMAKE_CXX98_COMPILE_EXTENSIONS}")
 
     if(NOT CMAKE_CXX_COMPILE_FEATURES)
       set(CMAKE_CXX_COMPILE_FEATURES
+        ${CMAKE_CXX98_COMPILE_FEATURES}
         ${CMAKE_CXX98_COMPILE_EXTENSIONS}
         ${CMAKE_CXX11_COMPILE_FEATURES}
         ${CMAKE_CXX11_COMPILE_EXTENSIONS}
diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
index 0b2ceca..f98f787 100644
--- a/Modules/Compiler/Clang-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
@@ -2,6 +2,7 @@
 set(testable_features
   cxx_delegating_constructors
   cxx_variadic_templates
+  cxx_binary_literals
 )
 foreach(feature ${testable_features})
   set(_cmake_feature_test_${feature} "__has_extension(${feature})")
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
index 3606ed8..68ac0c0 100644
--- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -11,3 +11,4 @@ set(_cmake_feature_test_gnuxx_typeof "!defined(__STRICT_ANSI__)")
 
 set(_cmake_feature_test_cxx_delegating_constructors "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L")
 set(_cmake_feature_test_cxx_variadic_templates "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L")
+set(_cmake_feature_test_cxx_binary_literals "1")
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 71921e8..1f86232 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -44,6 +44,7 @@
 #define FOR_EACH_CXX_FEATURE(F) \
   F(cxx_delegating_constructors) \
   F(cxx_variadic_templates) \
+  F(cxx_binary_literals) \
   F(gnuxx_typeof) \
   F(msvcxx_sealed)
 
diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
index ab79b29..35fcd43 100644
--- a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
@@ -32,4 +32,11 @@ target_compile_features(lib_delegating_constructors
 add_executable(lib_user lib_user.cpp)
 target_link_libraries(lib_user lib_delegating_constructors)
 
+if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang")
+  add_executable(binary_literals binary_literals.cpp)
+  target_compile_features(binary_literals
+    PRIVATE cxx_binary_literals
+  )
+endif()
+
 add_subdirectory(feature_conditional_link)
diff --git a/Tests/CMakeCommands/target_compile_features/binary_literals.cpp b/Tests/CMakeCommands/target_compile_features/binary_literals.cpp
new file mode 100644
index 0000000..3956e73
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/binary_literals.cpp
@@ -0,0 +1,6 @@
+
+int main(int, char **)
+{
+  int i = 0b0101;
+  return i - 5;
+}
diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in
index 97298dc..669a6f9 100644
--- a/Tests/SystemInformation/SystemInformation.in
+++ b/Tests/SystemInformation/SystemInformation.in
@@ -26,6 +26,7 @@ CMAKE_CXX11_STANDARD_COMPILE_OPTION == "${CMAKE_CXX11_STANDARD_COMPILE_OPTION}"
 CMAKE_CXX98_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX98_EXTENSION_COMPILE_OPTION}"
 CMAKE_CXX11_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}"
 CMAKE_CXX_COMPILE_FEATURES == "${CMAKE_CXX_COMPILE_FEATURES}"
+CMAKE_CXX98_COMPILE_FEATURES == "${CMAKE_CXX98_COMPILE_FEATURES}"
 CMAKE_CXX98_COMPILE_EXTENSIONS == "${CMAKE_CXX98_COMPILE_EXTENSIONS}"
 CMAKE_CXX11_COMPILE_FEATURES == "${CMAKE_CXX11_COMPILE_FEATURES}"
 CMAKE_CXX11_COMPILE_EXTENSIONS == "${CMAKE_CXX11_COMPILE_EXTENSIONS}"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4bd4da690b34dfba444167fdaf7f6411368df94a
commit 4bd4da690b34dfba444167fdaf7f6411368df94a
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 01:51:34 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    Genex: Add $<HAVE_COMPILER_FEATURE:LANG,FEATURE> genex.

diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index ed28abd..26fa77f 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -81,6 +81,8 @@ otherwise expands to nothing.
   else ``0``.  If the policy was not set, the warning message for the policy
   will be emitted. This generator expression only works for a subset of
   policies.
+``$<HAVE_COMPILE_FEATURE:lang,feature>``
+  ``1`` if the ``CMAKE_<lang>_COMPILER`` supports ``feature``, otherwise ``0``.
 
 Informational Expressions
 =========================
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 0f8c4e3..7f40b0b 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -585,6 +585,58 @@ static const struct LinkOnlyNode : public cmGeneratorExpressionNode
 } linkOnlyNode;
 
 //----------------------------------------------------------------------------
+static const struct HaveFeatureNode : public cmGeneratorExpressionNode
+{
+  HaveFeatureNode() {}
+
+  virtual int NumExpectedParameters() const { return 2; }
+
+  std::string Evaluate(const std::vector<std::string> &parameters,
+                       cmGeneratorExpressionContext *context,
+                       const GeneratorExpressionContent *content,
+                       cmGeneratorExpressionDAGChecker *) const
+  {
+    if (!context->HeadTarget)
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "$<HAVE_COMPILER_FEATURE:lang,feature> may only be used with "
+          "targets.  It may not be used with add_custom_command.");
+      return std::string();
+      }
+    if (context->HeadTarget->GetType() == cmTarget::INTERFACE_LIBRARY)
+      {
+      return "0";
+      }
+    std::string def = "CMAKE_" + parameters.front() + "_KNOWN_FEATURES";
+    const char *knownFeatures = context->Makefile ?
+                              context->Makefile->GetDefinition(
+                              def.c_str()) : 0;
+    assert(knownFeatures);
+    std::vector<std::string> featuresVec;
+    cmSystemTools::ExpandListArgument(knownFeatures, featuresVec);
+    if (std::find(featuresVec.begin(),
+                     featuresVec.end(),
+                     parameters[1]) == featuresVec.end())
+      {
+      reportError(context, content->GetOriginalExpression(),
+          "Unknown feature!");
+      return std::string();
+      }
+    const char *tgtProp =
+                        context->HeadTarget->GetProperty("COMPILE_FEATURES");
+    if(!tgtProp)
+      {
+      return "0";
+      }
+    featuresVec.clear();
+    cmSystemTools::ExpandListArgument(tgtProp, featuresVec);
+    return std::find(featuresVec.begin(),
+                     featuresVec.end(),
+                     parameters[1]) == featuresVec.end() ? "0" : "1";
+  }
+} haveFeatureNode;
+
+//----------------------------------------------------------------------------
 static const struct ConfigurationNode : public cmGeneratorExpressionNode
 {
   ConfigurationNode() {}
@@ -1514,6 +1566,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
     return &joinNode;
   else if (identifier == "LINK_ONLY")
     return &linkOnlyNode;
+  else if (identifier == "HAVE_COMPILER_FEATURE")
+    return &haveFeatureNode;
   return 0;
 
 }
diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
index 3a42088..ab79b29 100644
--- a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
@@ -31,3 +31,5 @@ target_compile_features(lib_delegating_constructors
 
 add_executable(lib_user lib_user.cpp)
 target_link_libraries(lib_user lib_delegating_constructors)
+
+add_subdirectory(feature_conditional_link)
diff --git a/Tests/CMakeCommands/target_compile_features/feature_conditional_link/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/CMakeLists.txt
new file mode 100644
index 0000000..64c6332
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/CMakeLists.txt
@@ -0,0 +1,26 @@
+
+add_library(no_variadics INTERFACE)
+target_include_directories(no_variadics INTERFACE no_variadics)
+add_library(have_variadics INTERFACE)
+target_include_directories(have_variadics INTERFACE have_variadics)
+
+add_library(maybe_variadics INTERFACE)
+target_link_libraries(maybe_variadics INTERFACE
+  $<$<HAVE_COMPILER_FEATURE:CXX,cxx_variadic_templates>:have_variadics>
+  $<$<NOT:$<HAVE_COMPILER_FEATURE:CXX,cxx_variadic_templates>>:no_variadics>
+)
+
+# Upstream publishes maybe_variadics, we use it below.
+
+add_executable(template_user_with_variadics template_user.cpp)
+target_compile_features(template_user_with_variadics PRIVATE cxx_variadic_templates)
+
+target_link_libraries(template_user_with_variadics
+  maybe_variadics
+)
+
+add_executable(template_user_no_variadics template_user.cpp)
+
+target_link_libraries(template_user_no_variadics
+  maybe_variadics
+)
diff --git a/Tests/CMakeCommands/target_compile_features/feature_conditional_link/have_variadics/interface.h b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/have_variadics/interface.h
new file mode 100644
index 0000000..a4f87c0
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/have_variadics/interface.h
@@ -0,0 +1,20 @@
+template<int I, int... Is>
+struct Interface;
+
+template<int I>
+struct Interface<I>
+{
+  static int accumulate()
+  {
+    return I;
+  }
+};
+
+template<int I, int... Is>
+struct Interface
+{
+  static int accumulate()
+  {
+    return I + Interface<Is...>::accumulate();
+  }
+};
diff --git a/Tests/CMakeCommands/target_compile_features/feature_conditional_link/no_variadics/interface.h b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/no_variadics/interface.h
new file mode 100644
index 0000000..5c5263a
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/no_variadics/interface.h
@@ -0,0 +1,6 @@
+
+template<int I1, int I2 = 0, int I3 = 0, int I4 = 0>
+struct Interface
+{
+  static int accumulate() { return I1 + I2 + I3 + I4; }
+};
diff --git a/Tests/CMakeCommands/target_compile_features/feature_conditional_link/template_user.cpp b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/template_user.cpp
new file mode 100644
index 0000000..f15362c
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/feature_conditional_link/template_user.cpp
@@ -0,0 +1,8 @@
+
+#include <interface.h>
+
+int main(int argc, char **argv)
+{
+  int result = Interface<1, 2, 3, 4>::accumulate();
+  return result == 10 ? 0 : 1;
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0acfb5c50675aeaa3a23269a0815a6170083899b
commit 0acfb5c50675aeaa3a23269a0815a6170083899b
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 15:19:52 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    Add a cxx_variadic_templates feature.

diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
index 3aa5017..fdc5f82 100644
--- a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -14,6 +14,11 @@ cxx_delegating_constructors
 
 .. _N1986: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
 
+cxx_variadic_templates
+  Variadic templates, as defined in N2242_.
+
+.. _N2242: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf
+
 gnuxx_typeof
   The GNU typeof extension.
 
diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
index f1eb031..0b2ceca 100644
--- a/Modules/Compiler/Clang-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
@@ -1,6 +1,7 @@
 
 set(testable_features
   cxx_delegating_constructors
+  cxx_variadic_templates
 )
 foreach(feature ${testable_features})
   set(_cmake_feature_test_${feature} "__has_extension(${feature})")
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
index e48d485..3606ed8 100644
--- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -10,3 +10,4 @@ set(_cmake_feature_test_gnuxx_typeof "!defined(__STRICT_ANSI__)")
 # set(isCxx11Mode "defined(__GXX_EXPERIMENTAL_CXX0X__)")
 
 set(_cmake_feature_test_cxx_delegating_constructors "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L")
+set(_cmake_feature_test_cxx_variadic_templates "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L")
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 05fca7b..71921e8 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -43,6 +43,7 @@
 
 #define FOR_EACH_CXX_FEATURE(F) \
   F(cxx_delegating_constructors) \
+  F(cxx_variadic_templates) \
   F(gnuxx_typeof) \
   F(msvcxx_sealed)
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f2c14bd14ff399df4a3374eb210bd74649cd1e5f
commit f2c14bd14ff399df4a3374eb210bd74649cd1e5f
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Nov 28 13:21:25 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    Remove version checks.
    
    These files can't have version checks as they can be read by a
    CMake which has a different compiler loaded.

diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
index 3580afc..f1eb031 100644
--- a/Modules/Compiler/Clang-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
@@ -1,9 +1,4 @@
 
-if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
-  # This file is only loaded if Clang >= 2.1
-  message(FATAL_ERROR "This file should not be included for Clang < 2.1.")
-endif()
-
 set(testable_features
   cxx_delegating_constructors
 )
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
index 13c6128..e48d485 100644
--- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -1,11 +1,6 @@
 
 set(_cmake_feature_test_gnuxx_typeof "!defined(__STRICT_ANSI__)")
 
-if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
-  # This file is only loaded if GCC >= 4.3
-  message(FATAL_ERROR "This file should not be included for GCC < 4.3.")
-endif()
-
 # For GCC 4.7, we can test the standard __cplusplus macro, ...
 # set(isCxx98Mode "__cplusplus >= 199711L")
 # set(isCxx11Mode "__cplusplus >= 201103L")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8bbbee3c0be8bbe573fed21fac30cc9b635b3ddb
commit 8bbbee3c0be8bbe573fed21fac30cc9b635b3ddb
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Wed Oct 30 21:13:44 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    Base the target_compile_features command on cmTargetPropCommandBase.
    
    This gives us 'free' handling of IMPORTED, ALIAS, INTERFACE,
    non-compilable and missing targets.

diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index 8b48ce3..8a7e5f8 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -15,49 +15,56 @@ bool cmTargetCompileFeaturesCommand::InitialPass(
   std::vector<std::string> const& args,
   cmExecutionStatus &)
 {
-  if (args.size() < 3)
-    {
-      this->SetError("called with wrong number of arguments.");
-      return false;
-    }
-  cmTarget *target = this->Makefile->FindTargetToUse(args[0].c_str());
+  return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
+}
 
-  if(!target)
-    {
-    this->SetError("specified invalid target.");
-    return false;
-    }
+void cmTargetCompileFeaturesCommand
+::HandleImportedTarget(const std::string &tgt)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile features for imported target \""
+    << tgt << "\".";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
 
-  if(target->IsImported())
-    {
-    this->SetError("may not be used with an IMPORTED target.");
-    return false;
-    }
+void cmTargetCompileFeaturesCommand
+::HandleMissingTarget(const std::string &name)
+{
+  cmOStringStream e;
+  e << "Cannot specify compile features for target \"" << name << "\" "
+       "which is not built by this project.";
+  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
 
-  const bool interfaceOnly = args[1] == "INTERFACE";
-  if(args[1] != "PRIVATE" && args[1] != "PUBLIC" && !interfaceOnly)
+//----------------------------------------------------------------------------
+std::string cmTargetCompileFeaturesCommand
+::Join(const std::vector<std::string> &content)
+{
+  std::string defs;
+  std::string sep;
+  for(std::vector<std::string>::const_iterator it = content.begin();
+    it != content.end(); ++it)
     {
-    this->SetError("called with invalid arguments.");
-    return false;
+    defs += sep + *it;
+    sep = ";";
     }
+  return defs;
+}
 
-  for (size_t i = 2; i < args.size(); ++i)
+//----------------------------------------------------------------------------
+bool cmTargetCompileFeaturesCommand
+::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
+                                   bool, bool)
+{
+  for(std::vector<std::string>::const_iterator it = content.begin();
+    it != content.end(); ++it)
     {
-    std::string feature = args[i];
-
-    if (!interfaceOnly)
-      {
-      if (!this->Makefile->AddRequiredTargetFeature(target, feature.c_str()))
-        {
-        cmOStringStream e;
-        e << "specified unknown feature \"" << feature << "\".";
-        this->SetError(e.str().c_str());
-        return false;
-        }
-      }
-    if (interfaceOnly || args[1] == "PUBLIC")
+    if(!this->Makefile->AddRequiredTargetFeature(tgt, it->c_str()))
       {
-      target->AppendProperty("INTERFACE_COMPILE_FEATURES", feature.c_str());
+      cmOStringStream e;
+      e << "specified unknown feature \"" << *it << "\".";
+      this->SetError(e.str().c_str());
+      return false;
       }
     }
   return true;
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
index 63beeca..97a61ba 100644
--- a/Source/cmTargetCompileFeaturesCommand.h
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -12,9 +12,9 @@
 #ifndef cmTargetCompileFeaturesCommand_h
 #define cmTargetCompileFeaturesCommand_h
 
-#include "cmCommand.h"
+#include "cmTargetPropCommandBase.h"
 
-class cmTargetCompileFeaturesCommand : public cmCommand
+class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
 {
   virtual cmCommand* Clone()
     {
@@ -26,7 +26,16 @@ class cmTargetCompileFeaturesCommand : public cmCommand
 
   virtual const char* GetName() const { return "target_compile_features";}
 
-  cmTypeMacro(cmTargetCompileFeaturesCommand, cmCommand);
+  cmTypeMacro(cmTargetCompileFeaturesCommand, cmTargetPropCommandBase);
+
+private:
+  virtual void HandleImportedTarget(const std::string &tgt);
+  virtual void HandleMissingTarget(const std::string &name);
+
+  virtual bool HandleDirectContent(cmTarget *tgt,
+                                   const std::vector<std::string> &content,
+                                   bool prepend, bool system);
+  virtual std::string Join(const std::vector<std::string> &content);
 };
 
 #endif
diff --git a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
index 28341c9..f2abef7 100644
--- a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
@@ -1,4 +1,11 @@
 include(RunCMake)
 
+run_cmake(not_enough_args)
+run_cmake(alias_target)
+run_cmake(utility_target)
+run_cmake(invalid_args)
+run_cmake(invalid_args_on_interface)
+run_cmake(imported_target)
+run_cmake(no_target)
 run_cmake(not_a_cxx_feature)
 run_cmake(no_matching_cxx_feature)
diff --git a/Tests/RunCMake/target_compile_features/alias_target-result.txt b/Tests/RunCMake/target_compile_features/alias_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/alias_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/alias_target-stderr.txt b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
new file mode 100644
index 0000000..3321e3f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at alias_target.cmake:4 \(target_compile_features\):
+  target_compile_features can not be used on an ALIAS target.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/alias_target.cmake b/Tests/RunCMake/target_compile_features/alias_target.cmake
new file mode 100644
index 0000000..d35ddba
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/alias_target.cmake
@@ -0,0 +1,4 @@
+
+add_executable(main empty.cpp)
+add_executable(Alias::Main ALIAS main)
+target_compile_features(Alias::Main PRIVATE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/imported_target-result.txt b/Tests/RunCMake/target_compile_features/imported_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/imported_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
new file mode 100644
index 0000000..95431b4
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at imported_target.cmake:3 \(target_compile_features\):
+  Cannot specify compile features for imported target "main".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/imported_target.cmake b/Tests/RunCMake/target_compile_features/imported_target.cmake
new file mode 100644
index 0000000..e248c2f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/imported_target.cmake
@@ -0,0 +1,3 @@
+
+add_library(main INTERFACE IMPORTED)
+target_compile_features(main INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args-result.txt b/Tests/RunCMake/target_compile_features/invalid_args-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
new file mode 100644
index 0000000..1242730
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at invalid_args.cmake:3 \(target_compile_features\):
+  target_compile_features called with invalid arguments
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args.cmake b/Tests/RunCMake/target_compile_features/invalid_args.cmake
new file mode 100644
index 0000000..1a7fb37
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args.cmake
@@ -0,0 +1,3 @@
+
+add_executable(main empty.cpp)
+target_compile_features(main INVALID cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
new file mode 100644
index 0000000..d7f48b1
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at invalid_args_on_interface.cmake:3 \(target_compile_features\):
+  target_compile_features may only be set INTERFACE properties on INTERFACE
+  targets
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
new file mode 100644
index 0000000..324d0f3
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
@@ -0,0 +1,3 @@
+
+add_library(main INTERFACE)
+target_compile_features(main PRIVATE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/no_target-result.txt b/Tests/RunCMake/target_compile_features/no_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/no_target-stderr.txt b/Tests/RunCMake/target_compile_features/no_target-stderr.txt
new file mode 100644
index 0000000..9cd5e6b
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_target-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at no_target.cmake:2 \(target_compile_features\):
+  Cannot specify compile features for target "main" which is not built by
+  this project.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/no_target.cmake b/Tests/RunCMake/target_compile_features/no_target.cmake
new file mode 100644
index 0000000..3f0afe2
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_target.cmake
@@ -0,0 +1,2 @@
+
+target_compile_features(main INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args-result.txt b/Tests/RunCMake/target_compile_features/not_enough_args-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_enough_args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
new file mode 100644
index 0000000..0f27a9c
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at not_enough_args.cmake:3 \(target_compile_features\):
+  target_compile_features called with incorrect number of arguments
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args.cmake b/Tests/RunCMake/target_compile_features/not_enough_args.cmake
new file mode 100644
index 0000000..9561230
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_enough_args.cmake
@@ -0,0 +1,3 @@
+
+add_executable(main empty.cpp)
+target_compile_features(main)
diff --git a/Tests/RunCMake/target_compile_features/utility_target-result.txt b/Tests/RunCMake/target_compile_features/utility_target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/utility_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/utility_target-stderr.txt b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
new file mode 100644
index 0000000..96b0bd7
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at utility_target.cmake:4 \(target_compile_features\):
+  target_compile_features called with non-compilable target type
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/utility_target.cmake b/Tests/RunCMake/target_compile_features/utility_target.cmake
new file mode 100644
index 0000000..8919056
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/utility_target.cmake
@@ -0,0 +1,4 @@
+
+add_custom_target(utility)
+
+target_compile_features(utility PRIVATE cxx_delegating_constructors)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f84c532f94118f17512f6d1ed80a28862bfda122
commit f84c532f94118f17512f6d1ed80a28862bfda122
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sat Nov 9 00:18:35 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:21 2013 +0100

    cmTargetPropCommandBase: Change the interface to return bool.
    
    This is needed for the target_compile_features command, which
    may fail at configure time if an invalid feature is specified.

diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index b567252..66d8ad3 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -58,9 +58,10 @@ std::string cmTargetCompileDefinitionsCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetCompileDefinitionsCommand
+bool cmTargetCompileDefinitionsCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                                    bool, bool)
 {
   tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
+  return true;
 }
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index 7405e90..eedcfbf 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -44,7 +44,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
   virtual std::string Join(const std::vector<std::string> &content);
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 254acc7..18499fd 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -51,7 +51,7 @@ std::string cmTargetCompileOptionsCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetCompileOptionsCommand
+bool cmTargetCompileOptionsCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                                    bool, bool)
 {
@@ -59,4 +59,5 @@ void cmTargetCompileOptionsCommand
   this->Makefile->GetBacktrace(lfbt);
   cmValueWithOrigin entry(this->Join(content), lfbt);
   tgt->InsertCompileOption(entry);
+  return true;
 }
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index 3713e5a..4376ba7 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -44,7 +44,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
   virtual std::string Join(const std::vector<std::string> &content);
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index e7b906c..af7fe77 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -64,7 +64,7 @@ std::string cmTargetIncludeDirectoriesCommand
 }
 
 //----------------------------------------------------------------------------
-void cmTargetIncludeDirectoriesCommand
+bool cmTargetIncludeDirectoriesCommand
 ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
                       bool prepend, bool system)
 {
@@ -76,6 +76,7 @@ void cmTargetIncludeDirectoriesCommand
     {
     tgt->AddSystemIncludeDirectories(content);
     }
+  return true;
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index 6863ee5..bb0efcd 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -45,7 +45,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt);
   virtual void HandleMissingTarget(const std::string &name);
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system);
   virtual void HandleInterfaceContent(cmTarget *tgt,
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index e7b6999..2470b28 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -131,29 +131,31 @@ bool cmTargetPropCommandBase
         || args[i] == "PRIVATE"
         || args[i] == "INTERFACE" )
       {
-      this->PopulateTargetProperies(scope, content, prepend, system);
-      return true;
+      return this->PopulateTargetProperies(scope, content, prepend, system);
       }
     content.push_back(args[i]);
     }
-  this->PopulateTargetProperies(scope, content, prepend, system);
-  return true;
+  return this->PopulateTargetProperies(scope, content, prepend, system);
 }
 
 //----------------------------------------------------------------------------
-void cmTargetPropCommandBase
+bool cmTargetPropCommandBase
 ::PopulateTargetProperies(const std::string &scope,
                           const std::vector<std::string> &content,
                           bool prepend, bool system)
 {
   if (scope == "PRIVATE" || scope == "PUBLIC")
     {
-    this->HandleDirectContent(this->Target, content, prepend, system);
+    if (!this->HandleDirectContent(this->Target, content, prepend, system))
+      {
+      return false;
+      }
     }
   if (scope == "INTERFACE" || scope == "PUBLIC")
     {
     this->HandleInterfaceContent(this->Target, content, prepend, system);
     }
+  return true;
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index c402836..67a8596 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -43,7 +43,7 @@ private:
   virtual void HandleImportedTarget(const std::string &tgt) = 0;
   virtual void HandleMissingTarget(const std::string &name) = 0;
 
-  virtual void HandleDirectContent(cmTarget *tgt,
+  virtual bool HandleDirectContent(cmTarget *tgt,
                                    const std::vector<std::string> &content,
                                    bool prepend, bool system) = 0;
 
@@ -51,7 +51,7 @@ private:
 
   bool ProcessContentArgs(std::vector<std::string> const& args,
                           unsigned int &argIndex, bool prepend, bool system);
-  void PopulateTargetProperies(const std::string &scope,
+  bool PopulateTargetProperies(const std::string &scope,
                                const std::vector<std::string> &content,
                                bool prepend, bool system);
 };

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=91cdb7c9032297aa394b52e9ff4e3cc27695ec55
commit 91cdb7c9032297aa394b52e9ff4e3cc27695ec55
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 01:40:47 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:20 2013 +0100

    cmTarget: Transitively evaluate compiler features.
    
    Extend the interface of the target_compile_features command with
    PUBLIC and INTERFACE keywords. Populate the INTERFACE_COMPILER_FEATURES
    target property if they are set. Consume the INTERFACE_COMPILER_FEATURES
    target property from linked dependent targets to determine the final
    required compiler features and the compile flag, if needed.

diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst
index ebd9611..e33ba4e 100644
--- a/Help/command/target_compile_features.rst
+++ b/Help/command/target_compile_features.rst
@@ -5,7 +5,7 @@ Add expected compiler features to a target.
 
 ::
 
-  target_compile_features(<target> PRIVATE <feature> [...])
+  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,
@@ -13,6 +13,12 @@ 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.
 
+The INTERFACE, PUBLIC and PRIVATE keywords are required to specify the
+scope of the features.  PRIVATE and PUBLIC items will
+populate the :prop_tgt:`COMPILE_FEATURES` property of <target>.  PUBLIC and
+INTERFACE items will populate the :prop_tgt:`INTERFACE_COMPILE_FEATURES` property
+of <target>.  Repeated calls for the same <target> append items in the order called.
+
 The named <target> must have been created by a command such as
 add_executable or add_library and must not be an IMPORTED target.
 
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 92f74f3..829c2d3 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -218,3 +218,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingAutoUicOptions() const
   return (strcmp(prop, "AUTOUIC_OPTIONS") == 0
        || strcmp(prop, "INTERFACE_AUTOUIC_OPTIONS") == 0 );
 }
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompileFeatures() const
+{
+  const char *prop = this->Property.c_str();
+  return (strcmp(prop, "COMPILE_FEATURES") == 0
+       || strcmp(prop, "INTERFACE_COMPILE_FEATURES") == 0);
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index fd47ad7..45640b4 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -21,14 +21,16 @@
   F(EvaluatingSystemIncludeDirectories) \
   F(EvaluatingCompileDefinitions) \
   F(EvaluatingCompileOptions) \
-  F(EvaluatingAutoUicOptions)
+  F(EvaluatingAutoUicOptions) \
+  F(EvaluatingCompileFeatures)
 
 #define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \
   F(INCLUDE_DIRECTORIES) \
   F(SYSTEM_INCLUDE_DIRECTORIES) \
   F(COMPILE_DEFINITIONS) \
   F(COMPILE_OPTIONS) \
-  F(AUTOUIC_OPTIONS)
+  F(AUTOUIC_OPTIONS) \
+  F(COMPILE_FEATURES)
 
 //----------------------------------------------------------------------------
 struct cmGeneratorExpressionDAGChecker
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index d4f451e..3331b33 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1440,6 +1440,13 @@ void cmLocalGenerator::AddCompileOptions(
       this->AppendFlagEscape(flags, i->c_str());
       }
     }
+  std::vector<std::string> features;
+  target->GetCompileFeatures(features, config);
+  for(std::vector<std::string>::const_iterator it = features.begin();
+      it != features.end(); ++it)
+    {
+    this->Makefile->AddRequiredTargetFeature(target, it->c_str());
+    }
   this->AddCompilerRequirementFlag(flags, target, lang);
 }
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 2158e33..7423df4 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -148,11 +148,14 @@ public:
                                 CachedLinkInterfaceAutoUicOptionsEntries;
   mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
                                 CachedLinkInterfaceCompileDefinitionsEntries;
+  mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
+                                CachedLinkInterfaceCompileFeaturesEntries;
 
   mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
   mutable std::map<std::string, bool> CacheLinkInterfaceAutoUicOptionsDone;
+  mutable std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone;
 };
 
 //----------------------------------------------------------------------------
@@ -188,6 +191,7 @@ cmTargetInternals::~cmTargetInternals()
   deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
   deleteAndClear(this->CachedLinkInterfaceAutoUicOptionsEntries);
+  deleteAndClear(this->CachedLinkInterfaceCompileFeaturesEntries);
   deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
 }
 
@@ -210,6 +214,7 @@ cmTarget::cmTarget()
   this->BuildInterfaceIncludesAppended = false;
   this->DebugIncludesDone = false;
   this->DebugCompileOptionsDone = false;
+  this->DebugCompileFeaturesDone = false;
   this->DebugCompileDefinitionsDone = false;
 }
 
@@ -2420,6 +2425,121 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
 }
 
 //----------------------------------------------------------------------------
+static void processCompileFeatures(cmTarget const* tgt,
+      const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+      std::vector<std::string> &options,
+      std::set<std::string> &uniqueOptions,
+      cmGeneratorExpressionDAGChecker *dagChecker,
+      const char *config, bool debugOptions)
+{
+  processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+                                dagChecker, config, debugOptions, "features");
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetCompileFeatures(std::vector<std::string> &result,
+                                 const char *config) const
+{
+  std::set<std::string> uniqueFeatures;
+  cmListFileBacktrace lfbt;
+
+  cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+                                             this->GetName(),
+                                             "COMPILE_FEATURES",
+                                             0, 0);
+
+  std::vector<std::string> debugProperties;
+  const char *debugProp =
+              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+  if (debugProp)
+    {
+    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+    }
+
+  bool debugFeatures = !this->DebugCompileFeaturesDone
+                    && std::find(debugProperties.begin(),
+                                 debugProperties.end(),
+                                 "COMPILE_FEATURES")
+                        != debugProperties.end();
+
+  if (this->Makefile->IsGeneratingBuildSystem())
+    {
+    this->DebugCompileFeaturesDone = true;
+    }
+
+  processCompileFeatures(this,
+                            this->Internal->CompileFeaturesEntries,
+                            result,
+                            uniqueFeatures,
+                            &dagChecker,
+                            config,
+                            debugFeatures);
+
+  std::string configString = config ? config : "";
+  if (!this->Internal->CacheLinkInterfaceCompileFeaturesDone[configString])
+    {
+
+    for (std::vector<cmValueWithOrigin>::const_iterator
+        it = this->Internal->LinkInterfacePropertyEntries.begin(),
+        end = this->Internal->LinkInterfacePropertyEntries.end();
+        it != end; ++it)
+      {
+      if (!cmGeneratorExpression::IsValidTargetName(it->Value)
+          && cmGeneratorExpression::Find(it->Value) == std::string::npos)
+        {
+        continue;
+        }
+      {
+      cmGeneratorExpression ge(lfbt);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+                                                        ge.Parse(it->Value);
+      std::string targetResult = cge->Evaluate(this->Makefile, config,
+                                        false, this, 0, 0);
+      if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
+        {
+        continue;
+        }
+      }
+      std::string featureGenex = "$<TARGET_PROPERTY:" +
+                              it->Value + ",INTERFACE_COMPILE_FEATURES>";
+      if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+        {
+        // Because it->Value is a generator expression, ensure that it
+        // evaluates to the non-empty string before being used in the
+        // TARGET_PROPERTY expression.
+        featureGenex = "$<$<BOOL:" + it->Value + ">:" + featureGenex + ">";
+        }
+      cmGeneratorExpression ge(it->Backtrace);
+      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+                                                                featureGenex);
+
+      this->Internal
+        ->CachedLinkInterfaceCompileFeaturesEntries[configString].push_back(
+                        new cmTargetInternals::TargetPropertyEntry(cge,
+                                                              it->Value));
+      }
+    }
+
+  processCompileFeatures(this,
+    this->Internal->CachedLinkInterfaceCompileFeaturesEntries[configString],
+                            result,
+                            uniqueFeatures,
+                            &dagChecker,
+                            config,
+                            debugFeatures);
+
+  if (!this->Makefile->IsGeneratingBuildSystem())
+    {
+    deleteAndClear(this->Internal->CachedLinkInterfaceCompileFeaturesEntries);
+    }
+  else
+    {
+    this->Internal->CacheLinkInterfaceCompileFeaturesDone[configString]
+                                                                      = true;
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
 {
   // Wipe out maps caching information affected by this property.
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index c70409c..c300012 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -534,6 +534,8 @@ public:
                          const char *config) const;
   void GetAutoUicOptions(std::vector<std::string> &result,
                          const char *config) const;
+  void GetCompileFeatures(std::vector<std::string> &result,
+                           const char *config) const;
 
   bool IsNullImpliedByLinkLibraries(const std::string &p) const;
   bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
@@ -693,6 +695,7 @@ private:
   mutable bool DebugCompileOptionsDone;
   mutable bool DebugAutoUicOptionsDone;
   mutable bool DebugCompileDefinitionsDone;
+  mutable bool DebugCompileFeaturesDone;
   mutable std::set<std::string> LinkImplicitNullProperties;
   bool BuildInterfaceIncludesAppended;
 
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index f89e075..8b48ce3 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -34,7 +34,8 @@ bool cmTargetCompileFeaturesCommand::InitialPass(
     return false;
     }
 
-  if(args[1] != "PRIVATE")
+  const bool interfaceOnly = args[1] == "INTERFACE";
+  if(args[1] != "PRIVATE" && args[1] != "PUBLIC" && !interfaceOnly)
     {
     this->SetError("called with invalid arguments.");
     return false;
@@ -44,12 +45,19 @@ bool cmTargetCompileFeaturesCommand::InitialPass(
     {
     std::string feature = args[i];
 
-    if (!this->Makefile->AddRequiredTargetFeature(target, feature.c_str()))
+    if (!interfaceOnly)
       {
-      cmOStringStream e;
-      e << "specified unknown feature \"" << feature << "\".";
-      this->SetError(e.str().c_str());
-      return false;
+      if (!this->Makefile->AddRequiredTargetFeature(target, feature.c_str()))
+        {
+        cmOStringStream e;
+        e << "specified unknown feature \"" << feature << "\".";
+        this->SetError(e.str().c_str());
+        return false;
+        }
+      }
+    if (interfaceOnly || args[1] == "PUBLIC")
+      {
+      target->AppendProperty("INTERFACE_COMPILE_FEATURES", feature.c_str());
       }
     }
   return true;
diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
index 947996e..3a42088 100644
--- a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
@@ -23,3 +23,11 @@ add_executable(target_compile_features main.cpp)
 target_compile_features(target_compile_features
   PRIVATE cxx_delegating_constructors
 )
+
+add_library(lib_delegating_constructors lib_delegating_constructors.cpp)
+target_compile_features(lib_delegating_constructors
+  PUBLIC cxx_delegating_constructors
+)
+
+add_executable(lib_user lib_user.cpp)
+target_link_libraries(lib_user lib_delegating_constructors)
diff --git a/Tests/CMakeCommands/target_compile_features/lib_delegating_constructors.cpp b/Tests/CMakeCommands/target_compile_features/lib_delegating_constructors.cpp
new file mode 100644
index 0000000..e597acd
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/lib_delegating_constructors.cpp
@@ -0,0 +1,8 @@
+
+#include "lib_delegating_constructors.h"
+
+Foo::Foo(int i)
+  : m_i(i)
+{
+
+}
diff --git a/Tests/CMakeCommands/target_compile_features/lib_delegating_constructors.h b/Tests/CMakeCommands/target_compile_features/lib_delegating_constructors.h
new file mode 100644
index 0000000..75be701
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/lib_delegating_constructors.h
@@ -0,0 +1,17 @@
+
+#include <cstring>
+
+class Foo
+{
+public:
+  Foo(int i);
+
+  Foo(const char *a)
+    : Foo(strlen(a))
+  {
+
+  }
+
+private:
+  int m_i;
+};
diff --git a/Tests/CMakeCommands/target_compile_features/lib_user.cpp b/Tests/CMakeCommands/target_compile_features/lib_user.cpp
new file mode 100644
index 0000000..83ad51e
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/lib_user.cpp
@@ -0,0 +1,27 @@
+
+#include "lib_delegating_constructors.h"
+
+class Bar
+{
+  Bar(int i)
+    :m_i(i)
+  {
+
+  }
+
+  Bar(const char *a)
+    : Bar(strlen(a))
+  {
+
+  }
+
+private:
+  int m_i;
+};
+
+int main(int argc, char **argv)
+{
+  Foo f("hello");
+  Foo b("world");
+  return 0;
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d438d5bb784a3651d7f2f4ddbbdec6a0c262e844
commit d438d5bb784a3651d7f2f4ddbbdec6a0c262e844
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 15:05:49 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:20 2013 +0100

    cmTarget: Allow populating COMPILE_FEATURES using generator expressions.

diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst
index aa438b2..ebd9611 100644
--- a/Help/command/target_compile_features.rst
+++ b/Help/command/target_compile_features.rst
@@ -15,3 +15,8 @@ automatically.
 
 The named <target> must have been created by a command such as
 add_executable or add_library and must not be an IMPORTED target.
+
+Arguments to target_compile_features may use "generator expressions"
+with the syntax "$<...>".
+See the :manual:`cmake-generator-expressions(7)` manual for available
+expressions.
diff --git a/Help/prop_tgt/COMPILE_FEATURES.rst b/Help/prop_tgt/COMPILE_FEATURES.rst
index b2c6145..3ef743c 100644
--- a/Help/prop_tgt/COMPILE_FEATURES.rst
+++ b/Help/prop_tgt/COMPILE_FEATURES.rst
@@ -5,3 +5,7 @@ Compiler features enabled for this target.
 
 The list of features in this property are a subset of the features listed
 in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
+
+Contents of COMPILE_FEATURES may use "generator expressions" with the
+syntax "$<...>".  See the :manual:`cmake-generator-expressions(7)` manual for
+available expressions.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 17ea2ad..05fca7b 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4491,6 +4491,11 @@ static const char * const CXX_STANDARDS[] = {
 bool cmMakefile::
 AddRequiredTargetFeature(cmTarget *target, const char *feature) const
 {
+  if (cmGeneratorExpression::Find(feature) != std::string::npos)
+    {
+    target->AppendProperty("COMPILE_FEATURES", feature);
+    return true;
+    }
   bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1,
               cmArrayEnd(CXX_FEATURES), cmStrCmp(feature))
               != cmArrayEnd(CXX_FEATURES);

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=11e3ed692889017cb6ae9bf83723b944abe219b5
commit 11e3ed692889017cb6ae9bf83723b944abe219b5
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 14:58:21 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:20 2013 +0100

    cmTarget: Make COMPILE_FEATURES available as a target property.

diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 9f690d2..52d8c20 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -99,6 +99,7 @@ Properties on Targets
    /prop_tgt/COMPILE_DEFINITIONS
    /prop_tgt/COMPILE_FLAGS
    /prop_tgt/COMPILE_OPTIONS
+   /prop_tgt/COMPILE_FEATURES
    /prop_tgt/CONFIG_OUTPUT_NAME
    /prop_tgt/CONFIG_POSTFIX
    /prop_tgt/CXX_STANDARD
diff --git a/Help/prop_tgt/COMPILE_FEATURES.rst b/Help/prop_tgt/COMPILE_FEATURES.rst
new file mode 100644
index 0000000..b2c6145
--- /dev/null
+++ b/Help/prop_tgt/COMPILE_FEATURES.rst
@@ -0,0 +1,7 @@
+COMPILE_FEATURES
+----------------
+
+Compiler features enabled for this target.
+
+The list of features in this property are a subset of the features listed
+in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 40ccf06..17ea2ad 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4523,6 +4523,8 @@ AddRequiredTargetFeature(cmTarget *target, const char *feature) const
     return false;
     }
 
+  target->AppendProperty("COMPILE_FEATURES", feature);
+
   bool needCxx98 = true;
   bool needCxx11 = false;
   bool needCxxExt = false;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index b4ae7f7..2158e33 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -136,6 +136,7 @@ public:
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
   std::vector<TargetPropertyEntry*> CompileOptionsEntries;
   std::vector<TargetPropertyEntry*> AutoUicOptionsEntries;
+  std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
   std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
   std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
 
@@ -1490,6 +1491,17 @@ void cmTarget::SetProperty(const char* prop, const char* value)
                           new cmTargetInternals::TargetPropertyEntry(cge));
     return;
     }
+  if(strcmp(prop,"COMPILE_FEATURES") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    this->Makefile->GetBacktrace(lfbt);
+    cmGeneratorExpression ge(lfbt);
+    deleteAndClear(this->Internal->CompileFeaturesEntries);
+    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+    this->Internal->CompileFeaturesEntries.push_back(
+                          new cmTargetInternals::TargetPropertyEntry(cge));
+    return;
+    }
   if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
     {
     cmListFileBacktrace lfbt;
@@ -1573,6 +1585,15 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
               new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
     return;
     }
+  if(strcmp(prop,"COMPILE_FEATURES") == 0)
+    {
+    cmListFileBacktrace lfbt;
+    this->Makefile->GetBacktrace(lfbt);
+    cmGeneratorExpression ge(lfbt);
+    this->Internal->CompileFeaturesEntries.push_back(
+              new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+    return;
+    }
   if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
     {
     cmListFileBacktrace lfbt;
@@ -2893,6 +2914,24 @@ const char *cmTarget::GetProperty(const char* prop,
       }
     return output.c_str();
     }
+  if(strcmp(prop,"COMPILE_FEATURES") == 0)
+    {
+    static std::string output;
+    output = "";
+    std::string sep;
+    typedef cmTargetInternals::TargetPropertyEntry
+                                TargetPropertyEntry;
+    for (std::vector<TargetPropertyEntry*>::const_iterator
+        it = this->Internal->CompileFeaturesEntries.begin(),
+        end = this->Internal->CompileFeaturesEntries.end();
+        it != end; ++it)
+      {
+      output += sep;
+      output += (*it)->ge->GetInput();
+      sep = ";";
+      }
+    return output.c_str();
+    }
   if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
     {
     static std::string output;
@@ -6103,6 +6142,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
   deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
   deleteAndClear(this->Pointer->CompileOptionsEntries);
   deleteAndClear(this->Pointer->AutoUicOptionsEntries);
+  deleteAndClear(this->Pointer->CompileFeaturesEntries);
   deleteAndClear(this->Pointer->CompileDefinitionsEntries);
   delete this->Pointer;
 }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9a629418b831d0a8cf08f164f22e9c72cf020075
commit 9a629418b831d0a8cf08f164f22e9c72cf020075
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 13 14:25:08 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:20 2013 +0100

    Add target_compile_features command.
    
    This can be used to set the compiler features required by particular
    targets. An error is issued at CMake time if the compiler does not
    support the required feature. If a language dialect flag is required
    by the features used, that will be added automatically.

diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst
new file mode 100644
index 0000000..aa438b2
--- /dev/null
+++ b/Help/command/target_compile_features.rst
@@ -0,0 +1,17 @@
+target_compile_features
+-----------------------
+
+Add expected compiler features to a target.
+
+::
+
+  target_compile_features(<target> PRIVATE <feature> [...])
+
+Specify compiler features required when compiling a given target.  If the
+feature is not listed in the :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.
+
+The named <target> must have been created by a command such as
+add_executable or add_library and must not be an IMPORTED target.
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index fb0d2b5..1294873 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -91,6 +91,7 @@ These commands may be used freely in CMake projects.
    /command/source_group
    /command/string
    /command/target_compile_definitions
+   /command/target_compile_features
    /command/target_compile_options
    /command/target_include_directories
    /command/target_link_libraries
diff --git a/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst b/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst
index 6be0124..386f5c0 100644
--- a/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst
+++ b/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst
@@ -6,3 +6,6 @@ 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 :variable:`CMAKE_CXX_KNOWN_FEATURES`
 variable.
+
+The features listed here may be used with the :command:`target_compile_features`
+command.
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 1e2a85c..8f89fd9 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -32,6 +32,7 @@
 #include "cmSubdirDependsCommand.cxx"
 #include "cmTargetCompileDefinitionsCommand.cxx"
 #include "cmTargetCompileOptionsCommand.cxx"
+#include "cmTargetCompileFeaturesCommand.cxx"
 #include "cmTargetIncludeDirectoriesCommand.cxx"
 #include "cmTargetPropCommandBase.cxx"
 #include "cmUseMangledMesaCommand.cxx"
@@ -77,6 +78,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
   commands.push_back(new cmTargetIncludeDirectoriesCommand);
   commands.push_back(new cmTargetCompileDefinitionsCommand);
   commands.push_back(new cmTargetCompileOptionsCommand);
+  commands.push_back(new cmTargetCompileFeaturesCommand);
   commands.push_back(new cmUseMangledMesaCommand);
   commands.push_back(new cmUtilitySourceCommand);
   commands.push_back(new cmVariableRequiresCommand);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 1c55acc..40ccf06 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4475,3 +4475,141 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
     pm[pid] = this->GetPolicyStatus(pid);
     }
 }
+
+#define FEATURE_STRING(F) , #F
+
+static const char * const CXX_FEATURES[] = {
+  0
+  FOR_EACH_CXX_FEATURE(FEATURE_STRING)
+};
+
+static const char * const CXX_STANDARDS[] = {
+    "98"
+  , "11"
+};
+
+bool cmMakefile::
+AddRequiredTargetFeature(cmTarget *target, const char *feature) const
+{
+  bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1,
+              cmArrayEnd(CXX_FEATURES), cmStrCmp(feature))
+              != cmArrayEnd(CXX_FEATURES);
+  if (!isCxxFeature)
+    {
+    return false;
+    }
+
+  const char* cxxFeaturesKnown =
+    this->GetDefinition("CMAKE_CXX_COMPILE_FEATURES");
+
+  if (!cxxFeaturesKnown)
+    {
+    // We know of no features for the compiler at all.
+    return true;
+    }
+
+  std::vector<std::string> availableFeatures;
+  cmSystemTools::ExpandListArgument(cxxFeaturesKnown, availableFeatures);
+  if (std::find(availableFeatures.begin(),
+                availableFeatures.end(),
+                feature) == availableFeatures.end())
+    {
+    cmOStringStream e;
+    e << "The compiler feature \"" << feature
+      << "\" is not known to compiler\n\""
+      << this->GetDefinition("CMAKE_CXX_COMPILER_ID") << "\"\nversion "
+      << this->GetDefinition("CMAKE_CXX_COMPILER_VERSION") << ".";
+    this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+    return false;
+    }
+
+  bool needCxx98 = true;
+  bool needCxx11 = false;
+  bool needCxxExt = false;
+
+  if (const char *propCxx98 =
+                        this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propCxx98, props);
+    needCxx98 = std::find(props.begin(), props.end(), feature) != props.end();
+    }
+  if (const char *propCxx11 =
+          this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propCxx11, props);
+    needCxx11 = std::find(props.begin(), props.end(), feature) != props.end();
+    }
+
+  if (const char *propCxx98ext =
+          this->GetDefinition("CMAKE_CXX98_COMPILE_EXTENSIONS"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propCxx98ext, props);
+    needCxxExt = std::find(props.begin(), props.end(), feature) != props.end();
+    needCxx98 = needCxx98 || needCxxExt;
+    }
+  if (const char *propCxx11ext =
+          this->GetDefinition("CMAKE_CXX11_COMPILE_EXTENSIONS"))
+    {
+    std::vector<std::string> props;
+    cmSystemTools::ExpandListArgument(propCxx11ext, props);
+    bool needCxx11Ext = std::find(props.begin(), props.end(), feature)
+                      != props.end();
+    needCxx11 = needCxx11 || needCxx11Ext;
+    needCxxExt = needCxxExt || needCxx11Ext;
+    }
+
+  const char *existingCxxStandard = target->GetProperty("CXX_STANDARD");
+  if (existingCxxStandard)
+    {
+    if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
+                  cmStrCmp(existingCxxStandard)) == cmArrayEnd(CXX_STANDARDS))
+      {
+      cmOStringStream e;
+      e << "The CXX_STANDARD property on target \"" << target->GetName()
+        << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
+      this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+      return false;
+      }
+    }
+  const char * const *existingCxxIt = existingCxxStandard
+                                    ? std::find_if(cmArrayBegin(CXX_STANDARDS),
+                                      cmArrayEnd(CXX_STANDARDS),
+                                      cmStrCmp(existingCxxStandard))
+                                    : cmArrayEnd(CXX_STANDARDS);
+
+  bool setCxx11 = needCxx11 && !existingCxxStandard;
+  bool setCxx98 = needCxx98 && !existingCxxStandard;
+
+  if (needCxx11 && existingCxxStandard && existingCxxIt <
+                                    std::find_if(cmArrayBegin(CXX_STANDARDS),
+                                      cmArrayEnd(CXX_STANDARDS),
+                                      cmStrCmp("11")))
+    {
+    setCxx11 = true;
+    }
+  else if(needCxx98 && existingCxxStandard && existingCxxIt <
+                                    std::find_if(cmArrayBegin(CXX_STANDARDS),
+                                      cmArrayEnd(CXX_STANDARDS),
+                                      cmStrCmp("98")))
+    {
+    setCxx98 = true;
+    }
+
+  if (setCxx11)
+    {
+    target->SetProperty("CXX_STANDARD", "11");
+    }
+  else if (setCxx98)
+    {
+    target->SetProperty("CXX_STANDARD", "98");
+    }
+  bool existingCxxExt = target->GetPropertyAsBool("CXX_EXTENSIONS");
+  if (needCxxExt && !existingCxxExt)
+    {
+    target->SetProperty("CXX_EXTENSIONS", "1");
+    }
+  return true;
+}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 44aaa66..0990b4a 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -883,6 +883,8 @@ public:
   std::set<cmStdString> const & GetSystemIncludeDirectories() const
     { return this->SystemIncludeDirectories; }
 
+  bool AddRequiredTargetFeature(cmTarget *target, const char *feature) const;
+
 protected:
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(const char* name, cmTarget& target);
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
new file mode 100644
index 0000000..f89e075
--- /dev/null
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -0,0 +1,56 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <steveire at gmail.com>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmTargetCompileFeaturesCommand.h"
+
+bool cmTargetCompileFeaturesCommand::InitialPass(
+  std::vector<std::string> const& args,
+  cmExecutionStatus &)
+{
+  if (args.size() < 3)
+    {
+      this->SetError("called with wrong number of arguments.");
+      return false;
+    }
+  cmTarget *target = this->Makefile->FindTargetToUse(args[0].c_str());
+
+  if(!target)
+    {
+    this->SetError("specified invalid target.");
+    return false;
+    }
+
+  if(target->IsImported())
+    {
+    this->SetError("may not be used with an IMPORTED target.");
+    return false;
+    }
+
+  if(args[1] != "PRIVATE")
+    {
+    this->SetError("called with invalid arguments.");
+    return false;
+    }
+
+  for (size_t i = 2; i < args.size(); ++i)
+    {
+    std::string feature = args[i];
+
+    if (!this->Makefile->AddRequiredTargetFeature(target, feature.c_str()))
+      {
+      cmOStringStream e;
+      e << "specified unknown feature \"" << feature << "\".";
+      this->SetError(e.str().c_str());
+      return false;
+      }
+    }
+  return true;
+}
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
new file mode 100644
index 0000000..63beeca
--- /dev/null
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -0,0 +1,32 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Stephen Kelly <steveire at gmail.com>
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmTargetCompileFeaturesCommand_h
+#define cmTargetCompileFeaturesCommand_h
+
+#include "cmCommand.h"
+
+class cmTargetCompileFeaturesCommand : public cmCommand
+{
+  virtual cmCommand* Clone()
+    {
+    return new cmTargetCompileFeaturesCommand;
+    }
+
+  virtual bool InitialPass(std::vector<std::string> const& args,
+                           cmExecutionStatus &status);
+
+  virtual const char* GetName() const { return "target_compile_features";}
+
+  cmTypeMacro(cmTargetCompileFeaturesCommand, cmCommand);
+};
+
+#endif
diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
new file mode 100644
index 0000000..947996e
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 2.8.12)
+cmake_policy(SET CMP0025 NEW)
+project(target_compile_features)
+
+set(CMAKE_VERBOSE_MAKEFILE ON)
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL GNU
+    OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+  add_executable(gnuxx_typeof_test gnuxx_typeof_test.cpp)
+  target_compile_features(gnuxx_typeof_test PRIVATE gnuxx_typeof)
+endif()
+if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
+  add_executable(msvcxx_sealed_test msvcxx_sealed_test.cpp)
+  target_compile_features(msvcxx_sealed_test PRIVATE msvcxx_sealed)
+endif()
+
+if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
+  add_executable(target_compile_features dummy.cpp)
+  return()
+endif()
+
+add_executable(target_compile_features main.cpp)
+target_compile_features(target_compile_features
+  PRIVATE cxx_delegating_constructors
+)
diff --git a/Tests/CMakeCommands/target_compile_features/dummy.cpp b/Tests/CMakeCommands/target_compile_features/dummy.cpp
new file mode 100644
index 0000000..341aaaf
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/dummy.cpp
@@ -0,0 +1,5 @@
+
+int main(int, char **)
+{
+  return 0;
+}
diff --git a/Tests/CMakeCommands/target_compile_features/gnuxx_typeof_test.cpp b/Tests/CMakeCommands/target_compile_features/gnuxx_typeof_test.cpp
new file mode 100644
index 0000000..3b8532e
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/gnuxx_typeof_test.cpp
@@ -0,0 +1,6 @@
+
+int main(int argc, char **argv)
+{
+  typeof(argc) ret = 0;
+  return ret;
+}
diff --git a/Tests/CMakeCommands/target_compile_features/main.cpp b/Tests/CMakeCommands/target_compile_features/main.cpp
new file mode 100644
index 0000000..77671b0
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/main.cpp
@@ -0,0 +1,25 @@
+
+#include <cstring>
+
+class Foo
+{
+  Foo(int i)
+    :m_i(i)
+  {
+
+  }
+
+  Foo(const char *a)
+    : Foo(strlen(a))
+  {
+
+  }
+
+private:
+  int m_i;
+};
+
+int main(int, char **)
+{
+  return 0;
+}
diff --git a/Tests/CMakeCommands/target_compile_features/msvcxx_sealed_test.cpp b/Tests/CMakeCommands/target_compile_features/msvcxx_sealed_test.cpp
new file mode 100644
index 0000000..0127937
--- /dev/null
+++ b/Tests/CMakeCommands/target_compile_features/msvcxx_sealed_test.cpp
@@ -0,0 +1,8 @@
+
+class A sealed {};
+
+int main(int argc, char **argv)
+{
+  A a;
+  return 0;
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index b2ba6e8..cb89e36 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2203,6 +2203,12 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
   ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
   ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions)
   ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options)
+
+  if ((CMAKE_CXX_COMPILER_ID STREQUAL GNU AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
+      OR CMAKE_CXX_COMPILER_ID STREQUAL Clang
+      OR (x${CMAKE_CXX_COMPILER_ID} STREQUAL xMSVC AND NOT MSVC_VERSION VERSION_LESS 1400))
+    ADD_TEST_MACRO(CMakeCommands.target_compile_features target_compile_features)
+  endif()
   ADD_TEST_MACRO(compile_features compile_features)
 
   configure_file(
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 209b0b3..a22ab40 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -134,4 +134,5 @@ endif()
 add_RunCMake_test(File_Generate)
 add_RunCMake_test(ExportWithoutLanguage)
 add_RunCMake_test(target_link_libraries)
+add_RunCMake_test(target_compile_features)
 add_RunCMake_test(CheckModules)
diff --git a/Tests/RunCMake/target_compile_features/CMakeLists.txt b/Tests/RunCMake/target_compile_features/CMakeLists.txt
new file mode 100644
index 0000000..aa7278d
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12)
+cmake_policy(SET CMP0025 NEW)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
new file mode 100644
index 0000000..28341c9
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
@@ -0,0 +1,4 @@
+include(RunCMake)
+
+run_cmake(not_a_cxx_feature)
+run_cmake(no_matching_cxx_feature)
diff --git a/Tests/RunCMake/target_compile_features/empty.cpp b/Tests/RunCMake/target_compile_features/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
new file mode 100644
index 0000000..a8f60c7
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at no_matching_cxx_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\):
+  The compiler feature "[^"]+" is not known to compiler
+
+  "[^"]*"
+
+  version *[.0-9]+\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
new file mode 100644
index 0000000..99d04b6
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
@@ -0,0 +1,26 @@
+
+if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";gnuxx_typeof;"
+    AND NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";msvcxx_sealed;" )
+  # Simulate passing the test.
+  message(SEND_ERROR
+    "The compiler feature \"gnuxx_dummy\" is not known to compiler\n\"GNU\"\nversion 4.8.1."
+  )
+  return()
+endif()
+
+if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";gnuxx_typeof;")
+  set(feature msvcxx_sealed)
+  if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";msvcxx_sealed;")
+    # If a compiler supports both extensions, remove one of them.
+    list(REMOVE_ITEM CMAKE_CXX_COMPILE_FEATURES msvcxx_sealed)
+  endif()
+else()
+  set(feature gnuxx_typeof)
+endif()
+
+add_executable(main empty.cpp)
+
+target_compile_features(main
+  PRIVATE
+    ${feature}
+)
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
new file mode 100644
index 0000000..1b82258
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at not_a_cxx_feature.cmake:3 \(target_compile_features\):
+  target_compile_features specified unknown feature "cxx_not_a_feature".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
new file mode 100644
index 0000000..0207b72
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
@@ -0,0 +1,6 @@
+
+add_executable(main empty.cpp)
+target_compile_features(main
+  PRIVATE
+    cxx_not_a_feature
+)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a7b356ba6abf4c740fd7af2d2da0165ae36edcac
commit a7b356ba6abf4c740fd7af2d2da0165ae36edcac
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sat Nov 9 09:18:53 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:20 2013 +0100

    Record compilers capable of msvcxx_sealed feature.
    
    Clang-cl is capable of this feature, but that is not yet released,
    nor have I tested it.

diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
index 366e9cc..3aa5017 100644
--- a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -16,3 +16,6 @@ cxx_delegating_constructors
 
 gnuxx_typeof
   The GNU typeof extension.
+
+msvcxx_sealed
+  The MSVC sealed extension.
diff --git a/Modules/Compiler/MSVC-CXX-FeatureTests.cmake b/Modules/Compiler/MSVC-CXX-FeatureTests.cmake
new file mode 100644
index 0000000..7a56acd
--- /dev/null
+++ b/Modules/Compiler/MSVC-CXX-FeatureTests.cmake
@@ -0,0 +1,2 @@
+
+set(_cmake_feature_test_msvcxx_sealed "_MSC_VER >= 1400")
diff --git a/Modules/Platform/Windows-MSVC-CXX.cmake b/Modules/Platform/Windows-MSVC-CXX.cmake
index 0e85005..89885b8 100644
--- a/Modules/Platform/Windows-MSVC-CXX.cmake
+++ b/Modules/Platform/Windows-MSVC-CXX.cmake
@@ -4,3 +4,7 @@ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
   set(_FS_CXX " /FS")
 endif()
 __windows_compiler_msvc(CXX)
+
+macro(cmake_record_cxx_compile_features)
+  record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES)
+endmacro()
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 2665c09..1c55acc 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -43,7 +43,8 @@
 
 #define FOR_EACH_CXX_FEATURE(F) \
   F(cxx_delegating_constructors) \
-  F(gnuxx_typeof)
+  F(gnuxx_typeof) \
+  F(msvcxx_sealed)
 
 class cmMakefile::Internals
 {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=90ab0f03626960bda1ca2b56e2d4ad2d69083283
commit 90ab0f03626960bda1ca2b56e2d4ad2d69083283
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sat Nov 9 09:18:32 2013 +0100
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:20 2013 +0100

    Record compilers capable of the gnuxx_typeof feature.

diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
index effaf6f..366e9cc 100644
--- a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -13,3 +13,6 @@ cxx_delegating_constructors
   Delegating constructors, as defined in N1986_.
 
 .. _N1986: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
+
+gnuxx_typeof
+  The GNU typeof extension.
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index f64cb66..28bd1cf 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -3,7 +3,9 @@ set(CMAKE_CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@")
 set(CMAKE_CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@")
 set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@")
 set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@")
+set(CMAKE_CXX98_COMPILE_EXTENSIONS "@CMAKE_CXX98_COMPILE_EXTENSIONS@")
 set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
+set(CMAKE_CXX11_COMPILE_EXTENSIONS "@CMAKE_CXX11_COMPILE_EXTENSIONS@")
 
 set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@")
 set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@")
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
index 40aa9d6..7950144 100644
--- a/Modules/CMakeDetermineCompileFeatures.cmake
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -17,7 +17,9 @@ function(cmake_determine_compile_features lang)
   if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
     message(STATUS "Detecting ${lang} compile features")
 
+    set(CMAKE_CXX98_COMPILE_EXTENSIONS)
     set(CMAKE_CXX11_COMPILE_FEATURES)
+    set(CMAKE_CXX11_COMPILE_EXTENSIONS)
 
     include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
 
@@ -28,14 +30,21 @@ function(cmake_determine_compile_features lang)
       return()
     endif()
 
+    string(REPLACE "${CMAKE_CXX98_COMPILE_EXTENSIONS}" "" CMAKE_CXX11_COMPILE_EXTENSIONS "${CMAKE_CXX11_COMPILE_EXTENSIONS}")
+    string(REPLACE "${CMAKE_CXX11_COMPILE_FEATURES}" "" CMAKE_CXX11_COMPILE_EXTENSIONS "${CMAKE_CXX11_COMPILE_EXTENSIONS}")
+
     if(NOT CMAKE_CXX_COMPILE_FEATURES)
       set(CMAKE_CXX_COMPILE_FEATURES
+        ${CMAKE_CXX98_COMPILE_EXTENSIONS}
         ${CMAKE_CXX11_COMPILE_FEATURES}
+        ${CMAKE_CXX11_COMPILE_EXTENSIONS}
       )
     endif()
 
     set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CXX98_COMPILE_EXTENSIONS ${CMAKE_CXX98_COMPILE_EXTENSIONS} PARENT_SCOPE)
     set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CXX11_COMPILE_EXTENSIONS ${CMAKE_CXX11_COMPILE_EXTENSIONS} PARENT_SCOPE)
 
     message(STATUS "Detecting ${lang} compile features - done")
   endif()
diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
index 940a182..3580afc 100644
--- a/Modules/Compiler/Clang-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
@@ -1,4 +1,9 @@
 
+if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
+  # This file is only loaded if Clang >= 2.1
+  message(FATAL_ERROR "This file should not be included for Clang < 2.1.")
+endif()
+
 set(testable_features
   cxx_delegating_constructors
 )
@@ -7,3 +12,5 @@ foreach(feature ${testable_features})
 endforeach()
 
 unset(testable_features)
+
+set(_cmake_feature_test_gnuxx_typeof "!defined(__STRICT_ANSI__)")
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index 4a72a99..1a6b485 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -28,9 +28,15 @@ macro(cmake_record_cxx_compile_features)
     record_compiler_features(CXX "-std=${std_version}" ${list})
   endmacro()
 
+  if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
+    _get_clang_features(gnu++98 CMAKE_CXX98_COMPILE_EXTENSIONS)
+  endif()
+
   if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1)
+    _get_clang_features(gnu++11 CMAKE_CXX11_COMPILE_EXTENSIONS)
     _get_clang_features(c++11 CMAKE_CXX11_COMPILE_FEATURES)
   elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
+    _get_clang_features(gnu++0x CMAKE_CXX11_COMPILE_EXTENSIONS)
     _get_clang_features(c++0x CMAKE_CXX11_COMPILE_FEATURES)
   endif()
 endmacro()
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
index 7da0563..13c6128 100644
--- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -1,2 +1,17 @@
 
-set(_cmake_feature_test_cxx_delegating_constructors "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407")
+set(_cmake_feature_test_gnuxx_typeof "!defined(__STRICT_ANSI__)")
+
+if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
+  # This file is only loaded if GCC >= 4.3
+  message(FATAL_ERROR "This file should not be included for GCC < 4.3.")
+endif()
+
+# For GCC 4.7, we can test the standard __cplusplus macro, ...
+# set(isCxx98Mode "__cplusplus >= 199711L")
+# set(isCxx11Mode "__cplusplus >= 201103L")
+# ... but before GCC 4.7, __cplusplus is always defined to 1, so check
+# the old macro.
+# set(isCxx98Mode "!defined(__GXX_EXPERIMENTAL_CXX0X__)")
+# set(isCxx11Mode "defined(__GXX_EXPERIMENTAL_CXX0X__)")
+
+set(_cmake_feature_test_cxx_delegating_constructors "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L")
diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake
index 7884eea..a15c14f 100644
--- a/Modules/Compiler/GNU-CXX.cmake
+++ b/Modules/Compiler/GNU-CXX.cmake
@@ -29,9 +29,15 @@ macro(cmake_record_cxx_compile_features)
     record_compiler_features(CXX "-std=${std_version}" ${list})
   endmacro()
 
+  if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
+    _get_gcc_features(gnu++98 CMAKE_CXX98_COMPILE_EXTENSIONS)
+  endif()
+
   if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
     _get_gcc_features(c++11 CMAKE_CXX11_COMPILE_FEATURES)
+    _get_gcc_features(gnu++11 CMAKE_CXX11_COMPILE_EXTENSIONS)
   elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
     _get_gcc_features(c++0x CMAKE_CXX11_COMPILE_FEATURES)
+    _get_gcc_features(gnu++0x CMAKE_CXX11_COMPILE_EXTENSIONS)
   endif()
 endmacro()
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 99a2f57..2665c09 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -42,7 +42,8 @@
 #include <assert.h>
 
 #define FOR_EACH_CXX_FEATURE(F) \
-  F(cxx_delegating_constructors)
+  F(cxx_delegating_constructors) \
+  F(gnuxx_typeof)
 
 class cmMakefile::Internals
 {
diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in
index 954a2fe..97298dc 100644
--- a/Tests/SystemInformation/SystemInformation.in
+++ b/Tests/SystemInformation/SystemInformation.in
@@ -26,7 +26,9 @@ CMAKE_CXX11_STANDARD_COMPILE_OPTION == "${CMAKE_CXX11_STANDARD_COMPILE_OPTION}"
 CMAKE_CXX98_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX98_EXTENSION_COMPILE_OPTION}"
 CMAKE_CXX11_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}"
 CMAKE_CXX_COMPILE_FEATURES == "${CMAKE_CXX_COMPILE_FEATURES}"
+CMAKE_CXX98_COMPILE_EXTENSIONS == "${CMAKE_CXX98_COMPILE_EXTENSIONS}"
 CMAKE_CXX11_COMPILE_FEATURES == "${CMAKE_CXX11_COMPILE_FEATURES}"
+CMAKE_CXX11_COMPILE_EXTENSIONS == "${CMAKE_CXX11_COMPILE_EXTENSIONS}"
 
 // C shared library flag
 CMAKE_SHARED_LIBRARY_C_FLAGS == "${CMAKE_SHARED_LIBRARY_C_FLAGS}"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aea693e73f16977b708b3e32c3d3ac46fd598ecf
commit aea693e73f16977b708b3e32c3d3ac46fd598ecf
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Oct 17 11:47:29 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:19 2013 +0100

    Record the compilers capable of the cxx_delegating_constructors feature.
    
    Add a feature test using the compiler macros and the preprocessor to
    determine available features. Add a unit test which outputs the
    feature test file compiled. Record the list of features in
    the SystemInformation unit test.
    
    Add a CMAKE_CXX_COMPILE_FEATURES variable which contains all features
    known to the loaded compiler, and a CMAKE_CXX_KNOWN_FEATURES variable
    containing all features known to CMake. Add language standard specific
    variables for internal use to determine the standard-specific compile
    flags to use. Add internal variables matching CMAKE_PP_NAME_<feature>
    for each feature. Those variables are used as preprocessor defines.

diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index ac3fa34..6e61d26 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -226,6 +226,8 @@ Variables for Languages
    :maxdepth: 1
 
    /variable/CMAKE_COMPILER_IS_GNULANG
+   /variable/CMAKE_CXX_COMPILE_FEATURES
+   /variable/CMAKE_CXX_KNOWN_FEATURES
    /variable/CMAKE_CXX_STANDARD
    /variable/CMAKE_Fortran_MODDIR_DEFAULT
    /variable/CMAKE_Fortran_MODDIR_FLAG
diff --git a/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst b/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst
new file mode 100644
index 0000000..6be0124
--- /dev/null
+++ b/Help/variable/CMAKE_CXX_COMPILE_FEATURES.rst
@@ -0,0 +1,8 @@
+CMAKE_CXX_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 :variable:`CMAKE_CXX_KNOWN_FEATURES`
+variable.
diff --git a/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
new file mode 100644
index 0000000..effaf6f
--- /dev/null
+++ b/Help/variable/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -0,0 +1,15 @@
+CMAKE_CXX_KNOWN_FEATURES
+------------------------
+
+List of C++ features known to this version of CMake.
+
+The features listed in this variable 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_CXX_COMPILE_FEATURES` variable.
+
+The features known to this version of CMake are:
+
+cxx_delegating_constructors
+  Delegating constructors, as defined in N1986_.
+
+.. _N1986: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 35aa6c4..f64cb66 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -2,6 +2,9 @@ set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@")
 set(CMAKE_CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@")
 set(CMAKE_CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@")
 set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@")
+set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@")
+set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
+
 set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@")
 set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@")
 set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@")
diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake
new file mode 100644
index 0000000..40aa9d6
--- /dev/null
+++ b/Modules/CMakeDetermineCompileFeatures.cmake
@@ -0,0 +1,43 @@
+
+#=============================================================================
+# Copyright 2013 Stephen Kelly <steveire at gmail.com>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+function(cmake_determine_compile_features lang)
+
+  if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
+    message(STATUS "Detecting ${lang} compile features")
+
+    set(CMAKE_CXX11_COMPILE_FEATURES)
+
+    include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
+
+    cmake_record_cxx_compile_features()
+
+    if(NOT _result EQUAL 0)
+      message(STATUS "Detecting ${lang} compile features - failed")
+      return()
+    endif()
+
+    if(NOT CMAKE_CXX_COMPILE_FEATURES)
+      set(CMAKE_CXX_COMPILE_FEATURES
+        ${CMAKE_CXX11_COMPILE_FEATURES}
+      )
+    endif()
+
+    set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE)
+    set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE)
+
+    message(STATUS "Detecting ${lang} compile features - done")
+  endif()
+
+endfunction()
diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake
index a06c92a..81561b2 100644
--- a/Modules/CMakeTestCXXCompiler.cmake
+++ b/Modules/CMakeTestCXXCompiler.cmake
@@ -66,6 +66,9 @@ else()
   # Try to identify the ABI and configure it into CMakeCXXCompiler.cmake
   include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
   CMAKE_DETERMINE_COMPILER_ABI(CXX ${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp)
+  # Try to identify the compiler features
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+  CMAKE_DETERMINE_COMPILE_FEATURES(CXX)
 
   # Re-configure to save learned information.
   configure_file(
diff --git a/Modules/Compiler/Clang-CXX-FeatureTests.cmake b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
new file mode 100644
index 0000000..940a182
--- /dev/null
+++ b/Modules/Compiler/Clang-CXX-FeatureTests.cmake
@@ -0,0 +1,9 @@
+
+set(testable_features
+  cxx_delegating_constructors
+)
+foreach(feature ${testable_features})
+  set(_cmake_feature_test_${feature} "__has_extension(${feature})")
+endforeach()
+
+unset(testable_features)
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index a1b3a10..4a72a99 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -22,3 +22,15 @@ elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
   set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
   set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
 endif()
+
+macro(cmake_record_cxx_compile_features)
+  macro(_get_clang_features std_version list)
+    record_compiler_features(CXX "-std=${std_version}" ${list})
+  endmacro()
+
+  if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1)
+    _get_clang_features(c++11 CMAKE_CXX11_COMPILE_FEATURES)
+  elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
+    _get_clang_features(c++0x CMAKE_CXX11_COMPILE_FEATURES)
+  endif()
+endmacro()
diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
new file mode 100644
index 0000000..7da0563
--- /dev/null
+++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake
@@ -0,0 +1,2 @@
+
+set(_cmake_feature_test_cxx_delegating_constructors "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407")
diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake
index 3ee8639..7884eea 100644
--- a/Modules/Compiler/GNU-CXX.cmake
+++ b/Modules/Compiler/GNU-CXX.cmake
@@ -23,3 +23,15 @@ elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
   set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
   set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
 endif()
+
+macro(cmake_record_cxx_compile_features)
+  macro(_get_gcc_features std_version list)
+    record_compiler_features(CXX "-std=${std_version}" ${list})
+  endmacro()
+
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
+    _get_gcc_features(c++11 CMAKE_CXX11_COMPILE_FEATURES)
+  elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
+    _get_gcc_features(c++0x CMAKE_CXX11_COMPILE_FEATURES)
+  endif()
+endmacro()
diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake
new file mode 100644
index 0000000..92d262c
--- /dev/null
+++ b/Modules/Internal/FeatureTesting.cmake
@@ -0,0 +1,57 @@
+
+macro(record_compiler_features lang compile_flags feature_list)
+  include("${CMAKE_ROOT}/Modules/Compiler/${CMAKE_${lang}_COMPILER_ID}-${lang}-FeatureTests.cmake" OPTIONAL)
+
+  string(TOLOWER ${lang} lang_lc)
+  file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin")
+  file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "
+  extern const char features[] = {\"\"\n")
+  foreach(feature ${CMAKE_${lang}_KNOWN_FEATURES})
+    if (_cmake_feature_test_${feature})
+      if (${_cmake_feature_test_${feature}} STREQUAL 1)
+        set(_feature_condition "\"1\" ")
+      else()
+        set(_feature_condition "#if ${_cmake_feature_test_${feature}}\n\"1\"\n#else\n\"0\"\n#endif\n")
+      endif()
+      file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n")
+    endif()
+  endforeach()
+  file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
+    "\n};\n\nint main(int, char **) { return 0; }\n")
+
+  try_compile(CMAKE_${lang}_FEATURE_TEST
+    ${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
+    COMPILE_DEFINITIONS "${compile_flags}"
+    OUTPUT_VARIABLE _output
+    COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
+    COPY_FILE_ERROR _copy_error
+    )
+  if(CMAKE_${lang}_FEATURE_TEST AND NOT _copy_error)
+    set(_result 0)
+  else()
+    set(_result 255)
+  endif()
+  unset(CMAKE_${lang}_FEATURE_TEST CACHE)
+
+  if (_result EQUAL 0)
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+      "\n\nDetecting ${lang} [${compile_flags}] compiler features compiled with the following output:\n${_output}\n\n")
+    if(EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin")
+      file(STRINGS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
+        features REGEX "${lang}_FEATURE:.*")
+      foreach(info ${features})
+        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+          "    Feature record: ${info}\n")
+        string(REPLACE "${lang}_FEATURE:" "" info ${info})
+        string(SUBSTRING ${info} 0 1 has_feature)
+        if(has_feature)
+          string(REGEX REPLACE "^1" "" feature ${info})
+          list(APPEND ${feature_list} ${feature})
+        endif()
+      endforeach()
+    endif()
+  else()
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+      "Detecting ${lang} [${compile_flags}] compiler features failed to compile with the following output:\n${_output}\n${_copy_error}\n\n")
+  endif()
+endmacro()
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 30a1557..99a2f57 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -41,6 +41,9 @@
 #include <ctype.h> // for isspace
 #include <assert.h>
 
+#define FOR_EACH_CXX_FEATURE(F) \
+  F(cxx_delegating_constructors)
+
 class cmMakefile::Internals
 {
 public:
@@ -2444,6 +2447,20 @@ const char* cmMakefile::GetDefinition(const char* name) const
     {
     this->Internal->VarUsageStack.top().insert(name);
     }
+  if (strcmp(name, "CMAKE_CXX_KNOWN_FEATURES") == 0)
+    {
+#define STRING_LIST_ELEMENT(F) ";" #F
+    return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
+#undef STRING_LIST_ELEMENT
+    }
+#define PP_FEATURE_NAME(F) \
+  if (strcmp(name, "CMAKE_PP_NAME_" #F) == 0) \
+    { \
+    static std::string val = ("COMPILER_" + cmSystemTools::UpperCase(#F)); \
+    return val.c_str(); \
+    }
+  FOR_EACH_CXX_FEATURE(PP_FEATURE_NAME)
+#undef PP_FEATURE_NAME
   const char* def = this->Internal->VarStack.top().Get(name);
   if(!def)
     {
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 0c685a1..b2ba6e8 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2203,6 +2203,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
   ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
   ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions)
   ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options)
+  ADD_TEST_MACRO(compile_features compile_features)
 
   configure_file(
     "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"
diff --git a/Tests/SystemInformation/CMakeLists.txt b/Tests/SystemInformation/CMakeLists.txt
index 838fd4a..1f88e15 100644
--- a/Tests/SystemInformation/CMakeLists.txt
+++ b/Tests/SystemInformation/CMakeLists.txt
@@ -1,4 +1,5 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.12)
+cmake_policy(SET CMP0025 NEW)
 project(SystemInformation)
 
 include_directories("This does not exists")
diff --git a/Tests/SystemInformation/SystemInformation.in b/Tests/SystemInformation/SystemInformation.in
index 92b24e2..954a2fe 100644
--- a/Tests/SystemInformation/SystemInformation.in
+++ b/Tests/SystemInformation/SystemInformation.in
@@ -25,6 +25,8 @@ CMAKE_CXX98_STANDARD_COMPILE_OPTION == "${CMAKE_CXX98_STANDARD_COMPILE_OPTION}"
 CMAKE_CXX11_STANDARD_COMPILE_OPTION == "${CMAKE_CXX11_STANDARD_COMPILE_OPTION}"
 CMAKE_CXX98_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX98_EXTENSION_COMPILE_OPTION}"
 CMAKE_CXX11_EXTENSION_COMPILE_OPTION == "${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}"
+CMAKE_CXX_COMPILE_FEATURES == "${CMAKE_CXX_COMPILE_FEATURES}"
+CMAKE_CXX11_COMPILE_FEATURES == "${CMAKE_CXX11_COMPILE_FEATURES}"
 
 // C shared library flag
 CMAKE_SHARED_LIBRARY_C_FLAGS == "${CMAKE_SHARED_LIBRARY_C_FLAGS}"
diff --git a/Tests/compile_features/CMakeLists.txt b/Tests/compile_features/CMakeLists.txt
new file mode 100644
index 0000000..c234357
--- /dev/null
+++ b/Tests/compile_features/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.12)
+cmake_policy(SET CMP0025 NEW)
+project(compile_features)
+
+if (EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.cxx")
+  file(READ "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.cxx" featureTest)
+  message("_CMAKE_CXX_CREATE_OBJECT_FILE: ${_CMAKE_CXX_CREATE_OBJECT_FILE}")
+  message("_compile_object_command: ${_compile_object_command}")
+  message("CTEST_FULL_OUTPUT\n${featureTest}")
+else()
+  message("No known features!")
+endif()
+
+add_executable(compile_features main.cpp)
diff --git a/Tests/compile_features/main.cpp b/Tests/compile_features/main.cpp
new file mode 100644
index 0000000..341aaaf
--- /dev/null
+++ b/Tests/compile_features/main.cpp
@@ -0,0 +1,5 @@
+
+int main(int, char **)
+{
+  return 0;
+}

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=89e36dffe0af0942dc9086a8b42754410b306cae
commit 89e36dffe0af0942dc9086a8b42754410b306cae
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 13 02:00:24 2013 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Nov 28 21:13:19 2013 +0100

    cmTarget: Add CXX_STANDARD and CXX_EXTENSION target properties.
    
    These are used to determine whether to add -std=c++11, -std=gnu++11
    etc flags on the compile line.

diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index d569e31..9f690d2 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -101,6 +101,8 @@ Properties on Targets
    /prop_tgt/COMPILE_OPTIONS
    /prop_tgt/CONFIG_OUTPUT_NAME
    /prop_tgt/CONFIG_POSTFIX
+   /prop_tgt/CXX_STANDARD
+   /prop_tgt/CXX_EXTENSIONS
    /prop_tgt/DEBUG_POSTFIX
    /prop_tgt/DEFINE_SYMBOL
    /prop_tgt/EchoString
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 4e24823..ac3fa34 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -226,6 +226,7 @@ Variables for Languages
    :maxdepth: 1
 
    /variable/CMAKE_COMPILER_IS_GNULANG
+   /variable/CMAKE_CXX_STANDARD
    /variable/CMAKE_Fortran_MODDIR_DEFAULT
    /variable/CMAKE_Fortran_MODDIR_FLAG
    /variable/CMAKE_Fortran_MODOUT_FLAG
diff --git a/Help/prop_tgt/CXX_EXTENSIONS.rst b/Help/prop_tgt/CXX_EXTENSIONS.rst
new file mode 100644
index 0000000..329e2c9
--- /dev/null
+++ b/Help/prop_tgt/CXX_EXTENSIONS.rst
@@ -0,0 +1,8 @@
+CXX_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=gnu++11
+instead of -std=c++11 to the compile line.
diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst
new file mode 100644
index 0000000..c3cd486
--- /dev/null
+++ b/Help/prop_tgt/CXX_STANDARD.rst
@@ -0,0 +1,13 @@
+CXX_STANDARD
+------------
+
+The C++ standard whose features are required to build this target.
+
+This property specifies the C++ standard whose features are required
+to build this target.  For some compilers, this results in adding a
+flag such as -std=c++11 to the compile line.
+
+Supported values are 98 and 11.
+
+This property is initialized by the value of the :variable:`CMAKE_CXX_STANDARD`
+variable if it is set when a target is created.
diff --git a/Help/variable/CMAKE_CXX_STANDARD.rst b/Help/variable/CMAKE_CXX_STANDARD.rst
new file mode 100644
index 0000000..87c00c8
--- /dev/null
+++ b/Help/variable/CMAKE_CXX_STANDARD.rst
@@ -0,0 +1,8 @@
+CMAKE_CXX_STANDARD
+------------------
+
+Default value for CXX_STANDARD property of targets.
+
+This variable is used to initialize the :prop_tgt:`CXX_STANDARD`
+property on all targets.  See that target property for additional
+information.
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index d26d6e9..d4f451e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1440,6 +1440,7 @@ void cmLocalGenerator::AddCompileOptions(
       this->AppendFlagEscape(flags, i->c_str());
       }
     }
+  this->AddCompilerRequirementFlag(flags, target, lang);
 }
 
 //----------------------------------------------------------------------------
@@ -2123,6 +2124,36 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
     }
 }
 
+//----------------------------------------------------------------------------
+void cmLocalGenerator::
+AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
+                           const char *lang)
+{
+  if (!lang)
+    {
+    return;
+    }
+  std::string l(lang);
+  std::string stdProp = l + "_STANDARD";
+  const char *standard = target->GetProperty(stdProp.c_str());
+  if (!standard)
+    {
+    return;
+    }
+  std::string extProp = l + "_EXTENSIONS";
+  bool ext = target->GetPropertyAsBool(extProp.c_str());
+  std::string type = ext ? "EXTENSION" : "STANDARD";
+
+  std::string compile_option =
+            "CMAKE_" + l + std::string(standard)
+                     + "_" + type + "_COMPILE_OPTION";
+  if (const char *opt =
+                target->GetMakefile()->GetDefinition(compile_option.c_str()))
+    {
+    this->AppendFlags(flags, opt);
+    }
+}
+
 static void AddVisibilityCompileOption(std::string &flags, cmTarget* target,
                                        cmLocalGenerator *lg, const char *lang)
 {
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 21700e9..4a307f7 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -147,6 +147,8 @@ public:
                                 const char *lang);
   void AddConfigVariableFlags(std::string& flags, const char* var,
                               const char* config);
+  void AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
+                                  const char *lang);
   ///! Append flags to a string.
   virtual void AppendFlags(std::string& flags, const char* newFlags);
   virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index fe68a8a..b4ae7f7 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -287,6 +287,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     this->SetPropertyDefault("MACOSX_BUNDLE", 0);
     this->SetPropertyDefault("MACOSX_RPATH", 0);
     this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0);
+    this->SetPropertyDefault("CXX_STANDARD", 0);
     }
 
   // Collect the set of configuration types.
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 9e74b7d..0c685a1 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -271,6 +271,19 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(AliasTarget AliasTarget)
   ADD_TEST_MACRO(StagingPrefix StagingPrefix)
   ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary)
+  if(CMAKE_CXX_COMPILER_ID STREQUAL GNU
+      AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
+    set(runCxxDialectTest 1)
+  endif()
+  if(CMAKE_CXX_COMPILER_ID STREQUAL Clang
+        AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.9)
+    if(NOT APPLE OR POLICY CMP0025)
+      set(runCxxDialectTest 1)
+    endif()
+  endif()
+  if(runCxxDialectTest)
+    ADD_TEST_MACRO(CxxDialect CxxDialect)
+  endif()
   set_tests_properties(EmptyLibrary PROPERTIES
     PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
   ADD_TEST_MACRO(CrossCompile CrossCompile)
diff --git a/Tests/CxxDialect/CMakeLists.txt b/Tests/CxxDialect/CMakeLists.txt
new file mode 100644
index 0000000..f0b2d10
--- /dev/null
+++ b/Tests/CxxDialect/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.12)
+cmake_policy(SET CMP0025 NEW)
+project(CxxDialect)
+
+add_executable(use_typeof use_typeof.cxx)
+set_property(TARGET use_typeof PROPERTY CXX_STANDARD 98)
+set_property(TARGET use_typeof PROPERTY CXX_EXTENSIONS TRUE)
+
+add_executable(use_constexpr use_constexpr.cxx)
+set_property(TARGET use_constexpr PROPERTY CXX_STANDARD 11)
+
+add_executable(CxxDialect use_constexpr_and_typeof.cxx)
+set_property(TARGET CxxDialect PROPERTY CXX_STANDARD 11)
+set_property(TARGET CxxDialect PROPERTY CXX_EXTENSIONS TRUE)
diff --git a/Tests/CxxDialect/use_constexpr.cxx b/Tests/CxxDialect/use_constexpr.cxx
new file mode 100644
index 0000000..30ccc4c
--- /dev/null
+++ b/Tests/CxxDialect/use_constexpr.cxx
@@ -0,0 +1,10 @@
+
+constexpr int foo()
+{
+  return 0;
+}
+
+int main(int argc, char**)
+{
+  return foo();
+}
diff --git a/Tests/CxxDialect/use_constexpr_and_typeof.cxx b/Tests/CxxDialect/use_constexpr_and_typeof.cxx
new file mode 100644
index 0000000..af217b6
--- /dev/null
+++ b/Tests/CxxDialect/use_constexpr_and_typeof.cxx
@@ -0,0 +1,11 @@
+
+constexpr int foo()
+{
+  return 0;
+}
+
+int main(int argc, char**)
+{
+  typeof(argc) ret = foo();
+  return ret;
+}
diff --git a/Tests/CxxDialect/use_typeof.cxx b/Tests/CxxDialect/use_typeof.cxx
new file mode 100644
index 0000000..dabb61f
--- /dev/null
+++ b/Tests/CxxDialect/use_typeof.cxx
@@ -0,0 +1,6 @@
+
+int main(int argc, char**)
+{
+  typeof(argc) ret = 0;
+  return ret;
+}

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list