From 73d28d2177a8b014f8807a61d14d3064c5d5c033 Mon Sep 17 00:00:00 2001
From: "Daniele E. Domenichelli" <daniele.domenichelli@iit.it>
Date: Fri, 20 Sep 2013 15:10:40 +0200
Subject: CheckStructHasMember: Add support for C++

Previously if headers required to check if a struct has a member can be
compiled with C++ compiler only, the check would fail because the C
compiler fails.  As a consequence, the result variable would be set to
false, even if the struct has that particular member.

Teach CHECK_STRUCT_HAS_MEMBER to accept a new optional argument LANGUAGE
that allows one to explicitly set the compiler to use.  The new
signature is therefore:

  CHECK_STRUCT_HAS_MEMBER (<struct> <member> <header> <variable>
                           [LANGUAGE <language>])
---
 Modules/CheckStructHasMember.cmake                 | 35 +++++---
 Tests/CMakeOnly/CMakeLists.txt                     |  2 +
 .../CMakeOnly/CheckStructHasMember/CMakeLists.txt  | 93 ++++++++++++++++++++++
 Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h     |  9 +++
 Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx   | 16 ++++
 Tests/RunCMake/CMakeLists.txt                      |  1 +
 Tests/RunCMake/CheckModules/CMakeLists.txt         |  3 +
 .../CheckStructHasMemberMissingKey-result.txt      |  1 +
 .../CheckStructHasMemberMissingKey-stderr.txt      |  8 ++
 .../CheckStructHasMemberMissingKey.cmake           |  2 +
 .../CheckStructHasMemberMissingLanguage-result.txt |  1 +
 .../CheckStructHasMemberMissingLanguage-stderr.txt |  8 ++
 .../CheckStructHasMemberMissingLanguage.cmake      |  2 +
 .../CheckModules/CheckStructHasMemberOk.cmake      |  4 +
 ...CheckStructHasMemberTooManyArguments-result.txt |  1 +
 ...CheckStructHasMemberTooManyArguments-stderr.txt |  8 ++
 .../CheckStructHasMemberTooManyArguments.cmake     |  2 +
 .../CheckStructHasMemberUnknownLanguage-result.txt |  1 +
 .../CheckStructHasMemberUnknownLanguage-stderr.txt | 10 +++
 .../CheckStructHasMemberUnknownLanguage.cmake      |  2 +
 .../CheckStructHasMemberWrongKey-result.txt        |  1 +
 .../CheckStructHasMemberWrongKey-stderr.txt        |  8 ++
 .../CheckStructHasMemberWrongKey.cmake             |  2 +
 Tests/RunCMake/CheckModules/RunCMakeTest.cmake     |  8 ++
 24 files changed, 219 insertions(+), 9 deletions(-)
 create mode 100644 Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt
 create mode 100644 Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h
 create mode 100644 Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx
 create mode 100644 Tests/RunCMake/CheckModules/CMakeLists.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt
 create mode 100644 Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake
 create mode 100644 Tests/RunCMake/CheckModules/RunCMakeTest.cmake

diff --git a/Modules/CheckStructHasMember.cmake b/Modules/CheckStructHasMember.cmake
index ea2891c..d28cc2a 100644
--- a/Modules/CheckStructHasMember.cmake
+++ b/Modules/CheckStructHasMember.cmake
@@ -1,10 +1,12 @@
 # - Check if the given struct or class has the specified member variable
-# CHECK_STRUCT_HAS_MEMBER (STRUCT MEMBER HEADER VARIABLE)
+# CHECK_STRUCT_HAS_MEMBER (<struct> <member> <header> <variable>
+#                          [LANGUAGE <language>])
 #
-#  STRUCT - the name of the struct or class you are interested in
-#  MEMBER - the member which existence you want to check
-#  HEADER - the header(s) where the prototype should be declared
-#  VARIABLE - variable to store the result
+#  <struct> - the name of the struct or class you are interested in
+#  <member> - the member which existence you want to check
+#  <header> - the header(s) where the prototype should be declared
+#  <variable> - variable to store the result
+#  <language> - the compiler to use (C or CXX)
 #
 # The following variables may be set before calling this macro to
 # modify the way the check is run:
@@ -12,8 +14,9 @@
 #  CMAKE_REQUIRED_FLAGS = string of compile command line flags
 #  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
 #  CMAKE_REQUIRED_INCLUDES = list of include directories
+#  CMAKE_REQUIRED_LIBRARIES = list of libraries to link
 #
