mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
PrintAsClang is supposed to emit declarations in the same order regardless of the compiler’s internal state, but we have repeatedly found that our current criteria are inadequate, resulting in non-functionality-affecting changes to generated header content. Add a diagnostic that’s emitted when this happens soliciting a bug report. Since there *should* be no cases where the compiler fails to order declarations, this diagnostic is never actually emitted. Instead, we test this change by enabling `-verify` on nearly all PrintAsClang tests to make sure they are unaffected. This did demonstrate a missing criterion that only mattered in C++ mode: extensions that varied only in their generic signature were not sorted stably. Add a sort criterion for this.
248 lines
13 KiB
Swift
248 lines
13 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-swift-frontend %s -module-name Functions -clang-header-expose-decls=all-public -typecheck -verify -emit-clang-header-path %t/functions.h
|
|
// RUN: %FileCheck %s < %t/functions.h
|
|
|
|
// RUN: %check-interop-cxx-header-in-clang(%t/functions.h -Wno-unused-function -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY)
|
|
|
|
// RUN: %target-swift-frontend %s -module-name Functions -enable-library-evolution -clang-header-expose-decls=all-public -typecheck -verify -emit-clang-header-path %t/functions-evo.h
|
|
// RUN: %FileCheck %s < %t/functions-evo.h
|
|
|
|
// RUN: %check-interop-cxx-header-in-clang(%t/functions-evo.h -Wno-unused-function -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY)
|
|
|
|
public func genericPrintFunctionTwoArg<T>(_ x: T, _ y: Int) {
|
|
print("X:", x)
|
|
print("Y:", y)
|
|
}
|
|
|
|
public func genericPrintFunction<T>(_ x: T) {
|
|
print("\(T.self) value=\(x)")
|
|
}
|
|
|
|
public func genericPrintFunctionMultiGeneric<T1, T2>(_ x: Int, _ t1: T1, _ t1p: T1, _ y: Int, _ t2: T2) {
|
|
print("\(T1.self) value 1=\(t1)")
|
|
print("\(T1.self) value 2=\(t1p)")
|
|
print("\(T2.self) value 1=\(t2)")
|
|
print("other values=\(x),\(y)")
|
|
}
|
|
|
|
public func genericSwap<T>(_ x: inout T, _ y: inout T) {
|
|
let t = x
|
|
x = y
|
|
y = t
|
|
}
|
|
|
|
public func genericRet<T>(_ x: T) -> T {
|
|
return x
|
|
}
|
|
|
|
public func genericRequirementProtocol<T: Hashable>(_ x: T) {
|
|
}
|
|
|
|
public func genericRequirementClass<T>(_ x: T) where T: TestClass {
|
|
}
|
|
|
|
public class TestClass {
|
|
let field: Int
|
|
|
|
init() { field = 0 }
|
|
deinit { print("deinit TestClass") }
|
|
}
|
|
|
|
public func createTestClass() -> TestClass { return TestClass() }
|
|
|
|
public struct TestLargeStruct {
|
|
var x1, x2, x3, x4, x5, x6: Int
|
|
|
|
init(_ x: Int) {
|
|
x1 = x
|
|
x2 = x+1
|
|
x3 = x-1
|
|
x4 = x
|
|
x5 = x+2
|
|
x6 = x-2
|
|
}
|
|
|
|
public mutating func mut() {
|
|
x1 = -x1
|
|
x6 = x5
|
|
}
|
|
}
|
|
|
|
public func createTestLargeStruct(_ x: Int) -> TestLargeStruct {
|
|
return TestLargeStruct(x)
|
|
}
|
|
|
|
@frozen
|
|
public struct TestSmallStruct {
|
|
var x1: UInt32
|
|
|
|
public mutating func mut() {
|
|
x1 = ~x1
|
|
}
|
|
|
|
public func genericMethodPassThrough<T>(_ x: T) -> T {
|
|
return x
|
|
}
|
|
|
|
public mutating func genericMethodMutTake<T>(_ x: T) {
|
|
if let y = x as? UInt32 {
|
|
x1 += y
|
|
} else {
|
|
x1 -= 1
|
|
}
|
|
}
|
|
}
|
|
|
|
public func createTestSmallStruct(_ x: UInt32) -> TestSmallStruct {
|
|
return TestSmallStruct(x1: x)
|
|
}
|
|
|
|
// CHECK: SWIFT_EXTERN void $s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, struct swift_interop_passStub_Functions_uint32_t_0_4 _self, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericMethodPassThrough(_:)
|
|
// CHECK-NEXT: SWIFT_EXTERN void $s9Functions15TestSmallStructV20genericMethodMutTakeyyxlF(const void * _Nonnull x, void * _Nonnull , SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // genericMethodMutTake(_:)
|
|
|
|
// CHECK: SWIFT_EXTERN void $s9Functions20genericPrintFunctionyyxlF(const void * _Nonnull x, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunction(_:)
|
|
// CHECK-NEXT: SWIFT_EXTERN void $s9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF(ptrdiff_t x, const void * _Nonnull t1, const void * _Nonnull t1p, ptrdiff_t y, const void * _Nonnull t2, void * _Nonnull , void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunctionMultiGeneric(_:_:_:_:_:)
|
|
// CHECK-NEXT: SWIFT_EXTERN void $s9Functions26genericPrintFunctionTwoArgyyx_SitlF(const void * _Nonnull x, ptrdiff_t y, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunctionTwoArg(_:_:)
|
|
// CHECK-NEXT: SWIFT_EXTERN void $s9Functions10genericRetyxxlF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericRet(_:)
|
|
// CHECK-NEXT: SWIFT_EXTERN void $s9Functions11genericSwapyyxz_xztlF(void * _Nonnull x, void * _Nonnull y, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericSwap(_:_:)
|
|
|
|
// CHECK-NOT: genericRequirement
|
|
|
|
// Skip templates in impl classes.
|
|
// CHECK: _impl_TestSmallStruct
|
|
// CHECK: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK T_0_0 genericMethodPassThrough(const T_0_0& x) const SWIFT_SYMBOL("s:9Functions15TestSmallStructV24genericMethodPassThroughyxxlF");
|
|
// CHECK-NEXT: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK void genericMethodMutTake(const T_0_0& x) SWIFT_SYMBOL("s:9Functions15TestSmallStructV20genericMethodMutTakeyyxlF");
|
|
// CHECK: template<class T>
|
|
// CHECK-NEXT: returnNewValue
|
|
|
|
// CHECK: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK void genericPrintFunction(const T_0_0& x) noexcept SWIFT_SYMBOL("s:9Functions20genericPrintFunctionyyxlF") {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: _impl::$s9Functions20genericPrintFunctionyyxlF(swift::_impl::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: }
|
|
|
|
|
|
// CHECK: template<class T_0_0, class T_0_1>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK void genericPrintFunctionMultiGeneric(swift::Int x, const T_0_0& t1, const T_0_0& t1p, swift::Int y, const T_0_1& t2) noexcept SWIFT_SYMBOL("s:9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF") {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_1>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: _impl::$s9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF(x, swift::_impl::getOpaquePointer(t1), swift::_impl::getOpaquePointer(t1p), y, swift::_impl::getOpaquePointer(t2), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata(), swift::TypeMetadataTrait<T_0_1>::getTypeMetadata());
|
|
// CHECK-NEXT: }
|
|
|
|
|
|
// CHECK: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK void genericPrintFunctionTwoArg(const T_0_0& x, swift::Int y) noexcept SWIFT_SYMBOL("s:9Functions26genericPrintFunctionTwoArgyyx_SitlF") {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: _impl::$s9Functions26genericPrintFunctionTwoArgyyx_SitlF(swift::_impl::getOpaquePointer(x), y, swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: }
|
|
|
|
// CHECK: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK T_0_0 genericRet(const T_0_0& x) noexcept SWIFT_SYMBOL("s:9Functions10genericRetyxxlF") SWIFT_WARN_UNUSED_RESULT {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: #pragma clang diagnostic push
|
|
// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions"
|
|
// CHECK-NEXT: if constexpr (std::is_base_of<::swift::_impl::RefCountedClass, T_0_0>::value) {
|
|
// CHECK-NEXT: void *returnValue;
|
|
// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(reinterpret_cast<void *>(&returnValue), swift::_impl::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::makeRetained(returnValue);
|
|
// CHECK-NEXT: } else if constexpr (::swift::_impl::isValueType<T_0_0>) {
|
|
// CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::returnNewValue([&](void * _Nonnull returnValue) SWIFT_INLINE_THUNK_ATTRIBUTES {
|
|
// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(returnValue, swift::_impl::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: });
|
|
// CHECK-NEXT: } else if constexpr (::swift::_impl::isSwiftBridgedCxxRecord<T_0_0>) {
|
|
// CHECK-NEXT: alignas(alignof(T_0_0)) char storage[sizeof(T_0_0)];
|
|
// CHECK-NEXT: auto * _Nonnull storageObjectPtr = reinterpret_cast<T_0_0 *>(storage);
|
|
// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(storage, swift::_impl::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: T_0_0 result(static_cast<T_0_0 &&>(*storageObjectPtr));
|
|
// CHECK-NEXT: storageObjectPtr->~T_0_0();
|
|
// CHECK-NEXT: return result;
|
|
// CHECK-NEXT: } else {
|
|
// CHECK-NEXT: T_0_0 returnValue;
|
|
// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(reinterpret_cast<void *>(&returnValue), swift::_impl::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: return returnValue;
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: #pragma clang diagnostic pop
|
|
// CHECK-NEXT: }
|
|
|
|
// CHECK: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK void genericSwap(T_0_0& x, T_0_0& y) noexcept SWIFT_SYMBOL("s:9Functions11genericSwapyyxz_xztlF") {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: _impl::$s9Functions11genericSwapyyxz_xztlF(swift::_impl::getOpaquePointer(x), swift::_impl::getOpaquePointer(y), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: }
|
|
|
|
// CHECK: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK T_0_0 TestSmallStruct::genericMethodPassThrough(const T_0_0& x) const {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: #pragma clang diagnostic push
|
|
// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions"
|
|
// CHECK-NEXT: if constexpr (std::is_base_of<::swift::_impl::RefCountedClass, T_0_0>::value) {
|
|
// CHECK-NEXT: void *returnValue;
|
|
// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(reinterpret_cast<void *>(&returnValue), swift::_impl::getOpaquePointer(x), Functions::_impl::swift_interop_passDirect_Functions_uint32_t_0_4(_getOpaquePointer()), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::makeRetained(returnValue);
|
|
// CHECK-NEXT: } else if constexpr (::swift::_impl::isValueType<T_0_0>) {
|
|
// CHECK-NEXT: return ::swift::_impl::implClassFor<T_0_0>::type::returnNewValue([&](void * _Nonnull returnValue) SWIFT_INLINE_THUNK_ATTRIBUTES {
|
|
// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(returnValue, swift::_impl::getOpaquePointer(x), Functions::_impl::swift_interop_passDirect_Functions_uint32_t_0_4(_getOpaquePointer()), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: });
|
|
// CHECK-NEXT: } else if constexpr (::swift::_impl::isSwiftBridgedCxxRecord<T_0_0>) {
|
|
// CHECK-NEXT: alignas(alignof(T_0_0)) char storage[sizeof(T_0_0)];
|
|
// CHECK-NEXT: auto * _Nonnull storageObjectPtr = reinterpret_cast<T_0_0 *>(storage);
|
|
// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(storage, swift::_impl::getOpaquePointer(x), Functions::_impl::swift_interop_passDirect_Functions_uint32_t_0_4(_getOpaquePointer()), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata())
|
|
// CHECK-NEXT: T_0_0 result(static_cast<T_0_0 &&>(*storageObjectPtr));
|
|
// CHECK-NEXT: storageObjectPtr->~T_0_0();
|
|
// CHECK-NEXT: return result;
|
|
// CHECK-NEXT: } else {
|
|
// CHECK-NEXT: T_0_0 returnValue;
|
|
// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV24genericMethodPassThroughyxxlF(reinterpret_cast<void *>(&returnValue), swift::_impl::getOpaquePointer(x), Functions::_impl::swift_interop_passDirect_Functions_uint32_t_0_4(_getOpaquePointer()), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
|
|
// CHECK-NEXT: return returnValue;
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: #pragma clang diagnostic pop
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: template<class T_0_0>
|
|
// CHECK-NEXT: #ifdef __cpp_concepts
|
|
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: SWIFT_INLINE_THUNK void TestSmallStruct::genericMethodMutTake(const T_0_0& x) {
|
|
// CHECK-NEXT: #ifndef __cpp_concepts
|
|
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
|
|
// CHECK-NEXT: #endif
|
|
// CHECK-NEXT: _impl::$s9Functions15TestSmallStructV20genericMethodMutTakeyyxlF(swift::_impl::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata(), _getOpaquePointer());
|
|
// CHECK-NEXT: }
|