[PATCH] add a module to check C++0x 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 upcoming C++0x standard are supported by the compiler.
---
 Modules/CheckCXX0xFeatures.cmake                   |   68 ++++++++++++++++++++
 Modules/c++0x-test-__func__-N2340.cpp              |    8 ++
 Modules/c++0x-test-constexpr-N2235.cpp             |   13 ++++
 Modules/c++0x-test-cstdint.cpp                     |    6 ++
 Modules/c++0x-test-long_long-N1811.cpp             |    6 ++
 Modules/c++0x-test-nullptr-N2431.cpp               |    6 ++
 Modules/c++0x-test-nullptr-N2431_fail_compile.cpp  |    6 ++
 Modules/c++0x-test-rvalue-references-N2118.cpp     |   57 ++++++++++++++++
 Modules/c++0x-test-sizeof_member-N2253.cpp         |    9 +++
 Modules/c++0x-test-sizeof_member-N2253_fail.cpp    |    9 +++
 Modules/c++0x-test-static_assert-N1720.cpp         |    5 ++
 ...c++0x-test-static_assert-N1720_fail_compile.cpp |    5 ++
 Tests/CMakeLists.txt                               |    1 +
 Tests/Module/CXX0xFeatures/CMakeLists.txt          |   21 ++++++
 Tests/Module/CXX0xFeatures/cxx0xfeatures.cxx       |   57 ++++++++++++++++
 15 files changed, 277 insertions(+), 0 deletions(-)
 create mode 100644 Modules/CheckCXX0xFeatures.cmake
 create mode 100644 Modules/c++0x-test-__func__-N2340.cpp
 create mode 100644 Modules/c++0x-test-constexpr-N2235.cpp
 create mode 100644 Modules/c++0x-test-cstdint.cpp
 create mode 100644 Modules/c++0x-test-long_long-N1811.cpp
 create mode 100644 Modules/c++0x-test-nullptr-N2431.cpp
 create mode 100644 Modules/c++0x-test-nullptr-N2431_fail_compile.cpp
 create mode 100644 Modules/c++0x-test-rvalue-references-N2118.cpp
 create mode 100644 Modules/c++0x-test-sizeof_member-N2253.cpp
 create mode 100644 Modules/c++0x-test-sizeof_member-N2253_fail.cpp
 create mode 100644 Modules/c++0x-test-static_assert-N1720.cpp
 create mode 100644 Modules/c++0x-test-static_assert-N1720_fail_compile.cpp
 create mode 100644 Tests/Module/CXX0xFeatures/CMakeLists.txt
 create mode 100644 Tests/Module/CXX0xFeatures/cxx0xfeatures.cxx

