Author: Gábor Horváth Date: 2025-09-15T12:30:29+02:00 New Revision: cdedc81c33649e97f053ca9eb346e3db6664bd7e
URL: https://github.com/llvm/llvm-project/commit/cdedc81c33649e97f053ca9eb346e3db6664bd7e DIFF: https://github.com/llvm/llvm-project/commit/cdedc81c33649e97f053ca9eb346e3db6664bd7e.diff LOG: [APINotes] Support annotating safety of APIs (#157506) Added: Modified: clang/docs/APINotes.rst clang/include/clang/APINotes/Types.h clang/lib/APINotes/APINotesFormat.h clang/lib/APINotes/APINotesReader.cpp clang/lib/APINotes/APINotesTypes.cpp clang/lib/APINotes/APINotesWriter.cpp clang/lib/APINotes/APINotesYAMLCompiler.cpp clang/lib/Sema/SemaAPINotes.cpp clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes clang/test/APINotes/Inputs/Headers/SwiftImportAs.h clang/test/APINotes/swift-import-as.cpp Removed: ################################################################################ diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index dec4b186ff72f..e142cfa62e5a2 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -229,6 +229,20 @@ declaration kind), all of which are optional: - Name: vector SwiftConformsTo: Cxx.CxxSequence +:SwiftSafety: + + Import a declaration as ``@safe`` or ``@unsafe`` to Swift. + + :: + + Tags: + - Name: UnsafeType + SwiftSafety: unsafe + - Name: span + Methods: + - Name: size + SwiftSafety: safe + :Availability, AvailabilityMsg: A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 71625715bda19..fb2b91a3e1750 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -46,6 +46,8 @@ enum class SwiftNewTypeKind { Enum, }; +enum class SwiftSafetyKind { Unspecified, Safe, Unsafe, None }; + /// Describes API notes data for any entity. /// /// This is used as the base of all API notes. @@ -71,13 +73,19 @@ class CommonEntityInfo { LLVM_PREFERRED_TYPE(bool) unsigned SwiftPrivate : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftSafetyAudited : 1; + + LLVM_PREFERRED_TYPE(SwiftSafetyKind) + unsigned SwiftSafety : 2; + public: /// Swift name of this entity. std::string SwiftName; CommonEntityInfo() : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0), - SwiftPrivate(0) {} + SwiftPrivate(0), SwiftSafetyAudited(0), SwiftSafety(0) {} std::optional<bool> isSwiftPrivate() const { return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate) @@ -89,6 +97,17 @@ class CommonEntityInfo { SwiftPrivate = Private.value_or(0); } + std::optional<SwiftSafetyKind> getSwiftSafety() const { + return SwiftSafetyAudited ? std::optional<SwiftSafetyKind>( + static_cast<SwiftSafetyKind>(SwiftSafety)) + : std::nullopt; + } + + void setSwiftSafety(SwiftSafetyKind Safety) { + SwiftSafetyAudited = 1; + SwiftSafety = static_cast<unsigned>(Safety); + } + friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &); CommonEntityInfo &operator|=(const CommonEntityInfo &RHS) { @@ -108,6 +127,9 @@ class CommonEntityInfo { if (!SwiftPrivateSpecified) setSwiftPrivate(RHS.isSwiftPrivate()); + if (!SwiftSafetyAudited && RHS.SwiftSafetyAudited) + setSwiftSafety(*RHS.getSwiftSafety()); + if (SwiftName.empty()) SwiftName = RHS.SwiftName; @@ -123,7 +145,9 @@ inline bool operator==(const CommonEntityInfo &LHS, LHS.Unavailable == RHS.Unavailable && LHS.UnavailableInSwift == RHS.UnavailableInSwift && LHS.SwiftPrivateSpecified == RHS.SwiftPrivateSpecified && - LHS.SwiftPrivate == RHS.SwiftPrivate && LHS.SwiftName == RHS.SwiftName; + LHS.SwiftPrivate == RHS.SwiftPrivate && + LHS.SwiftSafetyAudited == RHS.SwiftSafetyAudited && + LHS.SwiftSafety == RHS.SwiftSafety && LHS.SwiftName == RHS.SwiftName; } inline bool operator!=(const CommonEntityInfo &LHS, diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 69d180e7b3eb5..bb423ccb2bfaf 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 = 37; // SwiftDestroyOp +const uint16_t VERSION_MINOR = 38; // SwiftSafety 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 573356f97ff73..7f9bb5f12cda7 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -94,11 +94,14 @@ class VersionedTableInfo { /// Read serialized CommonEntityInfo. void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) { - uint8_t UnavailableBits = *Data++; - Info.Unavailable = (UnavailableBits >> 1) & 0x01; - Info.UnavailableInSwift = UnavailableBits & 0x01; - if ((UnavailableBits >> 2) & 0x01) - Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01)); + uint8_t EncodedBits = *Data++; + Info.Unavailable = (EncodedBits >> 1) & 0x01; + Info.UnavailableInSwift = EncodedBits & 0x01; + if ((EncodedBits >> 2) & 0x01) + Info.setSwiftPrivate(static_cast<bool>((EncodedBits >> 3) & 0x01)); + if ((EncodedBits >> 4) & 0x01) + Info.setSwiftSafety( + static_cast<SwiftSafetyKind>((EncodedBits >> 5) & 0x03)); unsigned MsgLength = endian::readNext<uint16_t, llvm::endianness::little>(Data); diff --git a/clang/lib/APINotes/APINotesTypes.cpp b/clang/lib/APINotes/APINotesTypes.cpp index f726faa832bcc..bff4be104c6c8 100644 --- a/clang/lib/APINotes/APINotesTypes.cpp +++ b/clang/lib/APINotes/APINotesTypes.cpp @@ -18,6 +18,21 @@ LLVM_DUMP_METHOD void CommonEntityInfo::dump(llvm::raw_ostream &OS) const { OS << "[UnavailableInSwift] "; if (SwiftPrivateSpecified) OS << (SwiftPrivate ? "[SwiftPrivate] " : ""); + if (SwiftSafetyAudited) { + switch (*getSwiftSafety()) { + case SwiftSafetyKind::Safe: + OS << "[Safe] "; + break; + case SwiftSafetyKind::Unsafe: + OS << "[Unsafe] "; + break; + case SwiftSafetyKind::Unspecified: + OS << "[Unspecified] "; + break; + case SwiftSafetyKind::None: + break; + } + } if (!SwiftName.empty()) OS << "Swift Name: " << SwiftName << ' '; OS << '\n'; diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index cf88d118d0979..47ed93a567c0e 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -507,6 +507,12 @@ void emitCommonEntityInfo(raw_ostream &OS, const CommonEntityInfo &CEI) { llvm::support::endian::Writer writer(OS, llvm::endianness::little); uint8_t payload = 0; + if (auto safety = CEI.getSwiftSafety()) { + payload = static_cast<unsigned>(*safety); + payload <<= 1; + payload |= 0x01; + } + payload <<= 2; if (auto swiftPrivate = CEI.isSwiftPrivate()) { payload |= 0x01; if (*swiftPrivate) diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index a91a1eea03d81..8e91d48b4ba62 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -29,6 +29,18 @@ using namespace clang; using namespace api_notes; +namespace llvm { +namespace yaml { +template <> struct ScalarEnumerationTraits<SwiftSafetyKind> { + static void enumeration(IO &IO, SwiftSafetyKind &SK) { + IO.enumCase(SK, "unspecified", SwiftSafetyKind::Unspecified); + IO.enumCase(SK, "safe", SwiftSafetyKind::Safe); + IO.enumCase(SK, "unsafe", SwiftSafetyKind::Unsafe); + } +}; +} // namespace yaml +} // namespace llvm + namespace { enum class APIAvailability { Available = 0, @@ -163,6 +175,7 @@ struct Method { bool Required = false; StringRef ResultType; StringRef SwiftReturnOwnership; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<Method> MethodsSeq; @@ -199,6 +212,7 @@ template <> struct MappingTraits<Method> { IO.mapOptional("ResultType", M.ResultType, StringRef("")); IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership, StringRef("")); + IO.mapOptional("SwiftSafety", M.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -214,6 +228,7 @@ struct Property { StringRef SwiftName; std::optional<bool> SwiftImportAsAccessors; StringRef Type; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<Property> PropertiesSeq; @@ -235,6 +250,7 @@ template <> struct MappingTraits<Property> { IO.mapOptional("SwiftName", P.SwiftName, StringRef("")); IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors); IO.mapOptional("Type", P.Type, StringRef("")); + IO.mapOptional("SwiftSafety", P.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -254,6 +270,7 @@ struct Class { std::optional<std::string> SwiftConformance; MethodsSeq Methods; PropertiesSeq Properties; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<Class> ClassesSeq; @@ -279,6 +296,7 @@ template <> struct MappingTraits<Class> { IO.mapOptional("SwiftConformsTo", C.SwiftConformance); IO.mapOptional("Methods", C.Methods); IO.mapOptional("Properties", C.Properties); + IO.mapOptional("SwiftSafety", C.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -297,6 +315,7 @@ struct Function { StringRef Type; StringRef ResultType; StringRef SwiftReturnOwnership; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<Function> FunctionsSeq; @@ -321,6 +340,7 @@ template <> struct MappingTraits<Function> { IO.mapOptional("ResultType", F.ResultType, StringRef("")); IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership, StringRef("")); + IO.mapOptional("SwiftSafety", F.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -334,6 +354,7 @@ struct GlobalVariable { std::optional<bool> SwiftPrivate; StringRef SwiftName; StringRef Type; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<GlobalVariable> GlobalVariablesSeq; @@ -353,6 +374,7 @@ template <> struct MappingTraits<GlobalVariable> { IO.mapOptional("SwiftPrivate", GV.SwiftPrivate); IO.mapOptional("SwiftName", GV.SwiftName, StringRef("")); IO.mapOptional("Type", GV.Type, StringRef("")); + IO.mapOptional("SwiftSafety", GV.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -364,6 +386,7 @@ struct EnumConstant { AvailabilityItem Availability; std::optional<bool> SwiftPrivate; StringRef SwiftName; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<EnumConstant> EnumConstantsSeq; @@ -381,6 +404,7 @@ template <> struct MappingTraits<EnumConstant> { IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef("")); IO.mapOptional("SwiftPrivate", EC.SwiftPrivate); IO.mapOptional("SwiftName", EC.SwiftName, StringRef("")); + IO.mapOptional("SwiftSafety", EC.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -424,6 +448,7 @@ struct Field { std::optional<bool> SwiftPrivate; StringRef SwiftName; StringRef Type; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<Field> FieldsSeq; @@ -443,6 +468,7 @@ template <> struct MappingTraits<Field> { IO.mapOptional("SwiftPrivate", F.SwiftPrivate); IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); IO.mapOptional("Type", F.Type, StringRef("")); + IO.mapOptional("SwiftSafety", F.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -470,6 +496,7 @@ struct Tag { std::optional<EnumConvenienceAliasKind> EnumConvenienceKind; std::optional<bool> SwiftCopyable; std::optional<bool> SwiftEscapable; + SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; FunctionsSeq Methods; FieldsSeq Fields; @@ -515,6 +542,7 @@ template <> struct MappingTraits<Tag> { IO.mapOptional("Methods", T.Methods); IO.mapOptional("Fields", T.Fields); IO.mapOptional("Tags", T.Tags); + IO.mapOptional("SwiftSafety", T.SafetyKind, SwiftSafetyKind::None); } }; } // namespace yaml @@ -530,6 +558,7 @@ struct Typedef { std::optional<StringRef> NSErrorDomain; std::optional<SwiftNewTypeKind> SwiftType; std::optional<std::string> SwiftConformance; + const SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; typedef std::vector<Typedef> TypedefsSeq; @@ -602,6 +631,7 @@ struct Namespace { StringRef SwiftName; std::optional<bool> SwiftPrivate; TopLevelItems Items; + const SwiftSafetyKind SafetyKind = SwiftSafetyKind::None; }; } // namespace @@ -797,6 +827,8 @@ class YAMLConverter { StringRef APIName) { convertAvailability(Common.Availability, Info, APIName); Info.setSwiftPrivate(Common.SwiftPrivate); + if (Common.SafetyKind != SwiftSafetyKind::None) + Info.setSwiftSafety(Common.SafetyKind); Info.SwiftName = std::string(Common.SwiftName); } @@ -956,6 +988,8 @@ class YAMLConverter { void convertFunction(const Function &Function, FuncOrMethodInfo &FI) { convertAvailability(Function.Availability, FI, Function.Name); FI.setSwiftPrivate(Function.SwiftPrivate); + if (Function.SafetyKind != SwiftSafetyKind::None) + FI.setSwiftSafety(Function.SafetyKind); FI.SwiftName = std::string(Function.SwiftName); std::optional<ParamInfo> This; convertParams(Function.Params, FI, This); diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 4cc1b76264340..99a29add8211d 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -13,6 +13,7 @@ #include "CheckExprLifetime.h" #include "TypeLocBuilder.h" #include "clang/APINotes/APINotesReader.h" +#include "clang/APINotes/Types.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -291,6 +292,29 @@ static void ProcessAPINotes(Sema &S, Decl *D, }); } + // swift_safety + if (auto SafetyKind = Info.getSwiftSafety()) { + bool Addition = *SafetyKind != api_notes::SwiftSafetyKind::Unspecified; + handleAPINotedAttribute<SwiftAttrAttr>( + S, D, Addition, Metadata, + [&] { + return SwiftAttrAttr::Create( + S.Context, *SafetyKind == api_notes::SwiftSafetyKind::Safe + ? "safe" + : "unsafe"); + }, + [](const Decl *D) { + return llvm::find_if(D->attrs(), [](const Attr *attr) { + if (const auto *swiftAttr = dyn_cast<SwiftAttrAttr>(attr)) { + if (swiftAttr->getAttribute() == "safe" || + swiftAttr->getAttribute() == "unsafe") + return true; + } + return false; + }); + }); + } + // swift_name if (!Info.SwiftName.empty()) { handleAPINotedAttribute<SwiftNameAttr>( diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes index 15c806842d08f..7e9cac32df3a5 100644 --- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes @@ -35,6 +35,14 @@ Tags: - Name: NoncopyableWithDestroyType SwiftCopyable: false SwiftDestroyOp: NCDDestroy +- Name: ImportAsUnsafeStruct + SwiftSafety: unsafe +- Name: StructWithUnsafeMethod + Methods: + - Name: ImportAsUnsafeMethod + SwiftSafety: unsafe + - Name: ImportAsUnsafeMethodActuallySafe + SwiftSafety: safe Functions: - Name: functionReturningFrt__ @@ -42,7 +50,20 @@ Functions: SwiftReturnOwnership: unretained - Name: functionReturningFrt_returns_retained SwiftReturnOwnership: retained + - Name: ImportAsUnsafe + SwiftSafety: unsafe + - Name: ImportAsUnsafeAlreadyAnnotated + SwiftSafety: unspecified Typedefs: - Name: WrappedOptions SwiftWrapper: struct SwiftConformsTo: Swift.OptionSet +SwiftVersions: + - Version: 3.0 + Functions: + - Name: ImportAsUnsafeVersioned + SwiftSafety: unsafe + - Version: 6.0 + Functions: + - Name: ImportAsUnsafeVersioned + SwiftSafety: safe diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h index 978b4fbbb3b00..272e3865ab2ba 100644 --- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h @@ -36,3 +36,14 @@ struct NoncopyableWithDestroyType { }; void NCDDestroy(NoncopyableWithDestroyType instance); + +void ImportAsUnsafe(); +struct ImportAsUnsafeStruct { +}; +struct StructWithUnsafeMethod { + void ImportAsUnsafeMethod(); + void ImportAsUnsafeMethodActuallySafe(); +}; + +void ImportAsUnsafeAlreadyAnnotated() __attribute__((swift_attr("unsafe"))); +void ImportAsUnsafeVersioned(); diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp index f5d08df7c6a1b..20d38b5a0968d 100644 --- a/clang/test/APINotes/swift-import-as.cpp +++ b/clang/test/APINotes/swift-import-as.cpp @@ -16,6 +16,7 @@ // 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 methodReturningFrt_returns_retained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-RETAINED %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 WrappedOptions | FileCheck -check-prefix=CHECK-WRAPPED-OPTIONS %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 NoncopyableWithDestroyType | FileCheck -check-prefix=CHECK-NONCOPYABLE-WITH-DESTROY %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 ImportAsUnsafe | FileCheck -check-prefix=CHECK-IMPORT-AS-UNSAFE %s #include <SwiftImportAs.h> @@ -103,3 +104,32 @@ // CHECK-NONCOPYABLE-WITH-DESTROY: RecordDecl {{.*}}struct NoncopyableWithDestroyType // CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "destroy:NCDDestroy" // CHECK-NONCOPYABLE-WITH-DESTROY: SwiftAttrAttr {{.+}} "~Copyable" + +// CHECK-IMPORT-AS-UNSAFE: Dumping ImportAsUnsafe: +// CHECK-IMPORT-AS-UNSAFE: FunctionDecl {{.+}} ImportAsUnsafe +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "unsafe" + +// CHECK-IMPORT-AS-UNSAFE: Dumping ImportAsUnsafeStruct: +// CHECK-IMPORT-AS-UNSAFE: CXXRecordDecl {{.+}} ImportAsUnsafeStruct +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "unsafe" + +// CHECK-IMPORT-AS-UNSAFE: Dumping StructWithUnsafeMethod::ImportAsUnsafeMethod: +// CHECK-IMPORT-AS-UNSAFE: CXXMethodDecl {{.+}} ImportAsUnsafeMethod +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "unsafe" + +// CHECK-IMPORT-AS-UNSAFE: Dumping StructWithUnsafeMethod::ImportAsUnsafeMethodActuallySafe: +// CHECK-IMPORT-AS-UNSAFE: CXXMethodDecl {{.+}} ImportAsUnsafeMethodActuallySafe +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "safe" + +// CHECK-IMPORT-AS-UNSAFE: Dumping ImportAsUnsafeAlreadyAnnotated: +// CHECK-IMPORT-AS-UNSAFE: FunctionDecl {{.+}} ImportAsUnsafeAlreadyAnnotated +// CHECK-IMPORT-AS-UNSAFE: SwiftVersionedAdditionAttr {{.+}} IsReplacedByActive +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "unsafe" +// CHECK-IMPORT-AS-UNSAFE-EMPTY: + +// CHECK-IMPORT-AS-UNSAFE: Dumping ImportAsUnsafeVersioned: +// CHECK-IMPORT-AS-UNSAFE: FunctionDecl {{.+}} ImportAsUnsafeVersioned +// CHECK-IMPORT-AS-UNSAFE: SwiftVersionedAdditionAttr {{.+}} 3.0 +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "unsafe" +// CHECK-IMPORT-AS-UNSAFE: SwiftVersionedAdditionAttr {{.+}} 6.0 +// CHECK-IMPORT-AS-UNSAFE: SwiftAttrAttr {{.+}} "safe" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits