Skip to content

Commit efa3139

Browse files
authored
Merge pull request #27170 from mikeash/the-missing-link
[Compatibility50] Look up swift_getObjCClassMetadata at runtime.
2 parents 0822ce5 + c9f9350 commit efa3139

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

stdlib/toolchain/Compatibility50/ProtocolConformance.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "Overrides.h"
2121
#include "../../public/runtime/Private.h"
2222
#include "swift/Basic/Lazy.h"
23+
#include <dlfcn.h>
2324
#include <mach-o/dyld.h>
2425
#include <mach-o/getsect.h>
2526
#include <objc/runtime.h>
@@ -89,13 +90,25 @@ static void registerAddImageCallback(void *) {
8990
_dyld_register_func_for_add_image(addImageCallback);
9091
}
9192

93+
static const Metadata *getObjCClassMetadata(const ClassMetadata *c) {
94+
// Look up swift_getObjCClassMetadata dynamically. This handles the case
95+
// where the main executable can't link against libswiftCore.dylib because
96+
// it will be loaded dynamically from a location that isn't known at build
97+
// time.
98+
using FPtr = const Metadata *(*)(const ClassMetadata *);
99+
FPtr func = SWIFT_LAZY_CONSTANT(
100+
reinterpret_cast<FPtr>(dlsym(RTLD_DEFAULT, "swift_getObjCClassMetadata")));
101+
102+
return func(c);
103+
}
104+
92105
// Clone of private helper swift::_swiftoverride_class_getSuperclass
93106
// for use in the override implementation.
94107
static const Metadata *_swift50override_class_getSuperclass(
95108
const Metadata *theClass) {
96109
if (const ClassMetadata *classType = theClass->getClassObject()) {
97110
if (classHasSuperclass(classType))
98-
return getMetadataForClass(classType->Superclass);
111+
return getObjCClassMetadata(classType->Superclass);
99112
}
100113

101114
if (const ForeignClassMetadata *foreignClassType

test/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ foreach(SDK ${SWIFT_SDKS})
205205

206206
# NOTE create a stub BlocksRuntime library that can be used for the
207207
# reflection tests
208-
file(WRITE ${test_bin_dir}/BlocksRuntime.c
208+
file(WRITE ${test_bin_dir}/Inputs/BlocksRuntime.c
209209
"void
210210
#if defined(_WIN32)
211211
__declspec(dllexport)
@@ -220,7 +220,7 @@ _Block_release(void) { }\n")
220220
ARCHITECTURE ${ARCH}
221221
SDK ${SDK}
222222
INSTALL_IN_COMPONENT dev
223-
${test_bin_dir}/BlocksRuntime.c)
223+
${test_bin_dir}/Inputs/BlocksRuntime.c)
224224
set_target_properties(BlocksRuntimeStub${VARIANT_SUFFIX} PROPERTIES
225225
ARCHIVE_OUTPUT_DIRECTORY ${test_bin_dir}
226226
LIBRARY_OUTPUT_DIRECTORY ${test_bin_dir}

test/lit.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ config.test_format = swift_test.SwiftTest(coverage_mode=config.coverage_mode,
178178
execute_external=not use_lit_shell)
179179

180180
# suffixes: A list of file extensions to treat as test files.
181-
config.suffixes = ['.swift', '.ll', '.sil', '.gyb', '.m', '.swiftinterface',
182-
'.test-sh']
181+
config.suffixes = ['.swift', '.ll', '.sil', '.gyb', '.m', '.c',
182+
'.swiftinterface', '.test-sh']
183183

184184
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
185185
# subdirectories contain auxiliary inputs for various tests in their parent

test/stdlib/Compatibility50Linking.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-clang %s -all_load %test-resource-dir/%target-sdk-name/libswiftCompatibility50.a -lobjc -o %t/main
3+
// RUN: %target-run %t/main
4+
// REQUIRES: objc_interop
5+
// REQUIRES: executable_test
6+
7+
// The compatibility library needs to have no build-time dependencies on
8+
// libswiftCore so it can be linked into a program that doesn't link
9+
// libswiftCore, but will load it at runtime, such as xctest.
10+
//
11+
// Test this by linking it into a plain C program and making sure it builds.
12+
13+
int main(void) {}

0 commit comments

Comments
 (0)