diff --git a/Modules/CheckCXX0xFeatures.cmake b/Modules/CheckCXX0xFeatures.cmake
new file mode 100644
index 0000000..3e77a66
--- /dev/null
+++ b/Modules/CheckCXX0xFeatures.cmake
@@ -0,0 +1,68 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
+
+MACRO(CXX0X_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
+	IF (NOT DEFINED ${RESULT_VAR})
+		set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx0x_${FEATURE_NAME}")
+
+		IF (${FEATURE_NUMBER})
+			SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++0x-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
+			SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
+		ELSE (${FEATURE_NUMBER})
+			SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++0x-test-${FEATURE_NAME})
+			SET(_LOG_NAME "\"${FEATURE_NAME}\"")
+		ENDIF (${FEATURE_NUMBER})
+		MESSAGE(STATUS "Checking C++0x 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++0x support for ${_LOG_NAME}: works")
+		ELSE (${RESULT_VAR})
+			MESSAGE(STATUS "Checking C++0x support for ${_LOG_NAME}: not supported")
+		ENDIF (${RESULT_VAR})
+		SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++0x support for ${_LOG_NAME}")
+	ENDIF (NOT DEFINED ${RESULT_VAR})
+ENDMACRO(CXX0X_CHECK_FEATURE)
+
+CXX0X_CHECK_FEATURE("static_assert" 1720 HAS_CXX0X_STATIC_ASSERT)
+CXX0X_CHECK_FEATURE("long_long" 1811 HAS_CXX0X_LONG_LONG)
+CXX0X_CHECK_FEATURE("rvalue-references" 2118 HAS_CXX0X_RVALUE_REFERENCES)
+CXX0X_CHECK_FEATURE("constexpr" 2235 HAS_CXX0X_CONSTEXPR)
+CXX0X_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX0X_SIZEOF_MEMBER)
+CXX0X_CHECK_FEATURE("__func__" 2340 HAS_CXX0X_FUNC)
+CXX0X_CHECK_FEATURE("nullptr" 2431 HAS_CXX0X_NULLPTR)
+CXX0X_CHECK_FEATURE("cstdint" "" HAS_CXX0X_CSTDINT_H)
diff --git a/Modules/c++0x-test-__func__-N2340.cpp b/Modules/c++0x-test-__func__-N2340.cpp
new file mode 100644
index 0000000..bbd0be9
--- /dev/null
+++ b/Modules/c++0x-test-__func__-N2340.cpp
@@ -0,0 +1,8 @@
+int main(void)
+{
+	if (!__func__)
+		return 1;
+	if (!(*__func__))
+		return 1;
+	return 0;
+}
\ No newline at end of file
diff --git a/Modules/c++0x-test-constexpr-N2235.cpp b/Modules/c++0x-test-constexpr-N2235.cpp
new file mode 100644
index 0000000..37ee124
--- /dev/null
+++ b/Modules/c++0x-test-constexpr-N2235.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/c++0x-test-cstdint.cpp b/Modules/c++0x-test-cstdint.cpp
new file mode 100644
index 0000000..5d1aed8
--- /dev/null
+++ b/Modules/c++0x-test-cstdint.cpp
@@ -0,0 +1,6 @@
+#include <cstdint>
+
+int main(void)
+{
+	return (sizeof(uint64_t) == 8) ? 0 : 1;
+}
\ No newline at end of file
diff --git a/Modules/c++0x-test-long_long-N1811.cpp b/Modules/c++0x-test-long_long-N1811.cpp
new file mode 100644
index 0000000..9a7f137
--- /dev/null
+++ b/Modules/c++0x-test-long_long-N1811.cpp
@@ -0,0 +1,6 @@
+int main(void)
+{
+	long long l;
+
+	return sizeof(l == 8) ? 0 : 1;
+}
diff --git a/Modules/c++0x-test-nullptr-N2431.cpp b/Modules/c++0x-test-nullptr-N2431.cpp
new file mode 100644
index 0000000..9f41071
--- /dev/null
+++ b/Modules/c++0x-test-nullptr-N2431.cpp
@@ -0,0 +1,6 @@
+int main(void)
+{
+	void *v = nullptr;
+
+	return v ? 1 : 0;
+}
diff --git a/Modules/c++0x-test-nullptr-N2431_fail_compile.cpp b/Modules/c++0x-test-nullptr-N2431_fail_compile.cpp
new file mode 100644
index 0000000..6a002bc
--- /dev/null
+++ b/Modules/c++0x-test-nullptr-N2431_fail_compile.cpp
@@ -0,0 +1,6 @@
+int main(void)
+{
+	int i = nullptr;
+
+	return 1;
+}
diff --git a/Modules/c++0x-test-rvalue-references-N2118.cpp b/Modules/c++0x-test-rvalue-references-N2118.cpp
new file mode 100644
index 0000000..e261add
--- /dev/null
+++ b/Modules/c++0x-test-rvalue-references-N2118.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;
+}
\ No newline at end of file
diff --git a/Modules/c++0x-test-sizeof_member-N2253.cpp b/Modules/c++0x-test-sizeof_member-N2253.cpp
new file mode 100644
index 0000000..27ed4e8
--- /dev/null
+++ b/Modules/c++0x-test-sizeof_member-N2253.cpp
@@ -0,0 +1,9 @@
+struct foo {
+	short bar;
+	int baz;
+};
+
+int main(void)
+{
+	return (sizeof(foo::baz) == 4) ? 0 : 1;
+}
\ No newline at end of file
diff --git a/Modules/c++0x-test-sizeof_member-N2253_fail.cpp b/Modules/c++0x-test-sizeof_member-N2253_fail.cpp
new file mode 100644
index 0000000..579a31d
--- /dev/null
+++ b/Modules/c++0x-test-sizeof_member-N2253_fail.cpp
@@ -0,0 +1,9 @@
+struct foo {
+	int baz;
+	double bar;
+};
+
+int main(void)
+{
+	return (sizeof(foo::bar) == 4) ? 0 : 1;
+}
\ No newline at end of file
diff --git a/Modules/c++0x-test-static_assert-N1720.cpp b/Modules/c++0x-test-static_assert-N1720.cpp
new file mode 100644
index 0000000..1406b86
--- /dev/null
+++ b/Modules/c++0x-test-static_assert-N1720.cpp
@@ -0,0 +1,5 @@
+int main(void)
+{
+	static_assert(0 < 1, "your ordering of integers is screwed");
+	return 0;
+}
\ No newline at end of file
diff --git a/Modules/c++0x-test-static_assert-N1720_fail_compile.cpp b/Modules/c++0x-test-static_assert-N1720_fail_compile.cpp
new file mode 100644
index 0000000..56e0979
--- /dev/null
+++ b/Modules/c++0x-test-static_assert-N1720_fail_compile.cpp
@@ -0,0 +1,5 @@
+int main(void)
+{
+	static_assert(1 < 0, "your ordering of integers is screwed");
+	return 0;
+}
\ No newline at end of file
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 77c5752..64d0293 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -197,6 +197,7 @@ IF(BUILD_TESTING)
   LIST(APPEND TEST_BUILD_DIRS ${CMAKE_BUILD_TEST_BINARY_DIR})
 
   ADD_TEST_MACRO(Module.CheckTypeSize CheckTypeSize)
