diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 2b39748702dda..39c9d5b41a17c 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -823,6 +823,7 @@ class TagInfo : public CommonTypeInfo { std::optional SwiftImportAs; std::optional SwiftRetainOp; std::optional SwiftReleaseOp; + std::optional SwiftDefaultOwnership; /// The Swift protocol that this type should be automatically conformed to. std::optional SwiftConformance; @@ -872,6 +873,8 @@ class TagInfo : public CommonTypeInfo { SwiftRetainOp = RHS.SwiftRetainOp; if (!SwiftReleaseOp) SwiftReleaseOp = RHS.SwiftReleaseOp; + if (!SwiftDefaultOwnership) + SwiftDefaultOwnership = RHS.SwiftDefaultOwnership; if (!SwiftConformance) SwiftConformance = RHS.SwiftConformance; @@ -901,6 +904,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftImportAs == RHS.SwiftImportAs && LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && + LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership && LHS.SwiftConformance == RHS.SwiftConformance && LHS.isFlagEnum() == RHS.isFlagEnum() && LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 189240f734a3c..d56f34c54d680 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0; /// API notes file minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t VERSION_MINOR = 35; // BoundsSafety +const uint16_t VERSION_MINOR = 36; // SwiftDefaultOwnership const uint8_t kSwiftConforms = 1; const uint8_t kSwiftDoesNotConform = 2; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index d3910d69e6a59..efd82063ff865 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -663,6 +663,13 @@ class TagTableInfo ReleaseOpLength - 1); Data += ReleaseOpLength - 1; } + unsigned DefaultOwnershipLength = + endian::readNext(Data); + if (DefaultOwnershipLength > 0) { + Info.SwiftDefaultOwnership = std::string( + reinterpret_cast(Data), DefaultOwnershipLength - 1); + Data += DefaultOwnershipLength - 1; + } if (unsigned ConformanceLength = endian::readNext(Data)) { Info.SwiftConformance = std::string(reinterpret_cast(Data), diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index 794eb754e5cf6..9574e30b2de38 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1341,6 +1341,7 @@ class TagTableInfo : public CommonTypeTableInfo { return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + + 2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) + 2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) + 3 + getCommonTypeInfoSize(TI); // clang-format on @@ -1389,6 +1390,12 @@ class TagTableInfo : public CommonTypeTableInfo { } else { writer.write(0); } + if (auto DefaultOwnership = TI.SwiftDefaultOwnership) { + writer.write(DefaultOwnership->size() + 1); + OS.write(DefaultOwnership->c_str(), DefaultOwnership->size()); + } else { + writer.write(0); + } if (auto Conformance = TI.SwiftConformance) { writer.write(Conformance->size() + 1); OS.write(Conformance->c_str(), Conformance->size()); diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 776a9073b7edb..a690f087e95d8 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -628,6 +628,7 @@ struct Tag { std::optional SwiftImportAs; std::optional SwiftRetainOp; std::optional SwiftReleaseOp; + std::optional SwiftDefaultOwnership; std::optional SwiftConformance; std::optional EnumExtensibility; std::optional FlagEnum; @@ -668,6 +669,7 @@ template <> struct MappingTraits { IO.mapOptional("SwiftImportAs", T.SwiftImportAs); IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp); IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp); + IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership); IO.mapOptional("SwiftConformsTo", T.SwiftConformance); IO.mapOptional("EnumExtensibility", T.EnumExtensibility); IO.mapOptional("FlagEnum", T.FlagEnum); @@ -1176,6 +1178,8 @@ class YAMLConverter { TI.SwiftReleaseOp = T.SwiftReleaseOp; if (T.SwiftConformance) TI.SwiftConformance = T.SwiftConformance; + if (T.SwiftDefaultOwnership) + TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership; if (T.SwiftCopyable) TI.setSwiftCopyable(T.SwiftCopyable); diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 15e77045800d5..b7265dc4d2517 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -723,6 +723,9 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info, if (auto ReleaseOp = Info.SwiftReleaseOp) D->addAttr( SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value())); + if (auto DefaultOwnership = Info.SwiftDefaultOwnership) + D->addAttr(SwiftAttrAttr::Create( + S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default")); if (auto ConformsTo = Info.SwiftConformance) D->addAttr( diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes index 88e0da1382d6c..66fc46e50ba0d 100644 --- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes @@ -14,6 +14,11 @@ Tags: SwiftReleaseOp: RCRelease SwiftRetainOp: RCRetain SwiftConformsTo: MySwiftModule.MySwiftRefCountedProtocol +- Name: RefCountedTypeWithDefaultConvention + SwiftImportAs: reference + SwiftReleaseOp: release + SwiftRetainOp: retain + SwiftDefaultOwnership: unretained - Name: NonCopyableType SwiftCopyable: false SwiftConformsTo: MySwiftModule.MySwiftNonCopyableProtocol diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h index b6900fee8a979..20b8f04b4a914 100644 --- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h @@ -19,3 +19,7 @@ struct CopyableType { int value; }; struct NonEscapableType { int value; }; struct EscapableType { int value; }; + +struct RefCountedTypeWithDefaultConvention {}; +inline void retain(RefCountedType *x) {} +inline void release(RefCountedType *x) {} diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp index 3981ef1ed419a..929f924f2afee 100644 --- a/clang/test/APINotes/swift-import-as.cpp +++ b/clang/test/APINotes/swift-import-as.cpp @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter ImmortalRefType | FileCheck -check-prefix=CHECK-IMMORTAL %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedTypeWithDefaultConvention | FileCheck -check-prefix=CHECK-REF-COUNTED-DEFAULT %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonCopyableType | FileCheck -check-prefix=CHECK-NON-COPYABLE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter CopyableType | FileCheck -check-prefix=CHECK-COPYABLE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonEscapableType | FileCheck -check-prefix=CHECK-NON-ESCAPABLE %s @@ -26,6 +27,13 @@ // CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "release:RCRelease" // CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "conforms_to:MySwiftModule.MySwiftRefCountedProtocol" +// CHECK-REF-COUNTED-DEFAULT: Dumping RefCountedTypeWithDefaultConvention: +// CHECK-REF-COUNTED-DEFAULT-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct RefCountedTypeWithDefaultConvention +// CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <> "import_reference" +// CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <> "retain:retain" +// CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <> "release:release" +// CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <> "returned_as_unretained_by_default" + // CHECK-NON-COPYABLE: Dumping NonCopyableType: // CHECK-NON-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonCopyableType // CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"