[cxx-interop] Fix exporting Swift enums with C POD associated data

These types are OK to by copied using memcpy. Previously, the generated
code assumed these types are exported swift types with all the value witness
functions.

rdar://111812577
This commit is contained in:
Gabor Horvath
2025-03-14 15:10:13 +00:00
parent 1bd0cd7b94
commit e7a8fb1672
2 changed files with 27 additions and 3 deletions

View File

@@ -32,6 +32,7 @@
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/SwiftNameTranslation.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/AST/Types.h"
@@ -45,6 +46,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
@@ -475,6 +477,17 @@ private:
os << "@end\n";
}
static bool isClangPOD(const NominalTypeDecl *ntd) {
auto clangDecl = ntd->getClangDecl();
if (!clangDecl)
return false;
if (const auto *rd = dyn_cast<clang::RecordDecl>(clangDecl)) {
return !isa<clang::CXXRecordDecl>(rd) ||
cast<clang::CXXRecordDecl>(rd)->isPOD();
}
return false;
}
void visitEnumDeclCxx(EnumDecl *ED) {
assert(owningPrinter.outputLang == OutputLanguageMode::Cxx);
@@ -588,7 +601,9 @@ private:
assert(objectTypeDecl != nullptr || paramType->isOptional());
if (objectTypeDecl &&
owningPrinter.typeMapping.getKnownCxxTypeInfo(objectTypeDecl)) {
(owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl) ||
isClangPOD(objectTypeDecl))) {
outOfLineOS << " " << types[paramType] << " result;\n";
outOfLineOS << " "
"memcpy(&result, payloadFromDestruction, "
@@ -755,8 +770,9 @@ private:
assert(objectTypeDecl != nullptr || paramType->isOptional());
if (objectTypeDecl &&
owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl)) {
(owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl) ||
isClangPOD(objectTypeDecl))) {
outOfLineOS
<< " memcpy(result._getOpaquePointer(), &val, "
"sizeof(val));\n";

View File

@@ -3,6 +3,10 @@
// RUN: %target-swift-frontend %s -module-name UseCoreFoundation -enable-experimental-cxx-interop -clang-header-expose-decls=all-public -typecheck -verify -emit-clang-header-path %t/UseCoreFoundation.h
// RUN: %FileCheck %s < %t/UseCoreFoundation.h
// RUN: echo "#include <netinet/in.h>" > %t/full-header.h
// RUN: cat %t/UseCoreFoundation.h >> %t/full-header.h
// RUN: %target-interop-build-clangxx -std=gnu++20 -fobjc-arc -c -x objective-c++-header %t/full-header.h -o %t/o.o
// REQUIRES: objc_interop
import CoreFoundation
@@ -16,5 +20,9 @@ public func networkThing() -> in_addr? {
return nil
}
public enum MyEnum {
case value(in_addr)
}
// CHECK: SWIFT_EXTERN bool $s17UseCoreFoundation6foobarySbSo9CFDataRefaF(CFDataRef _Nonnull a) SWIFT_NOEXCEPT SWIFT_CALL; // foobar(_:)
// CHECK: SWIFT_INLINE_THUNK swift::Optional<in_addr> networkThing() noexcept SWIFT_SYMBOL("s:17UseCoreFoundation12networkThingSo7in_addrVSgyF") SWIFT_WARN_UNUSED_RESULT {