diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 9c01978fd49ef..0f2e49613b514 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -737,6 +737,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; @@ -786,6 +787,8 @@ class TagInfo : public CommonTypeInfo { SwiftRetainOp = RHS.SwiftRetainOp; if (!SwiftReleaseOp) SwiftReleaseOp = RHS.SwiftReleaseOp; + if (!SwiftDefaultOwnership) + SwiftDefaultOwnership = RHS.SwiftDefaultOwnership; if (!SwiftConformance) SwiftConformance = RHS.SwiftConformance; @@ -815,6 +818,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 939235179c363..bb0c276e74964 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 = 34; // SwiftReturnOwnership +const uint16_t VERSION_MINOR = 35; // 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 646eabd2a5ecd..2ba30ca427ae4 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -624,6 +624,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 1aae07bbdd30e..7578bc37b5c68 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1274,6 +1274,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 @@ -1322,6 +1323,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 414a59a4f12d0..803410c54c646 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -460,6 +460,7 @@ struct Tag { std::optional SwiftImportAs; std::optional SwiftRetainOp; std::optional SwiftReleaseOp; + std::optional SwiftDefaultOwnership; std::optional SwiftConformance; std::optional EnumExtensibility; std::optional FlagEnum; @@ -500,6 +501,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); @@ -990,6 +992,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 b354bb7b06435..def909fc2478d 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -643,6 +643,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"