Skip to content

Commit dbdd983

Browse files
author
Gabor Horvath
committed
[cxx-interop] Fix generated declaration order
The generated thunks for functions can refer to some internal methods of their arguments. As a result, those generated thunks should always be after the definitions of the corresponding argument types. The printer ordered the declarations by name, and Swift had the convention starting types with upper case letters and functions with lower case letters. This naming convention together with the ordering resulted in the correct ordering in most of the cases. There were a couple of exceptions when people diverged from the naming conventions or wanted to export operators. This patch fixes this problem by always ordering type decls before function decls. rdar://129276354
1 parent 85c0555 commit dbdd983

File tree

3 files changed

+17
-9
lines changed

3 files changed

+17
-9
lines changed

lib/PrintAsClang/ModuleContentsWriter.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "PrintSwiftToClangCoreScaffold.h"
2121
#include "SwiftToClangInteropContext.h"
2222

23+
#include "swift/AST/Decl.h"
2324
#include "swift/AST/DiagnosticsSema.h"
2425
#include "swift/AST/ExistentialLayout.h"
2526
#include "swift/AST/Module.h"
@@ -671,6 +672,15 @@ class ModuleWriter {
671672
llvm_unreachable("unknown top-level ObjC decl");
672673
};
673674

675+
// When we visit a function, we might also generate a thunk that calls into the
676+
// implementation of structs/enums to get the opaque pointers. To avoid
677+
// referencing these methods before we see the definition for the generated
678+
// classes, we want to visit function definitions last.
679+
if (isa<AbstractFunctionDecl>(*rhs) && isa<NominalTypeDecl>(*lhs))
680+
return Descending;
681+
if (isa<AbstractFunctionDecl>(*lhs) && isa<NominalTypeDecl>(*rhs))
682+
return Ascending;
683+
674684
// Sort by names.
675685
int result = getSortName(*rhs).compare(getSortName(*lhs));
676686
if (result != 0)
@@ -700,9 +710,9 @@ class ModuleWriter {
700710
// even when the variable might not actually be emitted by the emitter.
701711
// In that case, order the function before the variable.
702712
if (isa<AbstractFunctionDecl>(*rhs) && isa<VarDecl>(*lhs))
703-
return 1;
713+
return Descending;
704714
if (isa<AbstractFunctionDecl>(*lhs) && isa<VarDecl>(*rhs))
705-
return -1;
715+
return Ascending;
706716

707717
// Prefer value decls to extensions.
708718
assert(!(isa<ValueDecl>(*lhs) && isa<ValueDecl>(*rhs)));

test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ public final class ClassWithIntField {
102102
// CHECK-EMPTY:
103103
// CHECK-NEXT: namespace Class SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Class") {
104104

105-
// CHECK: SWIFT_INLINE_THUNK ClassWithIntField passThroughClassWithIntField(const ClassWithIntField& x) noexcept SWIFT_SYMBOL("s:5Class011passThroughA12WithIntFieldyAA0adeF0CADF") SWIFT_WARN_UNUSED_RESULT {
106-
// CHECK-NEXT: return _impl::_impl_ClassWithIntField::makeRetained(_impl::$s5Class011passThroughA12WithIntFieldyAA0adeF0CADF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(x)));
107-
// CHECK-NEXT: }
108-
109105
public final class register { }
110106

111107
// CHECK: class SWIFT_SYMBOL("s:5Class8registerC") register_ final : public swift::_impl::RefCountedClass {
112108

109+
// CHECK: SWIFT_INLINE_THUNK ClassWithIntField passThroughClassWithIntField(const ClassWithIntField& x) noexcept SWIFT_SYMBOL("s:5Class011passThroughA12WithIntFieldyAA0adeF0CADF") SWIFT_WARN_UNUSED_RESULT {
110+
// CHECK-NEXT: return _impl::_impl_ClassWithIntField::makeRetained(_impl::$s5Class011passThroughA12WithIntFieldyAA0adeF0CADF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(x)));
111+
// CHECK-NEXT: }
112+
113113
public func returnClassWithIntField() -> ClassWithIntField {
114114
return ClassWithIntField()
115115
}

test/Interop/SwiftToCxx/functions/swift-operators.swift

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// RUN: %target-swift-frontend %s -typecheck -module-name Operators -clang-header-expose-decls=all-public -emit-clang-header-path %t/operators.h
33
// RUN: %FileCheck %s < %t/operators.h
44

5-
// TODO: %check-interop-cxx-header-in-clang(%t/operators.h)
6-
// unfortunately the header still triggers an error:
7-
// error: no member named '_impl_IntBox' in namespace 'Operators::_impl'
5+
// RUN: %check-interop-cxx-header-in-clang(%t/operators.h)
86

97
// CHECK-LABEL: namespace Operators SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Operators") {
108

0 commit comments

Comments
 (0)