[AIX] Fix libc++ Symbol Visibility on AIX
authorMichael Francis <michaelfrancis@ibm.com>
Sat, 24 Dec 2022 20:45:26 +0000 (20:45 +0000)
committerMichael Francis <michaelfrancis@ibm.com>
Wed, 8 Mar 2023 18:58:55 +0000 (18:58 +0000)
The AIX linker does not support linking against libc++ if it exports symbols are redefined within compiled code.

Differential Revision: https://reviews.llvm.org/D140675

libcxx/include/__config
libcxx/test/libcxx/vendor/ibm/bad_function_call.pass.cpp [new file with mode: 0644]

index d3063f0..272ed28 100644 (file)
 #    if defined(__FreeBSD__)
 #      define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
 #    endif
+// For XCOFF linkers, we have problems if we see a weak hidden version of a symbol
+// in user code (like you get with -fvisibility-inlines-hidden) and then a strong def
+// in the library, so we need to always rely on the library version.
+#    if defined(_AIX)
+#      define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION
+#    endif
 #  endif
 
 #  if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2
diff --git a/libcxx/test/libcxx/vendor/ibm/bad_function_call.pass.cpp b/libcxx/test/libcxx/vendor/ibm/bad_function_call.pass.cpp
new file mode 100644 (file)
index 0000000..2b68446
--- /dev/null
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: target={{powerpc.*-ibm-aix.*}}
+// ADDITIONAL_COMPILE_FLAGS: -fvisibility-inlines-hidden
+
+// When there is a weak hidden symbol in user code and a strong definition
+// in the library, we test that the linker relies on the library version,
+// as the default weak resolution semantics don't favour weak local definitions
+// for XCOFF. This creates a conflict on std::bad_function_call, which is used
+// by the std::function template instantiated in main.
+#include <functional>
+#include "test_macros.h"
+#include "assert.h"
+
+void foo() {}
+
+void test_call() {
+  std::function<void()> r(foo);
+  r();
+}
+
+void test_throw() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  std::function<int()> f;
+  try {
+    f();
+    assert(false);
+  } catch (const std::bad_function_call&) {
+    return;
+  }
+  assert(false);
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+  test_call();
+  test_throw();
+  return 0;
+}