Pārlūkot izejas kodu

Add macro for checking the compiler's C++11 type trait templates.
Modify angelscript.h header file to use our custom compiler define based on the check result to cater for pre-standard Clang compiler toolchain.

Yao Wei Tjong 姚伟忠 8 gadi atpakaļ
vecāks
revīzija
40516e48c9

+ 33 - 1
CMake/Modules/CheckCompilerToolchain.cmake

@@ -51,6 +51,12 @@
 #  RTTI
 #  RTTI
 #  EXCEPTIONS
 #  EXCEPTIONS
 #
 #
+# C++11 type traits standard:
+#  IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE
+#  IS_TRIVIALLY_DESTRUCTIBLE
+#  IS_TRIVIALLY_COPY_ASSIGNABLE
+#  IS_TRIVIALLY_COPY_CONSTRUCTIBLE
+#  CLANG_PRE_STANDARD (Clang with pre-standard type trait templates)
 
 
 if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
 if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
     set (EMCC_FIX EMCC_FIX)
     set (EMCC_FIX EMCC_FIX)
@@ -124,6 +130,24 @@ macro (check_feature_enabled FEATURE)
     endif ()
     endif ()
 endmacro ()
 endmacro ()
 
 
+include (CheckCXXSourceCompiles)
+
+# Macro for checking if the type trait template is matching the C++11 standard
+macro (check_type_trait TYPE_TRAIT)
+    string (TOUPPER ${TYPE_TRAIT} UPPERCASE_${TYPE_TRAIT})
+    if (INVALIDATE_CCT)
+        unset (${UPPERCASE_${TYPE_TRAIT}} CACHE)
+    endif ()
+    if (CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang)
+        set (ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
+        set (CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
+    endif ()
+    check_cxx_source_compiles ("#include <type_traits>\nint main() { return std::${TYPE_TRAIT}<bool>::value; }" ${UPPERCASE_${TYPE_TRAIT}})
+    if (CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang)
+        set (CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+    endif ()
+endmacro ()
+
 # Macro for checking if a native compiler toolchain exists for building the host tool targets
 # Macro for checking if a native compiler toolchain exists for building the host tool targets
 # This macro is designed to be used in cross-compiling build
 # This macro is designed to be used in cross-compiling build
 macro (check_native_compiler_exist)
 macro (check_native_compiler_exist)
@@ -147,7 +171,7 @@ if (MSVC)
     # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
     # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
     set (NATIVE_64BIT ${CMAKE_CL_64})
     set (NATIVE_64BIT ${CMAKE_CL_64})
     # We only support one target arch when using MSVC for now and make certain assumptions as per documentation instead of querying the compiler
     # We only support one target arch when using MSVC for now and make certain assumptions as per documentation instead of querying the compiler
-    foreach (VAR X86 HAVE_MMX HAVE_SSE HAVE_SSE2 HAVE_SSE3 HAVE_SSE4 HAVE_AVX RTTI EXCEPTIONS)
+    foreach (VAR X86 HAVE_MMX HAVE_SSE HAVE_SSE2 HAVE_SSE3 HAVE_SSE4 HAVE_AVX RTTI EXCEPTIONS IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE IS_TRIVIALLY_DESTRUCTIBLE IS_TRIVIALLY_COPY_ASSIGNABLE IS_TRIVIALLY_COPY_CONSTRUCTIBLE)
         set (${VAR} 1)
         set (${VAR} 1)
     endforeach ()
     endforeach ()
 else ()
 else ()
@@ -204,4 +228,12 @@ else ()
     # Check if C++ feature is being turned on/off in the configured compiler flags
     # Check if C++ feature is being turned on/off in the configured compiler flags
     check_feature_enabled (RTTI __GXX_RTTI)
     check_feature_enabled (RTTI __GXX_RTTI)
     check_feature_enabled (EXCEPTIONS)
     check_feature_enabled (EXCEPTIONS)
+    # Check if C++11 type trait standard is being followed
+    check_type_trait (is_trivially_default_constructible)
+    check_type_trait (is_trivially_destructible)
+    check_type_trait (is_trivially_copy_assignable)
+    check_type_trait (is_trivially_copy_constructible)
+    if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND NOT IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE AND IS_TRIVIALLY_DESTRUCTIBLE)
+        set (CLANG_PRE_STANDARD 1)
+    endif ()
 endif ()
 endif ()

+ 2 - 0
CMake/Modules/exportheader.cmake.in

@@ -32,6 +32,8 @@
 #cmakedefine URHO3D_LUAJIT
 #cmakedefine URHO3D_LUAJIT
 #cmakedefine URHO3D_TESTING
 #cmakedefine URHO3D_TESTING
 
 
+#cmakedefine CLANG_PRE_STANDARD
+
 #ifdef @STATIC_DEFINE@
 #ifdef @STATIC_DEFINE@
 #  define @EXPORT_MACRO_NAME@
 #  define @EXPORT_MACRO_NAME@
 #  define @NO_EXPORT_MACRO_NAME@
 #  define @NO_EXPORT_MACRO_NAME@

+ 3 - 0
Source/ThirdParty/AngelScript/CMakeLists.txt

@@ -24,6 +24,9 @@
 set (TARGET_NAME AngelScript)
 set (TARGET_NAME AngelScript)
 
 
 # Define preprocessor macros
 # Define preprocessor macros
+if (CLANG_PRE_STANDARD)
+    add_definitions (-DCLANG_PRE_STANDARD)
+endif ()
 if (NOT EXCEPTIONS)
 if (NOT EXCEPTIONS)
     add_definitions (-DAS_NO_EXCEPTIONS)
     add_definitions (-DAS_NO_EXCEPTIONS)
 endif ()
 endif ()

+ 11 - 15
Source/ThirdParty/AngelScript/include/angelscript.h

@@ -28,7 +28,7 @@
    [email protected]
    [email protected]
 */
 */
 
 
-// Modified by Lasse Oorni and Nathanial Lydick for Urho3D
+// Modified by Lasse Oorni, Nathanial Lydick, and Yao Wei Tjong for Urho3D
 
 
 //
 //
 // angelscript.h
 // angelscript.h
@@ -420,15 +420,14 @@ typedef asIScriptContext *(*asREQUESTCONTEXTFUNC_t)(asIScriptEngine *, void *);
 typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, void *);
 typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, void *);
 
 
 // Check if the compiler can use C++11 features
 // Check if the compiler can use C++11 features