+  ADD_TEST_MACRO(Module.CXX0xFeatures CXX0xFeatures)
 
   ADD_TEST(LinkFlags-prepare
     ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE}
diff --git a/Tests/Module/CXX0xFeatures/CMakeLists.txt b/Tests/Module/CXX0xFeatures/CMakeLists.txt
new file mode 100644
index 0000000..24ca26f
--- /dev/null
+++ b/Tests/Module/CXX0xFeatures/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
+project(Cxx0xFeatures C CXX)
+
+include(CheckCXX0xFeatures)
+
+foreach (flag
+		HAS_CXX0X_STATIC_ASSERT
+		HAS_CXX0X_LONG_LONG
+		HAS_CXX0X_RVALUE_REFERENCES
+		HAS_CXX0X_CONSTEXPR
+		HAS_CXX0X_SIZEOF_MEMBER
+		HAS_CXX0X_FUNC
+		HAS_CXX0X_NULLPTR
+		HAS_CXX0X_CSTDINT_H)
+	if (${flag})
+		add_definitions("-D${flag}")
+		message(STATUS "Compiler C++0x support flag ${flag} set")
+	endif ()
+endforeach (flag)
+
+add_executable(CXX0xFeatures cxx0xfeatures.cxx)
diff --git a/Tests/Module/CXX0xFeatures/cxx0xfeatures.cxx b/Tests/Module/CXX0xFeatures/cxx0xfeatures.cxx
new file mode 100644
index 0000000..63a370f
--- /dev/null
+++ b/Tests/Module/CXX0xFeatures/cxx0xfeatures.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 uint32_t is not 64 bit long");
+#endif /* HAS_CXX0X_STATIC_ASSERT */
+#endif /* HAS_CXX0X_LONG_LONG */
+#endif /* HAS_CXX0X_SIZEOF_MEMBER */
+
+	return 0;
+}
-- 
1.7.3.2


--nextPart19155234.zELj1v8XrJ--

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

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

iEYEABECAAYFAk2LlPUACgkQXKSJPmm5/E5nGwCcCXjbapCbXFZrcidVS1lCLuI9
NDkAoJF1d3XrdinAPLasgqwQfYePP/VL
=fXMh
-----END PGP SIGNATURE-----

--nextPart1710391.N8rhx4VA7r--



More information about the CMake mailing list