[PATCH] add a module to check C++11 features

Rolf Eike Beer eike at sf-mail.de
Thu Mar 24 14:53:16 EDT 2011


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 <eike at sf-mail.de>
+#
+# 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


--nextPart2849071.ScilVGJ2el--

--nextPart1475909.iuGHcTdcOC
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)

iEYEABECAAYFAk9/FcMACgkQXKSJPmm5/E5sUQCfcmXyCD6/GpGTI8aSJPyP78hJ
93IAn2denJq8z4AFjpli4wsDpe1aLoj4
=m35U
-----END PGP SIGNATURE-----

--nextPart1475909.iuGHcTdcOC--



More information about the cmake-developers mailing list