-// Urho3D: restored earlier ifdef
 #if !defined(_MSC_VER) || _MSC_VER >= 1700   // MSVC 2012
 #if !defined(_MSC_VER) || _MSC_VER >= 1700   // MSVC 2012
-#if !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)  // gnuc 4.7
-#if !(defined(__GNUC__) && defined(__cplusplus) && __cplusplus < 201103L) // g++ -std=c++11
-#if !defined(__SUNPRO_CC)
-#define AS_CAN_USE_CPP11 1
-#endif
-#endif
-#endif
+ #if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)  // gnuc 4.7 or clang
+  #if !(defined(__GNUC__) && defined(__cplusplus) && __cplusplus < 201103L) // gnuc and clang require compiler flag -std=c++11
+   #if !defined(__SUNPRO_CC) // Oracle Solaris Studio
+    #define AS_CAN_USE_CPP11 1
+   #endif
+  #endif
+ #endif
 #endif
 #endif
 
 
 // This macro does basically the same thing as offsetof defined in stddef.h, but
 // This macro does basically the same thing as offsetof defined in stddef.h, but
@@ -442,9 +441,6 @@ typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, voi
 // check that the cast is really valid.
 // check that the cast is really valid.
 // BCC v5.8 (C++Builder 2006) and earlier have a similar bug which forces us to fall back to a C-style cast.
 // BCC v5.8 (C++Builder 2006) and earlier have a similar bug which forces us to fall back to a C-style cast.
 #define asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())((r (*)p)(f)))
 #define asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())((r (*)p)(f)))
-#elif (defined(_MSC_VER) && _MSC_VER >= 1900)
-// Urho3D: VS2015 does not compile the C-style cast of the function pointer
-#define asFUNCTIONPR(f,p,r) asFunctionPtr(reinterpret_cast<void (*)()>(static_cast<r (*)p>(f)))
 #else
 #else
 #define asFUNCTIONPR(f,p,r) asFunctionPtr(reinterpret_cast<void (*)()>(static_cast<r (*)p>(f)))
 #define asFUNCTIONPR(f,p,r) asFunctionPtr(reinterpret_cast<void (*)()>(static_cast<r (*)p>(f)))
 #endif
 #endif
@@ -605,15 +601,15 @@ BEGIN_AS_NAMESPACE
 template<typename T>
 template<typename T>
 asUINT asGetTypeTraits()
 asUINT asGetTypeTraits()
 {
 {
-// Urho3D: restore earlier ifdefs due to some Android CI builds breaking
-#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5)
+// Urho3D - Clang compiler built with old GCC's libstdc++ suffers the same pre-standard templates problem as old GCC compiler
+#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5) || (defined(__clang__) && !defined(CLANG_PRE_STANDARD))
 	// MSVC, XCode/Clang, and gnuc 5+
 	// MSVC, XCode/Clang, and gnuc 5+
 	// C++11 compliant code
 	// C++11 compliant code
 	bool hasConstructor        = std::is_default_constructible<T>::value && !std::is_trivially_default_constructible<T>::value;
 	bool hasConstructor        = std::is_default_constructible<T>::value && !std::is_trivially_default_constructible<T>::value;
 	bool hasDestructor         = std::is_destructible<T>::value          && !std::is_trivially_destructible<T>::value;
 	bool hasDestructor         = std::is_destructible<T>::value          && !std::is_trivially_destructible<T>::value;
 	bool hasAssignmentOperator = std::is_copy_assignable<T>::value       && !std::is_trivially_copy_assignable<T>::value;
 	bool hasAssignmentOperator = std::is_copy_assignable<T>::value       && !std::is_trivially_copy_assignable<T>::value;
 	bool hasCopyConstructor    = std::is_copy_constructible<T>::value    && !std::is_trivially_copy_constructible<T>::value;
 	bool hasCopyConstructor    = std::is_copy_constructible<T>::value    && !std::is_trivially_copy_constructible<T>::value;
-#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__)
 	// gnuc 4.8 is using a mix of C++11 standard and pre-standard templates
 	// gnuc 4.8 is using a mix of C++11 standard and pre-standard templates
 	bool hasConstructor        = std::is_default_constructible<T>::value && !std::has_trivial_default_constructor<T>::value;
 	bool hasConstructor        = std::is_default_constructible<T>::value && !std::has_trivial_default_constructor<T>::value;
 	bool hasDestructor         = std::is_destructible<T>::value          && !std::is_trivially_destructible<T>::value;
 	bool hasDestructor         = std::is_destructible<T>::value          && !std::is_trivially_destructible<T>::value;