diff --git a/CMakeLists.txt b/CMakeLists.txt
index 732f70f863..14e490bb85 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
# Outcome cmake
-# (C) 2016-2023 Niall Douglas
+# (C) 2016-2024 Niall Douglas
# File Created: June 2016
#
#
@@ -184,7 +184,7 @@ endif()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (NOT DEFINED BUILD_TESTING OR BUILD_TESTING))
# For all possible configurations of this library, add each test
- list_filter(outcome_TESTS EXCLUDE REGEX "constexprs")
+ list_filter(outcome_TESTS EXCLUDE REGEX "constexprs|link")
set(outcome_TESTS_DISABLE_PRECOMPILE_HEADERS
"outcome_hl--coroutine-support"
"outcome_hl--core-result"
@@ -359,9 +359,12 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (
endforeach()
endif()
+# Add in link tests
+add_subdirectory("test/link")
+
# Turn on pedantic warnings for all tests, examples and snippets
if(NOT MSVC)
- foreach(target ${outcome_TEST_TARGETS} ${outcome_EXAMPLE_TARGETS} ${example_bins})
+ foreach(target ${outcome_TEST_TARGETS} ${outcome_EXAMPLE_TARGETS} ${outcome_LINK_TARGETS} ${example_bins})
target_compile_options(${target} PUBLIC "-Wpedantic")
endforeach()
endif()
diff --git a/include/outcome/detail/revision.hpp b/include/outcome/detail/revision.hpp
index 982e095bb8..24a7d6ee3f 100644
--- a/include/outcome/detail/revision.hpp
+++ b/include/outcome/detail/revision.hpp
@@ -22,6 +22,6 @@ Distributed under the Boost Software License, Version 1.0.
*/
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define OUTCOME_PREVIOUS_COMMIT_REF 36beb5b34b24cf25d93ac421370ef5578f2f65ed
-#define OUTCOME_PREVIOUS_COMMIT_DATE "2024-09-04 13:14:36 +00:00"
-#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 36beb5b3
+#define OUTCOME_PREVIOUS_COMMIT_REF 2a8ff2b0ca37e4627b0d9919b653fee7d4cc6968
+#define OUTCOME_PREVIOUS_COMMIT_DATE "2024-09-04 14:48:43 +00:00"
+#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 2a8ff2b0
diff --git a/test/link/CMakeLists.txt b/test/link/CMakeLists.txt
new file mode 100644
index 0000000000..c0e822cb40
--- /dev/null
+++ b/test/link/CMakeLists.txt
@@ -0,0 +1,62 @@
+# Outcome cmake
+# (C) 2016-2024 Niall Douglas
+# File Created: June 2016
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License in the accompanying file
+# Licence.txt or at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file Licence.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
+
+set(outcome_LINK_TARGETS)
+foreach(type STATIC SHARED)
+ foreach(visibility default hidden)
+ set(target outcome-link-test-experimental-c-result-type_${type}-vis_${visibility})
+ add_library(${target}-lib ${type}
+ "experimental-c-result/lib.c"
+ "experimental-c-result/lib.cpp")
+ target_compile_definitions(${target}-lib PRIVATE MYLIB_SOURCE=1)
+ set_target_properties(${target}-lib PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+ POSITION_INDEPENDENT_CODE ON
+ C_VISIBILITY_PRESET "${visibility}"
+ CXX_VISIBILITY_PRESET "${visibility}"
+ DISABLE_PRECOMPILE_HEADERS On
+ )
+ target_link_libraries(${target}-lib PRIVATE outcome::hl)
+ list(APPEND outcome_LINK_TARGETS ${target}-lib)
+
+ add_executable(${target} "experimental-c-result/main.c")
+ set_target_properties(${target} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+ POSITION_INDEPENDENT_CODE ON
+ C_VISIBILITY_PRESET "${visibility}"
+ CXX_VISIBILITY_PRESET "${visibility}"
+ DISABLE_PRECOMPILE_HEADERS On
+ )
+ target_link_libraries(${target} PRIVATE ${target}-lib outcome::hl)
+ if(target MATCHES ".*-type_SHARED-vis_hidden")
+ # The shared library won't export the C++ helper machinery if visibility is hidden,
+ # so without including a copy of the C++ helpers it would correctly fail to link.
+ add_library(${target}-cxx-helpers OBJECT "experimental-c-result/lib.cpp")
+ target_link_libraries(${target}-cxx-helpers PRIVATE outcome::hl)
+ target_link_libraries(${target} PRIVATE ${target}-cxx-helpers)
+ endif()
+ list(APPEND outcome_LINK_TARGETS ${target})
+ endforeach()
+endforeach()
diff --git a/test/link/experimental-c-result/lib.c b/test/link/experimental-c-result/lib.c
new file mode 100644
index 0000000000..e0900a159c
--- /dev/null
+++ b/test/link/experimental-c-result/lib.c
@@ -0,0 +1,35 @@
+/* Link testing for outcomes
+(C) 2024 Niall Douglas (6 commits)
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "lib.h"
+
+#include
+
+mylib_result test_function(int x)
+{
+ if(x < 0)
+ {
+ return make_failure_result(EINVAL);
+ }
+ return make_success_result(x);
+}
diff --git a/test/link/experimental-c-result/lib.cpp b/test/link/experimental-c-result/lib.cpp
new file mode 100644
index 0000000000..4aa487f9e6
--- /dev/null
+++ b/test/link/experimental-c-result/lib.cpp
@@ -0,0 +1,26 @@
+/* Link testing for outcomes
+(C) 2024 Niall Douglas (6 commits)
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+// This should be all that is necessary to create the C++ runtime
+// side of things for the C code
+#include "lib.h" // NOLINT
diff --git a/test/link/experimental-c-result/lib.h b/test/link/experimental-c-result/lib.h
new file mode 100644
index 0000000000..31e14e368f
--- /dev/null
+++ b/test/link/experimental-c-result/lib.h
@@ -0,0 +1,75 @@
+/* Link testing for outcomes
+(C) 2024 Niall Douglas (6 commits)
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef OUTCOME_TEST_LINK_EXPERIMENTAL_C_RESULT_H
+#define OUTCOME_TEST_LINK_EXPERIMENTAL_C_RESULT_H
+
+#include
+
+#if MYLIB_SOURCE
+#ifdef _MSC_VER
+#define MYLIB_DECL __declspec(dllexport)
+#else
+#define MYLIB_DECL __attribute__((visibility("default")))
+#endif
+#else
+#define MYLIB_DECL
+#endif
+
+CXX_DECLARE_RESULT_SYSTEM(mylib, intptr_t);
+
+typedef CXX_RESULT_SYSTEM(mylib) mylib_result;
+
+static int is_result_ok(mylib_result r)
+{
+ return CXX_RESULT_HAS_VALUE(r);
+}
+
+static int is_result_failed(mylib_result r)
+{
+ return CXX_RESULT_HAS_ERROR(r);
+}
+
+static mylib_result make_success_result(intptr_t v)
+{
+ return CXX_MAKE_RESULT_SYSTEM_SUCCESS(mylib, v);
+}
+
+static mylib_result make_failure_result(int v)
+{
+ return CXX_MAKE_RESULT_SYSTEM_FAILURE_SYSTEM(mylib, v);
+}
+
+static int is_result_equivalent(mylib_result r, int errcode)
+{
+ return outcome_status_code_equal_generic(&r, errcode);
+}
+
+static const char *result_failure_message(mylib_result r)
+{
+ return outcome_status_code_message(&r);
+}
+
+extern MYLIB_DECL mylib_result test_function(int x);
+
+#endif
diff --git a/test/link/experimental-c-result/main.c b/test/link/experimental-c-result/main.c
new file mode 100644
index 0000000000..8115e8bd25
--- /dev/null
+++ b/test/link/experimental-c-result/main.c
@@ -0,0 +1,57 @@
+/* Link testing for outcomes
+(C) 2024 Niall Douglas (6 commits)
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "lib.h"
+
+#include
+#include
+#include
+#include
+
+int main(void)
+{
+ mylib_result r = test_function(5);
+ if(is_result_failed(r))
+ {
+ fprintf(stderr, "FATAL: test_function(5) failed with '%s'\n", result_failure_message(r));
+ abort();
+ }
+ if(r.value != 5)
+ {
+ fprintf(stderr, "FATAL: test_function(5) did not return 5\n");
+ abort();
+ }
+ r = test_function(-5);
+ if(!is_result_failed(r))
+ {
+ fprintf(stderr, "FATAL: test_function(-5) did not fail\n");
+ abort();
+ }
+ const char *msg = result_failure_message(r);
+ printf("test_function(-5) should fail with 'Invalid argument'\nIt failed with '%s'\n", msg);
+ if(0 != strcmp(msg, "Invalid argument"))
+ {
+ abort();
+ }
+ return 0;
+}
\ No newline at end of file