-# Example: CHECK_STRUCT_HAS_MEMBER("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC)
+# Example: CHECK_STRUCT_HAS_MEMBER("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC LANGUAGE C)
 
 #=============================================================================
 # Copyright 2007-2009 Kitware, Inc.
@@ -29,6 +32,7 @@
 #  License text for the above reference.)
 
 include(CheckCSourceCompiles)
+include(CheckCXXSourceCompiles)
 
 macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
    set(_INCLUDE_FILES)
@@ -36,16 +40,29 @@ macro (CHECK_STRUCT_HAS_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
       set(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
    endforeach ()
 
+   if("x${ARGN}" STREQUAL "x")
+      set(_lang C)
+   elseif("x${ARGN}" MATCHES "^xLANGUAGE;([a-zA-Z]+)$")
+      set(_lang "${CMAKE_MATCH_1}")
+   else()
+      message(FATAL_ERROR "Unknown arguments:\n  ${ARGN}\n")
+   endif()
+
    set(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
 ${_INCLUDE_FILES}
 int main()
 {
    ${_STRUCT}* tmp;
    tmp->${_MEMBER};
-  return 0;
+   return 0;
 }
 ")
-   CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
 
+   if("${_lang}" STREQUAL "C")
+      CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
+   elseif("${_lang}" STREQUAL "CXX")
+      CHECK_CXX_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
+   else()
+      message(FATAL_ERROR "Unknown language:\n  ${_lang}\nSupported languages: C, CXX.\n")
+   endif()
 endmacro ()
-
diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt
index be7ddbc..7586de6 100644
--- a/Tests/CMakeOnly/CMakeLists.txt
+++ b/Tests/CMakeOnly/CMakeLists.txt
@@ -19,6 +19,8 @@ add_CMakeOnly_test(CheckCXXCompilerFlag)
 
 add_CMakeOnly_test(CheckLanguage)
 
+add_CMakeOnly_test(CheckStructHasMember)
+
 add_CMakeOnly_test(CompilerIdC)
 add_CMakeOnly_test(CompilerIdCXX)
 if(CMAKE_Fortran_COMPILER)
diff --git a/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt b/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt
new file mode 100644
index 0000000..f06d5c3
--- /dev/null
+++ b/Tests/CMakeOnly/CheckStructHasMember/CMakeLists.txt
@@ -0,0 +1,93 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(CheckStructHasMember)
+
+set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}")
+
+include(CheckStructHasMember)
+
+foreach(_config_type Release RelWithDebInfo MinSizeRel Debug)
+    set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type})
+    unset(CSHM_RESULT_S1_${_config_type} CACHE)
+    unset(CSHM_RESULT_S2_${_config_type} CACHE)
+    unset(CSHM_RESULT_S3_${_config_type} CACHE)
+    message(STATUS "Testing configuration ${_config_type}")
+
+    check_struct_has_member("struct non_existent_struct" "foo" "cm_cshm.h" CSHM_RESULT_S1_${_config_type})
+    check_struct_has_member("struct struct_with_member" "non_existent_member" "cm_cshm.h" CSHM_RESULT_S2_${_config_type})
+    check_struct_has_member("struct struct_with_member" "member" "cm_cshm.h" CSHM_RESULT_S3_${_config_type})
+
+    if(CSHM_RESULT_S1_${_config_type} OR CSHM_RESULT_S2_${_config_type})
+        message(SEND_ERROR "CheckStructHasMember reported a nonexistent member as existing in configuration ${_config_type}")
+    endif()
+
+    if(NOT CSHM_RESULT_S3_${_config_type})
+        message(SEND_ERROR "CheckStructHasMember did not report an existent member as existing in configuration ${_config_type}")
+    endif()
+endforeach()
+
+foreach(_config_type Release RelWithDebInfo MinSizeRel Debug)
+    set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type})
+    unset(CSHM_RESULT_S1_${_config_type}_C CACHE)
+    unset(CSHM_RESULT_S2_${_config_type}_C CACHE)
+    unset(CSHM_RESULT_S3_${_config_type}_C CACHE)
+    message(STATUS "Testing configuration ${_config_type}")
+
+    check_struct_has_member("struct non_existent_struct" "foo" "cm_cshm.h" CSHM_RESULT_S1_${_config_type}_C LANGUAGE C)
+    check_struct_has_member("struct struct_with_member" "non_existent_member" "cm_cshm.h" CSHM_RESULT_S2_${_config_type}_C LANGUAGE C)
+    check_struct_has_member("struct struct_with_member" "member" "cm_cshm.h" CSHM_RESULT_S3_${_config_type}_C LANGUAGE C)
+
+    if(CSHM_RESULT_S1_${_config_type}_C OR CSHM_RESULT_S2_${_config_type}_C)
+        message(SEND_ERROR "CheckStructHasMember reported a nonexistent member as existing in configuration ${_config_type}")
+    endif()
+
+    if(NOT CSHM_RESULT_S3_${_config_type}_C)
+        message(SEND_ERROR "CheckStructHasMember did not report an existent member as existing in configuration ${_config_type}")
+    endif()
+endforeach()
+
+foreach(_config_type Release RelWithDebInfo MinSizeRel Debug)
+    set(CMAKE_TRY_COMPILE_CONFIGURATION ${_config_type})
+    unset(CSHM_RESULT_S1_${_config_type}_CXX CACHE)
+    unset(CSHM_RESULT_S2_${_config_type}_CXX CACHE)
+    unset(CSHM_RESULT_S3_${_config_type}_CXX CACHE)
+    unset(CSHM_RESULT_C1_${_config_type}_CXX CACHE)
+    unset(CSHM_RESULT_C2_${_config_type}_CXX CACHE)
+    unset(CSHM_RESULT_C3_${_config_type}_CXX CACHE)
+
+    message(STATUS "Testing configuration ${_config_type}")
+
+    check_struct_has_member("non_existent_struct" "foo" "cm_cshm.h" CSHM_RESULT_S1_${_config_type}_CXX LANGUAGE CXX)
+    check_struct_has_member("struct_with_non_existent_members" "non_existent_member" "cm_cshm.h" CSHM_RESULT_S2_${_config_type}_CXX LANGUAGE CXX)
+    check_struct_has_member("struct struct_with_member" "member" "cm_cshm.h" CSHM_RESULT_S3_${_config_type}_CXX LANGUAGE CXX)
+    check_struct_has_member("ns::non_existent_class" "foo" "cm_cshm.hxx" CSHM_RESULT_C1_${_config_type}_CXX LANGUAGE CXX)
+    check_struct_has_member("ns::class_with_non_existent_members" "foo" "cm_cshm.hxx" CSHM_RESULT_C2_${_config_type}_CXX LANGUAGE CXX)
+    check_struct_has_member("ns::class_with_member" "foo" "cm_cshm.hxx" CSHM_RESULT_C3_${_config_type}_CXX LANGUAGE CXX)
+
+    if(CSHM_RESULT_S1_${_config_type}_CXX OR CSHM_RESULT_S2_${_config_type}_CXX OR CSHM_RESULT_C1_${_config_type}_CXX OR CSHM_RESULT_C2_${_config_type}_CXX)
+        message(SEND_ERROR "CheckStructHasMember reported a nonexistent member as existing in configuration ${_config_type}")
+    endif()
+
+    if(NOT CSHM_RESULT_S3_${_config_type}_CXX OR NOT CSHM_RESULT_C3_${_config_type}_CXX)
+        message(SEND_ERROR "CheckStructHasMember did not report an existent member as existing in configuration ${_config_type}")
+    endif()
+endforeach()
+
+
+set(CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
+
+if (CMAKE_COMPILER_IS_GNUCC)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
+    unset(CSHM_RESULT_O3 CACHE)
+    unset(CSHM_RESULT_O3_C CACHE)
+    unset(CSHM_RESULT_O3_CXX CACHE)
+    message(STATUS "Testing with optimization -O3")
+
+    check_struct_has_member("class_with_non_existent_members" foo "cm_cshm.h" CSHM_RESULT_O3)
+    check_struct_has_member("class_with_non_existent_members" foo "cm_cshm.h" CSHM_RESULT_O3_C LANGUAGE C)
+    check_struct_has_member("class_with_non_existent_members" foo "cm_cshm.h" CSHM_RESULT_O3_CXX LANGUAGE CXX)
+
+  if (CSE_RESULT_O3 OR CSHM_RESULT_O3_C OR CSHM_RESULT_O3_CXX)
+    message(SEND_ERROR "CheckSymbolExists reported a nonexistent symbol as existing with optimization -O3")
+  endif ()
+endif ()
diff --git a/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h
new file mode 100644
index 0000000..82bb049
--- /dev/null
+++ b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.h
@@ -0,0 +1,9 @@
+#ifndef _CSHM_DUMMY_H
+#define _CSHM_DUMMY_H
+
+struct non_existent_struct;
+struct struct_with_member{
+    int member;
+};
+
+#endif
diff --git a/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx
new file mode 100644
index 0000000..458a99b
--- /dev/null
+++ b/Tests/CMakeOnly/CheckStructHasMember/cm_cshm.hxx
@@ -0,0 +1,16 @@
+#ifndef _CSHM_DUMMY_HXX
+#define _CSHM_DUMMY_HXX
+
+namespace ns {
+
+class non_existent_class;
+class class_with_non_existent_members {
+};
+class class_with_member {
+public:
+    int foo;
+};
+
+}
+
+#endif
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index e45aba3..35c8e13 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -119,3 +119,4 @@ endif()
 add_RunCMake_test(File_Generate)
 add_RunCMake_test(ExportWithoutLanguage)
 add_RunCMake_test(target_link_libraries)
+add_RunCMake_test(CheckModules)
diff --git a/Tests/RunCMake/CheckModules/CMakeLists.txt b/Tests/RunCMake/CheckModules/CMakeLists.txt
new file mode 100644
index 0000000..65ac8e8
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.11)
+project(${RunCMake_TEST})
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt
new file mode 100644
index 0000000..1b8603a
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\):
+  Unknown arguments:
+
+    C
+
+Call Stack \(most recent call first\):
+  CheckStructHasMemberMissingKey.cmake:[0-9]+ \(check_struct_has_member\)
+  CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake
new file mode 100644
index 0000000..49f51ce
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingKey.cmake
@@ -0,0 +1,2 @@
+include(CheckStructHasMember)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K C)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt
new file mode 100644
index 0000000..8fceab0
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\):
+  Unknown arguments:
+
+    LANGUAGE
+
+Call Stack \(most recent call first\):
+  CheckStructHasMemberMissingLanguage.cmake:[0-9]+ \(check_struct_has_member\)
+  CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake
new file mode 100644
index 0000000..b404d66
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberMissingLanguage.cmake
@@ -0,0 +1,2 @@
+include(CheckStructHasMember)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake
new file mode 100644
index 0000000..b319e18
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberOk.cmake
@@ -0,0 +1,4 @@
+include(CheckStructHasMember)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_C LANGUAGE C)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_CXX LANGUAGE CXX)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt
new file mode 100644
index 0000000..4598867
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\):
+  Unknown arguments:
+
+    LANGUAGE;C;CXX
+
+Call Stack \(most recent call first\):
+  CheckStructHasMemberTooManyArguments.cmake:[0-9]+ \(check_struct_has_member\)
+  CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake
new file mode 100644
index 0000000..12f8158
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberTooManyArguments.cmake
@@ -0,0 +1,2 @@
+include(CheckStructHasMember)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE C CXX)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt
new file mode 100644
index 0000000..ba9e313
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\):
+  Unknown language:
+
+    FORTRAN
+
+  Supported languages: C, CXX.
+
+Call Stack \(most recent call first\):
+  CheckStructHasMemberUnknownLanguage.cmake:[0-9]+ \(check_struct_has_member\)
+  CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake
new file mode 100644
index 0000000..183058d
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberUnknownLanguage.cmake
@@ -0,0 +1,2 @@
+include(CheckStructHasMember)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAGE FORTRAN)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt
new file mode 100644
index 0000000..b9fbd38
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\):
+  Unknown arguments:
+
+    LANGUAG;C
+
+Call Stack \(most recent call first\):
+  CheckStructHasMemberWrongKey.cmake:[0-9]+ \(check_struct_has_member\)
+  CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake
new file mode 100644
index 0000000..900eb0a
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake
@@ -0,0 +1,2 @@
+include(CheckStructHasMember)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAG C)
diff --git a/Tests/RunCMake/CheckModules/RunCMakeTest.cmake b/Tests/RunCMake/CheckModules/RunCMakeTest.cmake
new file mode 100644
index 0000000..6a6b36e
--- /dev/null
+++ b/Tests/RunCMake/CheckModules/RunCMakeTest.cmake
@@ -0,0 +1,8 @@
+include(RunCMake)
+
+run_cmake(CheckStructHasMemberOk)
+run_cmake(CheckStructHasMemberUnknownLanguage)
+run_cmake(CheckStructHasMemberMissingLanguage)
+run_cmake(CheckStructHasMemberMissingKey)
+run_cmake(CheckStructHasMemberTooManyArguments)
+run_cmake(CheckStructHasMemberWrongKey)
-- 
cgit v0.12