Am Mittwoch, 4. April 2012, 10:13:17 schrieb Rolf Eike Beer: > > Hi! > > > > I'm going to write FinCXX11.cmake that will do the following: > > * find compiler flags that enable C++11 functionality, and store them in > > CXX11_CXX_FLAGS; > > * declare a component for some (each?) new language feature, and test it > > using check_cxx_source_compiles(). > > > > I have a few questions: > > - for each of supported compilers other than gcc and clang, which flags > > should I check? > > - for each new language feature, do you have a minimal code example that > > check if this feature is available? > > I already have such a macro (for the feature tests, not the compiler flag) > on my disk. I'll can send you the patches tonight. > > An older version of the patch can be found in > http://www.mail-archive.com/[email protected]/msg35421.html
Attached is what I currently have. Eike
>From 4e63f896970d16aab3ad595df9cd3b661f59688a Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer <[email protected]> Date: Thu, 24 Mar 2011 19:53:16 +0100 Subject: [PATCH] add a module to check C++11 features With this module one can get a set of CMake variables indicating which features of the new C++11 standard are supported by the compiler. --- Modules/CheckCXX11Features.cmake | 85 ++++++++++++++++++++ Modules/CheckCXX11Features/cxx11-test-__func__.cpp | 8 ++ Modules/CheckCXX11Features/cxx11-test-auto.cpp | 7 ++ .../cxx11-test-auto_fail_compile.cpp | 7 ++ .../cxx11-test-class_override_final.cpp | 21 +++++ ...xx11-test-class_override_final_fail_compile.cpp | 25 ++++++ .../CheckCXX11Features/cxx11-test-constexpr.cpp | 13 +++ Modules/CheckCXX11Features/cxx11-test-cstdint.cpp | 6 ++ .../cxx11-test-initializer_list.cpp | 27 +++++++ .../CheckCXX11Features/cxx11-test-long_long.cpp | 6 ++ Modules/CheckCXX11Features/cxx11-test-nullptr.cpp | 6 ++ .../cxx11-test-nullptr_fail_compile.cpp | 6 ++ .../cxx11-test-rvalue-references.cpp | 57 +++++++++++++ .../cxx11-test-sizeof_member.cpp | 9 +++ .../cxx11-test-sizeof_member_fail.cpp | 9 +++ .../cxx11-test-static_assert.cpp | 5 ++ .../cxx11-test-static_assert_fail_compile.cpp | 5 ++ Tests/CMakeLists.txt | 1 + Tests/Module/CXX11Features/CMakeLists.txt | 23 ++++++ Tests/Module/CXX11Features/cxx11features.cxx | 57 +++++++++++++ 20 files changed, 383 insertions(+) create mode 100644 Modules/CheckCXX11Features.cmake create mode 100644 Modules/CheckCXX11Features/cxx11-test-__func__.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-auto.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-auto_fail_compile.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-class_override_final.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-class_override_final_fail_compile.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-constexpr.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-cstdint.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-initializer_list.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-long_long.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-nullptr.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-nullptr_fail_compile.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-rvalue-references.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-sizeof_member.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-sizeof_member_fail.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-static_assert.cpp create mode 100644 Modules/CheckCXX11Features/cxx11-test-static_assert_fail_compile.cpp create mode 100644 Tests/Module/CXX11Features/CMakeLists.txt create mode 100644 Tests/Module/CXX11Features/cxx11features.cxx diff --git a/Modules/CheckCXX11Features.cmake b/Modules/CheckCXX11Features.cmake new file mode 100644 index 0000000..3ca5ca5 --- /dev/null +++ b/Modules/CheckCXX11Features.cmake @@ -0,0 +1,85 @@ +# - Check which parts of the C++11 standard the compiler supports + +#============================================================================= +# Copyright 2011,2012 Rolf Eike Beer <[email protected]> +# +# 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.) + +if (NOT CMAKE_CXX_COMPILER_LOADED) + message(FATAL_ERROR "CheckCXX11Features modules only works if language CXX is enabled") +endif() + +cmake_minimum_required(VERSION 2.8.3) + +function(cxx11_check_feature FEATURE_NAME RESULT_VAR) + if (NOT DEFINED ${RESULT_VAR}) + set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11_${FEATURE_NAME}") + + set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXX11Features/cxx11-test-${FEATURE_NAME}) + set(_LOG_NAME "\"${FEATURE_NAME}\"") + message(STATUS "Checking C++11 support for ${_LOG_NAME}") + + set(_SRCFILE "${_SRCFILE_BASE}.cpp") + set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp") + set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp") + + if (CROSS_COMPILING) + try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}") + if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}") + endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + else (CROSS_COMPILING) + try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR + "${_bindir}" "${_SRCFILE}") + if (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR) + set(${RESULT_VAR} TRUE) + else (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR) + set(${RESULT_VAR} FALSE) + endif (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR) + if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR + "${_bindir}_fail" "${_SRCFILE_FAIL}") + if (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR) + set(${RESULT_VAR} TRUE) + else (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR) + set(${RESULT_VAR} FALSE) + endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR) + endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL}) + endif (CROSS_COMPILING) + if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE}) + try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}") + if (_TMP_RESULT) + set(RESULT_VAR FALSE) + else (_TMP_RESULT) + set(RESULT_VAR TRUE) + endif (_TMP_RESULT) + endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE}) + + if (${RESULT_VAR}) + message(STATUS "Checking C++11 support for ${_LOG_NAME}: works") + else (${RESULT_VAR}) + message(STATUS "Checking C++11 support for ${_LOG_NAME}: not supported") + endif (${RESULT_VAR}) + set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}") + endif (NOT DEFINED ${RESULT_VAR}) +endfunction(cxx11_check_feature) + +cxx11_check_feature("static_assert" HAS_CXX11_STATIC_ASSERT) +cxx11_check_feature("long_long" HAS_CXX11_LONG_LONG) +cxx11_check_feature("auto" HAS_CXX11_AUTO) +cxx11_check_feature("rvalue-references" HAS_CXX11_RVALUE_REFERENCES) +cxx11_check_feature("constexpr" HAS_CXX11_CONSTEXPR) +cxx11_check_feature("sizeof_member" HAS_CXX11_SIZEOF_MEMBER) +cxx11_check_feature("__func__" HAS_CXX11_FUNC) +cxx11_check_feature("nullptr" HAS_CXX11_NULLPTR) +cxx11_check_feature("cstdint" HAS_CXX11_CSTDINT_H) +cxx11_check_feature("initializer_list" HAS_CXX11_INITIALIZER_LIST) +cxx11_check_feature("class_override_final" HAS_CXX11_CLASS_OVERRIDE) diff --git a/Modules/CheckCXX11Features/cxx11-test-__func__.cpp b/Modules/CheckCXX11Features/cxx11-test-__func__.cpp new file mode 100644 index 0000000..3bfd8a8 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-__func__.cpp @@ -0,0 +1,8 @@ +int main(void) +{ + if (!__func__) + return 1; + if (!(*__func__)) + return 1; + return 0; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-auto.cpp b/Modules/CheckCXX11Features/cxx11-test-auto.cpp new file mode 100644 index 0000000..77b010d --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-auto.cpp @@ -0,0 +1,7 @@ +int main(void) +{ + auto i = 42; + auto f = 42.0; + + return (i == f) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-auto_fail_compile.cpp b/Modules/CheckCXX11Features/cxx11-test-auto_fail_compile.cpp new file mode 100644 index 0000000..3c0e3f2 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-auto_fail_compile.cpp @@ -0,0 +1,7 @@ +int main(void) +{ + // must fail because there is no initializer + auto i; + + return 0; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-class_override_final.cpp b/Modules/CheckCXX11Features/cxx11-test-class_override_final.cpp new file mode 100644 index 0000000..cf14bc4 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-class_override_final.cpp @@ -0,0 +1,21 @@ +class base { +public: + virtual int foo(int a) + { return 4 + a; } + int bar(int a) final + { return a - 2; } +}; + +class sub final : public base { +public: + virtual int foo(int a) override + { return 8 + 2 * a; }; +}; + +int main(void) +{ + base b; + sub s; + + return (b.foo(2) * 2 == sub.foo(2)) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-class_override_final_fail_compile.cpp b/Modules/CheckCXX11Features/cxx11-test-class_override_final_fail_compile.cpp new file mode 100644 index 0000000..bc00b27 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-class_override_final_fail_compile.cpp @@ -0,0 +1,25 @@ +class base { +public: + virtual int foo(int a) + { return 4 + a; } + virtual int bar(int a) final + { return a - 2; } +}; + +class sub final : public base { +public: + virtual int foo(int a) override + { return 8 + 2 * a; }; + virtual int bar(int a) + { return a; } +}; + +class impossible : public sub { }; + +int main(void) +{ + base b; + sub s; + + return 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-constexpr.cpp b/Modules/CheckCXX11Features/cxx11-test-constexpr.cpp new file mode 100644 index 0000000..37ee124 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-constexpr.cpp @@ -0,0 +1,13 @@ +#include <sys/types.h> + +constexpr size_t intsize() +{ + return sizeof(int); +} + +int main(void) +{ + unsigned char size_like_int[intsize()]; + + return sizeof(size_like_int) >= sizeof(int) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-cstdint.cpp b/Modules/CheckCXX11Features/cxx11-test-cstdint.cpp new file mode 100644 index 0000000..56f9896 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-cstdint.cpp @@ -0,0 +1,6 @@ +#include <cstdint> + +int main(void) +{ + return (sizeof(uint64_t) == 8) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-initializer_list.cpp b/Modules/CheckCXX11Features/cxx11-test-initializer_list.cpp new file mode 100644 index 0000000..aad4e55 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-initializer_list.cpp @@ -0,0 +1,27 @@ +#include <vector> + +class seq { +public: + seq(std::initializer_list<int> list); + + int length() const; +private: + std::vector<int> m_v; +}; + +seq::seq(std::initializer_list<int> list) + : m_v(list) +{ +} + +int seq::length() const +{ + return m_v.length(); +} + +int main(void) +{ + seq a = {18, 20, 2, 0, 4, 7}; + + return (a.length() == 6) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-long_long.cpp b/Modules/CheckCXX11Features/cxx11-test-long_long.cpp new file mode 100644 index 0000000..9a7f137 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-long_long.cpp @@ -0,0 +1,6 @@ +int main(void) +{ + long long l; + + return sizeof(l == 8) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-nullptr.cpp b/Modules/CheckCXX11Features/cxx11-test-nullptr.cpp new file mode 100644 index 0000000..9f41071 --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-nullptr.cpp @@ -0,0 +1,6 @@ +int main(void) +{ + void *v = nullptr; + + return v ? 1 : 0; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-nullptr_fail_compile.cpp b/Modules/CheckCXX11Features/cxx11-test-nullptr_fail_compile.cpp new file mode 100644 index 0000000..6a002bc --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-nullptr_fail_compile.cpp @@ -0,0 +1,6 @@ +int main(void) +{ + int i = nullptr; + + return 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-rvalue-references.cpp b/Modules/CheckCXX11Features/cxx11-test-rvalue-references.cpp new file mode 100644 index 0000000..e6e7e5a --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-rvalue-references.cpp @@ -0,0 +1,57 @@ +#include <cassert> + +class rvmove { +public: + void *ptr; + char *array; + + rvmove() + : ptr(0), + array(new char[10]) + { + ptr = this; + } + + rvmove(rvmove &&other) + : ptr(other.ptr), + array(other.array) + { + other.array = 0; + other.ptr = 0; + } + + ~rvmove() + { + assert(((ptr != 0) && (array != 0)) || ((ptr == 0) && (array == 0))); + delete[] array; + } + + rvmove &operator=(rvmove &&other) + { + delete[] array; + ptr = other.ptr; + array = other.array; + other.array = 0; + other.ptr = 0; + return *this; + } + + static rvmove create() + { + return rvmove(); + } +private: + rvmove(const rvmove &); + rvmove &operator=(const rvmove &); +}; + +int main() +{ + rvmove mine; + if (mine.ptr != &mine) + return 1; + mine = rvmove::create(); + if (mine.ptr == &mine) + return 1; + return 0; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-sizeof_member.cpp b/Modules/CheckCXX11Features/cxx11-test-sizeof_member.cpp new file mode 100644 index 0000000..5aea6ab --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-sizeof_member.cpp @@ -0,0 +1,9 @@ +struct foo { + short bar; + int baz; +}; + +int main(void) +{ + return (sizeof(foo::baz) == 4) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-sizeof_member_fail.cpp b/Modules/CheckCXX11Features/cxx11-test-sizeof_member_fail.cpp new file mode 100644 index 0000000..0348c2c --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-sizeof_member_fail.cpp @@ -0,0 +1,9 @@ +struct foo { + int baz; + double bar; +}; + +int main(void) +{ + return (sizeof(foo::bar) == 4) ? 0 : 1; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-static_assert.cpp b/Modules/CheckCXX11Features/cxx11-test-static_assert.cpp new file mode 100644 index 0000000..47c2fef --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-static_assert.cpp @@ -0,0 +1,5 @@ +int main(void) +{ + static_assert(0 < 1, "your ordering of integers is screwed"); + return 0; +} diff --git a/Modules/CheckCXX11Features/cxx11-test-static_assert_fail_compile.cpp b/Modules/CheckCXX11Features/cxx11-test-static_assert_fail_compile.cpp new file mode 100644 index 0000000..362fcdd --- /dev/null +++ b/Modules/CheckCXX11Features/cxx11-test-static_assert_fail_compile.cpp @@ -0,0 +1,5 @@ +int main(void) +{ + static_assert(1 < 0, "your ordering of integers is screwed"); + return 0; +} diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index c0b7cd6..3cdaf64 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -312,6 +312,7 @@ IF(BUILD_TESTING) LIST(APPEND TEST_BUILD_DIRS ${CMAKE_BUILD_TEST_BINARY_DIR}) ADD_TEST_MACRO(Module.CheckTypeSize CheckTypeSize) + ADD_TEST_MACRO(Module.CXX11Features CXX11Features) ADD_TEST_MACRO(Module.GenerateExportHeader GenerateExportHeader) diff --git a/Tests/Module/CXX11Features/CMakeLists.txt b/Tests/Module/CXX11Features/CMakeLists.txt new file mode 100644 index 0000000..5c09f0b --- /dev/null +++ b/Tests/Module/CXX11Features/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR) +project(Cxx11Features CXX) + +include(CheckCXX11Features) + +foreach (flag + HAS_CXX11_STATIC_ASSERT + HAS_CXX11_LONG_LONG + HAS_CXX11_RVALUE_REFERENCES + HAS_CXX11_CONSTEXPR + HAS_CXX11_SIZEOF_MEMBER + HAS_CXX11_FUNC + HAS_CXX11_NULLPTR + HAS_CXX11_CSTDINT_H + HAS_CXX11_INITIALIZER_LIST + HAS_CXX11_CLASS_OVERRIDE) + if (${flag}) + add_definitions("-D${flag}") + message(STATUS "Compiler C++11 support flag ${flag} set") + endif () +endforeach (flag) + +add_executable(CXX11Features cxx11features.cxx) diff --git a/Tests/Module/CXX11Features/cxx11features.cxx b/Tests/Module/CXX11Features/cxx11features.cxx new file mode 100644 index 0000000..c09038f --- /dev/null +++ b/Tests/Module/CXX11Features/cxx11features.cxx @@ -0,0 +1,57 @@ +#if defined(HAS_CXX0X_CSTDINT_H) +#include <cstdint> +#endif + +#include <sys/types.h> + +struct thing { + unsigned char one; +#if defined(HAS_CXX0X_CSTDINT_H) + uint32_t four; +#endif +#if defined(HAS_CXX0X_LONG_LONG) + long long eight; +#endif +}; + +#include <stdio.h> + +int main() +{ +#if defined (HAS_CXX0X_NULLPTR) + void *nix = nullptr; +#else /* HAS_CXX0X_NULLPTR */ + void *nix = 0; +#endif /* HAS_CXX0X_NULLPTR */ + +#if defined(HAS_CXX0X_STATIC_ASSERT) + static_assert(1 < 42, "Your C++ compiler is b0rked"); +#endif /* HAS_CXX0X_STATIC_ASSERT */ + +#if defined(HAS_CXX0X_FUNC) + const char *funcname = __func__; + printf("the name of main() function is: %s\n", funcname); +#endif /* HAS_CXX0X_FUNC */ + +#if defined(HAS_CXX0X_SIZEOF_MEMBER) + size_t onesize = sizeof(thing::one); +#if defined(HAS_CXX0X_STATIC_ASSERT) + static_assert(sizeof(thing::one) == 1, "Your char is not one byte long"); +#endif /* HAS_CXX0X_STATIC_ASSERT */ + +#if defined(HAS_CXX0X_CSTDINT_H) + size_t foursize = sizeof(thing::four); +#if defined(HAS_CXX0X_STATIC_ASSERT) + static_assert(sizeof(thing::four) == 4, "Your uint32_t is not 32 bit long"); +#endif /* HAS_CXX0X_STATIC_ASSERT */ +#endif /* HAS_CXX0X_CSTDINT_H */ +#if defined(HAS_CXX0X_LONG_LONG) + size_t eightsize = sizeof(thing::eight); +#if defined(HAS_CXX0X_STATIC_ASSERT) + static_assert(sizeof(thing::eight) == 8, "Your long long is not 64 bit long"); +#endif /* HAS_CXX0X_STATIC_ASSERT */ +#endif /* HAS_CXX0X_LONG_LONG */ +#endif /* HAS_CXX0X_SIZEOF_MEMBER */ + + return 0; +} -- 1.7.9.2
signature.asc
Description: This is a digitally signed message part.
-- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://public.kitware.com/cgi-bin/mailman/listinfo/cmake-developers
