1e8d8bef9SDimitry Andric //===-- APINotesYAMLCompiler.cpp - API Notes YAML Format Reader -*- C++ -*-===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // The types defined locally are designed to represent the YAML state, which 10e8d8bef9SDimitry Andric // adds an additional bit of state: e.g. a tri-state boolean attribute (yes, no, 11e8d8bef9SDimitry Andric // not applied) becomes a tri-state boolean + present. As a result, while these 12e8d8bef9SDimitry Andric // enumerations appear to be redefining constants from the attributes table 13e8d8bef9SDimitry Andric // data, they are distinct. 14e8d8bef9SDimitry Andric // 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric #include "clang/APINotes/APINotesYAMLCompiler.h" 17*5f757f3fSDimitry Andric #include "clang/APINotes/APINotesWriter.h" 18e8d8bef9SDimitry Andric #include "clang/APINotes/Types.h" 19e8d8bef9SDimitry Andric #include "clang/Basic/LLVM.h" 20e8d8bef9SDimitry Andric #include "clang/Basic/Specifiers.h" 21*5f757f3fSDimitry Andric #include "llvm/ADT/StringSet.h" 22*5f757f3fSDimitry Andric #include "llvm/Support/SourceMgr.h" 23e8d8bef9SDimitry Andric #include "llvm/Support/VersionTuple.h" 24e8d8bef9SDimitry Andric #include "llvm/Support/YAMLTraits.h" 25bdd1243dSDimitry Andric #include <optional> 26e8d8bef9SDimitry Andric #include <vector> 27*5f757f3fSDimitry Andric 28e8d8bef9SDimitry Andric using namespace clang; 29e8d8bef9SDimitry Andric using namespace api_notes; 30e8d8bef9SDimitry Andric 31e8d8bef9SDimitry Andric namespace { 32e8d8bef9SDimitry Andric enum class APIAvailability { 33e8d8bef9SDimitry Andric Available = 0, 34e8d8bef9SDimitry Andric None, 35e8d8bef9SDimitry Andric NonSwift, 36e8d8bef9SDimitry Andric }; 37e8d8bef9SDimitry Andric } // namespace 38e8d8bef9SDimitry Andric 39e8d8bef9SDimitry Andric namespace llvm { 40e8d8bef9SDimitry Andric namespace yaml { 41e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<APIAvailability> { 42e8d8bef9SDimitry Andric static void enumeration(IO &IO, APIAvailability &AA) { 43e8d8bef9SDimitry Andric IO.enumCase(AA, "none", APIAvailability::None); 44e8d8bef9SDimitry Andric IO.enumCase(AA, "nonswift", APIAvailability::NonSwift); 45e8d8bef9SDimitry Andric IO.enumCase(AA, "available", APIAvailability::Available); 46e8d8bef9SDimitry Andric } 47e8d8bef9SDimitry Andric }; 48e8d8bef9SDimitry Andric } // namespace yaml 49e8d8bef9SDimitry Andric } // namespace llvm 50e8d8bef9SDimitry Andric 51e8d8bef9SDimitry Andric namespace { 52e8d8bef9SDimitry Andric enum class MethodKind { 53e8d8bef9SDimitry Andric Class, 54e8d8bef9SDimitry Andric Instance, 55e8d8bef9SDimitry Andric }; 56e8d8bef9SDimitry Andric } // namespace 57e8d8bef9SDimitry Andric 58e8d8bef9SDimitry Andric namespace llvm { 59e8d8bef9SDimitry Andric namespace yaml { 60e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<MethodKind> { 61e8d8bef9SDimitry Andric static void enumeration(IO &IO, MethodKind &MK) { 62e8d8bef9SDimitry Andric IO.enumCase(MK, "Class", MethodKind::Class); 63e8d8bef9SDimitry Andric IO.enumCase(MK, "Instance", MethodKind::Instance); 64e8d8bef9SDimitry Andric } 65e8d8bef9SDimitry Andric }; 66e8d8bef9SDimitry Andric } // namespace yaml 67e8d8bef9SDimitry Andric } // namespace llvm 68e8d8bef9SDimitry Andric 69e8d8bef9SDimitry Andric namespace { 70e8d8bef9SDimitry Andric struct Param { 71e8d8bef9SDimitry Andric unsigned Position; 72bdd1243dSDimitry Andric std::optional<bool> NoEscape = false; 73bdd1243dSDimitry Andric std::optional<NullabilityKind> Nullability; 74bdd1243dSDimitry Andric std::optional<RetainCountConventionKind> RetainCountConvention; 75e8d8bef9SDimitry Andric StringRef Type; 76e8d8bef9SDimitry Andric }; 77e8d8bef9SDimitry Andric 78e8d8bef9SDimitry Andric typedef std::vector<Param> ParamsSeq; 79e8d8bef9SDimitry Andric } // namespace 80e8d8bef9SDimitry Andric 81e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Param) 82e8d8bef9SDimitry Andric LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind) 83e8d8bef9SDimitry Andric 84e8d8bef9SDimitry Andric namespace llvm { 85e8d8bef9SDimitry Andric namespace yaml { 86e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<NullabilityKind> { 87e8d8bef9SDimitry Andric static void enumeration(IO &IO, NullabilityKind &NK) { 88e8d8bef9SDimitry Andric IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull); 89e8d8bef9SDimitry Andric IO.enumCase(NK, "Optional", NullabilityKind::Nullable); 90e8d8bef9SDimitry Andric IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified); 91e8d8bef9SDimitry Andric IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult); 92e8d8bef9SDimitry Andric // TODO: Mapping this to it's own value would allow for better cross 93e8d8bef9SDimitry Andric // checking. Also the default should be Unknown. 94e8d8bef9SDimitry Andric IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified); 95e8d8bef9SDimitry Andric 96e8d8bef9SDimitry Andric // Aliases for compatibility with existing APINotes. 97e8d8bef9SDimitry Andric IO.enumCase(NK, "N", NullabilityKind::NonNull); 98e8d8bef9SDimitry Andric IO.enumCase(NK, "O", NullabilityKind::Nullable); 99e8d8bef9SDimitry Andric IO.enumCase(NK, "U", NullabilityKind::Unspecified); 100e8d8bef9SDimitry Andric IO.enumCase(NK, "S", NullabilityKind::Unspecified); 101e8d8bef9SDimitry Andric } 102e8d8bef9SDimitry Andric }; 103e8d8bef9SDimitry Andric 104e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<RetainCountConventionKind> { 105e8d8bef9SDimitry Andric static void enumeration(IO &IO, RetainCountConventionKind &RCCK) { 106e8d8bef9SDimitry Andric IO.enumCase(RCCK, "none", RetainCountConventionKind::None); 107e8d8bef9SDimitry Andric IO.enumCase(RCCK, "CFReturnsRetained", 108e8d8bef9SDimitry Andric RetainCountConventionKind::CFReturnsRetained); 109e8d8bef9SDimitry Andric IO.enumCase(RCCK, "CFReturnsNotRetained", 110e8d8bef9SDimitry Andric RetainCountConventionKind::CFReturnsNotRetained); 111e8d8bef9SDimitry Andric IO.enumCase(RCCK, "NSReturnsRetained", 112e8d8bef9SDimitry Andric RetainCountConventionKind::NSReturnsRetained); 113e8d8bef9SDimitry Andric IO.enumCase(RCCK, "NSReturnsNotRetained", 114e8d8bef9SDimitry Andric RetainCountConventionKind::NSReturnsNotRetained); 115e8d8bef9SDimitry Andric } 116e8d8bef9SDimitry Andric }; 117e8d8bef9SDimitry Andric 118e8d8bef9SDimitry Andric template <> struct MappingTraits<Param> { 119e8d8bef9SDimitry Andric static void mapping(IO &IO, Param &P) { 120e8d8bef9SDimitry Andric IO.mapRequired("Position", P.Position); 121bdd1243dSDimitry Andric IO.mapOptional("Nullability", P.Nullability, std::nullopt); 122e8d8bef9SDimitry Andric IO.mapOptional("RetainCountConvention", P.RetainCountConvention); 123e8d8bef9SDimitry Andric IO.mapOptional("NoEscape", P.NoEscape); 124e8d8bef9SDimitry Andric IO.mapOptional("Type", P.Type, StringRef("")); 125e8d8bef9SDimitry Andric } 126e8d8bef9SDimitry Andric }; 127e8d8bef9SDimitry Andric } // namespace yaml 128e8d8bef9SDimitry Andric } // namespace llvm 129e8d8bef9SDimitry Andric 130e8d8bef9SDimitry Andric namespace { 131e8d8bef9SDimitry Andric typedef std::vector<NullabilityKind> NullabilitySeq; 132e8d8bef9SDimitry Andric 133e8d8bef9SDimitry Andric struct AvailabilityItem { 134e8d8bef9SDimitry Andric APIAvailability Mode = APIAvailability::Available; 135e8d8bef9SDimitry Andric StringRef Msg; 136e8d8bef9SDimitry Andric }; 137e8d8bef9SDimitry Andric 138e8d8bef9SDimitry Andric /// Old attribute deprecated in favor of SwiftName. 139e8d8bef9SDimitry Andric enum class FactoryAsInitKind { 140e8d8bef9SDimitry Andric /// Infer based on name and type (the default). 141e8d8bef9SDimitry Andric Infer, 142e8d8bef9SDimitry Andric /// Treat as a class method. 143e8d8bef9SDimitry Andric AsClassMethod, 144e8d8bef9SDimitry Andric /// Treat as an initializer. 145e8d8bef9SDimitry Andric AsInitializer, 146e8d8bef9SDimitry Andric }; 147e8d8bef9SDimitry Andric 148e8d8bef9SDimitry Andric struct Method { 149e8d8bef9SDimitry Andric StringRef Selector; 150e8d8bef9SDimitry Andric MethodKind Kind; 151e8d8bef9SDimitry Andric ParamsSeq Params; 152e8d8bef9SDimitry Andric NullabilitySeq Nullability; 153bdd1243dSDimitry Andric std::optional<NullabilityKind> NullabilityOfRet; 154bdd1243dSDimitry Andric std::optional<RetainCountConventionKind> RetainCountConvention; 155e8d8bef9SDimitry Andric AvailabilityItem Availability; 156bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 157e8d8bef9SDimitry Andric StringRef SwiftName; 158e8d8bef9SDimitry Andric FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer; 159e8d8bef9SDimitry Andric bool DesignatedInit = false; 160e8d8bef9SDimitry Andric bool Required = false; 161e8d8bef9SDimitry Andric StringRef ResultType; 162e8d8bef9SDimitry Andric }; 163e8d8bef9SDimitry Andric 164e8d8bef9SDimitry Andric typedef std::vector<Method> MethodsSeq; 165e8d8bef9SDimitry Andric } // namespace 166e8d8bef9SDimitry Andric 167e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Method) 168e8d8bef9SDimitry Andric 169e8d8bef9SDimitry Andric namespace llvm { 170e8d8bef9SDimitry Andric namespace yaml { 171e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<FactoryAsInitKind> { 172e8d8bef9SDimitry Andric static void enumeration(IO &IO, FactoryAsInitKind &FIK) { 173e8d8bef9SDimitry Andric IO.enumCase(FIK, "A", FactoryAsInitKind::Infer); 174e8d8bef9SDimitry Andric IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod); 175e8d8bef9SDimitry Andric IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer); 176e8d8bef9SDimitry Andric } 177e8d8bef9SDimitry Andric }; 178e8d8bef9SDimitry Andric 179e8d8bef9SDimitry Andric template <> struct MappingTraits<Method> { 180e8d8bef9SDimitry Andric static void mapping(IO &IO, Method &M) { 181e8d8bef9SDimitry Andric IO.mapRequired("Selector", M.Selector); 182e8d8bef9SDimitry Andric IO.mapRequired("MethodKind", M.Kind); 183e8d8bef9SDimitry Andric IO.mapOptional("Parameters", M.Params); 184e8d8bef9SDimitry Andric IO.mapOptional("Nullability", M.Nullability); 185bdd1243dSDimitry Andric IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, std::nullopt); 186e8d8bef9SDimitry Andric IO.mapOptional("RetainCountConvention", M.RetainCountConvention); 187e8d8bef9SDimitry Andric IO.mapOptional("Availability", M.Availability.Mode, 188e8d8bef9SDimitry Andric APIAvailability::Available); 189e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 190e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", M.SwiftPrivate); 191e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", M.SwiftName, StringRef("")); 192e8d8bef9SDimitry Andric IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer); 193e8d8bef9SDimitry Andric IO.mapOptional("DesignatedInit", M.DesignatedInit, false); 194e8d8bef9SDimitry Andric IO.mapOptional("Required", M.Required, false); 195e8d8bef9SDimitry Andric IO.mapOptional("ResultType", M.ResultType, StringRef("")); 196e8d8bef9SDimitry Andric } 197e8d8bef9SDimitry Andric }; 198e8d8bef9SDimitry Andric } // namespace yaml 199e8d8bef9SDimitry Andric } // namespace llvm 200e8d8bef9SDimitry Andric 201e8d8bef9SDimitry Andric namespace { 202e8d8bef9SDimitry Andric struct Property { 203e8d8bef9SDimitry Andric StringRef Name; 204bdd1243dSDimitry Andric std::optional<MethodKind> Kind; 205bdd1243dSDimitry Andric std::optional<NullabilityKind> Nullability; 206e8d8bef9SDimitry Andric AvailabilityItem Availability; 207bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 208e8d8bef9SDimitry Andric StringRef SwiftName; 209bdd1243dSDimitry Andric std::optional<bool> SwiftImportAsAccessors; 210e8d8bef9SDimitry Andric StringRef Type; 211e8d8bef9SDimitry Andric }; 212e8d8bef9SDimitry Andric 213e8d8bef9SDimitry Andric typedef std::vector<Property> PropertiesSeq; 214e8d8bef9SDimitry Andric } // namespace 215e8d8bef9SDimitry Andric 216e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Property) 217e8d8bef9SDimitry Andric 218e8d8bef9SDimitry Andric namespace llvm { 219e8d8bef9SDimitry Andric namespace yaml { 220e8d8bef9SDimitry Andric template <> struct MappingTraits<Property> { 221e8d8bef9SDimitry Andric static void mapping(IO &IO, Property &P) { 222e8d8bef9SDimitry Andric IO.mapRequired("Name", P.Name); 223e8d8bef9SDimitry Andric IO.mapOptional("PropertyKind", P.Kind); 224bdd1243dSDimitry Andric IO.mapOptional("Nullability", P.Nullability, std::nullopt); 225e8d8bef9SDimitry Andric IO.mapOptional("Availability", P.Availability.Mode, 226e8d8bef9SDimitry Andric APIAvailability::Available); 227e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef("")); 228e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", P.SwiftPrivate); 229e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", P.SwiftName, StringRef("")); 230e8d8bef9SDimitry Andric IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors); 231e8d8bef9SDimitry Andric IO.mapOptional("Type", P.Type, StringRef("")); 232e8d8bef9SDimitry Andric } 233e8d8bef9SDimitry Andric }; 234e8d8bef9SDimitry Andric } // namespace yaml 235e8d8bef9SDimitry Andric } // namespace llvm 236e8d8bef9SDimitry Andric 237e8d8bef9SDimitry Andric namespace { 238e8d8bef9SDimitry Andric struct Class { 239e8d8bef9SDimitry Andric StringRef Name; 240e8d8bef9SDimitry Andric bool AuditedForNullability = false; 241e8d8bef9SDimitry Andric AvailabilityItem Availability; 242bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 243e8d8bef9SDimitry Andric StringRef SwiftName; 244bdd1243dSDimitry Andric std::optional<StringRef> SwiftBridge; 245bdd1243dSDimitry Andric std::optional<StringRef> NSErrorDomain; 246bdd1243dSDimitry Andric std::optional<bool> SwiftImportAsNonGeneric; 247bdd1243dSDimitry Andric std::optional<bool> SwiftObjCMembers; 248e8d8bef9SDimitry Andric MethodsSeq Methods; 249e8d8bef9SDimitry Andric PropertiesSeq Properties; 250e8d8bef9SDimitry Andric }; 251e8d8bef9SDimitry Andric 252e8d8bef9SDimitry Andric typedef std::vector<Class> ClassesSeq; 253e8d8bef9SDimitry Andric } // namespace 254e8d8bef9SDimitry Andric 255e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Class) 256e8d8bef9SDimitry Andric 257e8d8bef9SDimitry Andric namespace llvm { 258e8d8bef9SDimitry Andric namespace yaml { 259e8d8bef9SDimitry Andric template <> struct MappingTraits<Class> { 260e8d8bef9SDimitry Andric static void mapping(IO &IO, Class &C) { 261e8d8bef9SDimitry Andric IO.mapRequired("Name", C.Name); 262e8d8bef9SDimitry Andric IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false); 263e8d8bef9SDimitry Andric IO.mapOptional("Availability", C.Availability.Mode, 264e8d8bef9SDimitry Andric APIAvailability::Available); 265e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef("")); 266e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", C.SwiftPrivate); 267e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", C.SwiftName, StringRef("")); 268e8d8bef9SDimitry Andric IO.mapOptional("SwiftBridge", C.SwiftBridge); 269e8d8bef9SDimitry Andric IO.mapOptional("NSErrorDomain", C.NSErrorDomain); 270e8d8bef9SDimitry Andric IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric); 271e8d8bef9SDimitry Andric IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers); 272e8d8bef9SDimitry Andric IO.mapOptional("Methods", C.Methods); 273e8d8bef9SDimitry Andric IO.mapOptional("Properties", C.Properties); 274e8d8bef9SDimitry Andric } 275e8d8bef9SDimitry Andric }; 276e8d8bef9SDimitry Andric } // namespace yaml 277e8d8bef9SDimitry Andric } // namespace llvm 278e8d8bef9SDimitry Andric 279e8d8bef9SDimitry Andric namespace { 280e8d8bef9SDimitry Andric struct Function { 281e8d8bef9SDimitry Andric StringRef Name; 282e8d8bef9SDimitry Andric ParamsSeq Params; 283e8d8bef9SDimitry Andric NullabilitySeq Nullability; 284bdd1243dSDimitry Andric std::optional<NullabilityKind> NullabilityOfRet; 285bdd1243dSDimitry Andric std::optional<api_notes::RetainCountConventionKind> RetainCountConvention; 286e8d8bef9SDimitry Andric AvailabilityItem Availability; 287bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 288e8d8bef9SDimitry Andric StringRef SwiftName; 289e8d8bef9SDimitry Andric StringRef Type; 290e8d8bef9SDimitry Andric StringRef ResultType; 291e8d8bef9SDimitry Andric }; 292e8d8bef9SDimitry Andric 293e8d8bef9SDimitry Andric typedef std::vector<Function> FunctionsSeq; 294e8d8bef9SDimitry Andric } // namespace 295e8d8bef9SDimitry Andric 296e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Function) 297e8d8bef9SDimitry Andric 298e8d8bef9SDimitry Andric namespace llvm { 299e8d8bef9SDimitry Andric namespace yaml { 300e8d8bef9SDimitry Andric template <> struct MappingTraits<Function> { 301e8d8bef9SDimitry Andric static void mapping(IO &IO, Function &F) { 302e8d8bef9SDimitry Andric IO.mapRequired("Name", F.Name); 303e8d8bef9SDimitry Andric IO.mapOptional("Parameters", F.Params); 304e8d8bef9SDimitry Andric IO.mapOptional("Nullability", F.Nullability); 305bdd1243dSDimitry Andric IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt); 306e8d8bef9SDimitry Andric IO.mapOptional("RetainCountConvention", F.RetainCountConvention); 307e8d8bef9SDimitry Andric IO.mapOptional("Availability", F.Availability.Mode, 308e8d8bef9SDimitry Andric APIAvailability::Available); 309e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef("")); 310e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", F.SwiftPrivate); 311e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); 312e8d8bef9SDimitry Andric IO.mapOptional("ResultType", F.ResultType, StringRef("")); 313e8d8bef9SDimitry Andric } 314e8d8bef9SDimitry Andric }; 315e8d8bef9SDimitry Andric } // namespace yaml 316e8d8bef9SDimitry Andric } // namespace llvm 317e8d8bef9SDimitry Andric 318e8d8bef9SDimitry Andric namespace { 319e8d8bef9SDimitry Andric struct GlobalVariable { 320e8d8bef9SDimitry Andric StringRef Name; 321bdd1243dSDimitry Andric std::optional<NullabilityKind> Nullability; 322e8d8bef9SDimitry Andric AvailabilityItem Availability; 323bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 324e8d8bef9SDimitry Andric StringRef SwiftName; 325e8d8bef9SDimitry Andric StringRef Type; 326e8d8bef9SDimitry Andric }; 327e8d8bef9SDimitry Andric 328e8d8bef9SDimitry Andric typedef std::vector<GlobalVariable> GlobalVariablesSeq; 329e8d8bef9SDimitry Andric } // namespace 330e8d8bef9SDimitry Andric 331e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable) 332e8d8bef9SDimitry Andric 333e8d8bef9SDimitry Andric namespace llvm { 334e8d8bef9SDimitry Andric namespace yaml { 335e8d8bef9SDimitry Andric template <> struct MappingTraits<GlobalVariable> { 336e8d8bef9SDimitry Andric static void mapping(IO &IO, GlobalVariable &GV) { 337e8d8bef9SDimitry Andric IO.mapRequired("Name", GV.Name); 338bdd1243dSDimitry Andric IO.mapOptional("Nullability", GV.Nullability, std::nullopt); 339e8d8bef9SDimitry Andric IO.mapOptional("Availability", GV.Availability.Mode, 340e8d8bef9SDimitry Andric APIAvailability::Available); 341e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef("")); 342e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", GV.SwiftPrivate); 343e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", GV.SwiftName, StringRef("")); 344e8d8bef9SDimitry Andric IO.mapOptional("Type", GV.Type, StringRef("")); 345e8d8bef9SDimitry Andric } 346e8d8bef9SDimitry Andric }; 347e8d8bef9SDimitry Andric } // namespace yaml 348e8d8bef9SDimitry Andric } // namespace llvm 349e8d8bef9SDimitry Andric 350e8d8bef9SDimitry Andric namespace { 351e8d8bef9SDimitry Andric struct EnumConstant { 352e8d8bef9SDimitry Andric StringRef Name; 353e8d8bef9SDimitry Andric AvailabilityItem Availability; 354bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 355e8d8bef9SDimitry Andric StringRef SwiftName; 356e8d8bef9SDimitry Andric }; 357e8d8bef9SDimitry Andric 358e8d8bef9SDimitry Andric typedef std::vector<EnumConstant> EnumConstantsSeq; 359e8d8bef9SDimitry Andric } // namespace 360e8d8bef9SDimitry Andric 361e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant) 362e8d8bef9SDimitry Andric 363e8d8bef9SDimitry Andric namespace llvm { 364e8d8bef9SDimitry Andric namespace yaml { 365e8d8bef9SDimitry Andric template <> struct MappingTraits<EnumConstant> { 366e8d8bef9SDimitry Andric static void mapping(IO &IO, EnumConstant &EC) { 367e8d8bef9SDimitry Andric IO.mapRequired("Name", EC.Name); 368e8d8bef9SDimitry Andric IO.mapOptional("Availability", EC.Availability.Mode, 369e8d8bef9SDimitry Andric APIAvailability::Available); 370e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef("")); 371e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", EC.SwiftPrivate); 372e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", EC.SwiftName, StringRef("")); 373e8d8bef9SDimitry Andric } 374e8d8bef9SDimitry Andric }; 375e8d8bef9SDimitry Andric } // namespace yaml 376e8d8bef9SDimitry Andric } // namespace llvm 377e8d8bef9SDimitry Andric 378e8d8bef9SDimitry Andric namespace { 379e8d8bef9SDimitry Andric /// Syntactic sugar for EnumExtensibility and FlagEnum 380e8d8bef9SDimitry Andric enum class EnumConvenienceAliasKind { 381e8d8bef9SDimitry Andric /// EnumExtensibility: none, FlagEnum: false 382e8d8bef9SDimitry Andric None, 383e8d8bef9SDimitry Andric /// EnumExtensibility: open, FlagEnum: false 384e8d8bef9SDimitry Andric CFEnum, 385e8d8bef9SDimitry Andric /// EnumExtensibility: open, FlagEnum: true 386e8d8bef9SDimitry Andric CFOptions, 387e8d8bef9SDimitry Andric /// EnumExtensibility: closed, FlagEnum: false 388e8d8bef9SDimitry Andric CFClosedEnum 389e8d8bef9SDimitry Andric }; 390e8d8bef9SDimitry Andric } // namespace 391e8d8bef9SDimitry Andric 392e8d8bef9SDimitry Andric namespace llvm { 393e8d8bef9SDimitry Andric namespace yaml { 394e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<EnumConvenienceAliasKind> { 395e8d8bef9SDimitry Andric static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) { 396e8d8bef9SDimitry Andric IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None); 397e8d8bef9SDimitry Andric IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum); 398e8d8bef9SDimitry Andric IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum); 399e8d8bef9SDimitry Andric IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions); 400e8d8bef9SDimitry Andric IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions); 401e8d8bef9SDimitry Andric IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); 402e8d8bef9SDimitry Andric IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); 403e8d8bef9SDimitry Andric } 404e8d8bef9SDimitry Andric }; 405e8d8bef9SDimitry Andric } // namespace yaml 406e8d8bef9SDimitry Andric } // namespace llvm 407e8d8bef9SDimitry Andric 408e8d8bef9SDimitry Andric namespace { 409e8d8bef9SDimitry Andric struct Tag { 410e8d8bef9SDimitry Andric StringRef Name; 411e8d8bef9SDimitry Andric AvailabilityItem Availability; 412e8d8bef9SDimitry Andric StringRef SwiftName; 413bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 414bdd1243dSDimitry Andric std::optional<StringRef> SwiftBridge; 415bdd1243dSDimitry Andric std::optional<StringRef> NSErrorDomain; 416*5f757f3fSDimitry Andric std::optional<std::string> SwiftImportAs; 417*5f757f3fSDimitry Andric std::optional<std::string> SwiftRetainOp; 418*5f757f3fSDimitry Andric std::optional<std::string> SwiftReleaseOp; 419bdd1243dSDimitry Andric std::optional<EnumExtensibilityKind> EnumExtensibility; 420bdd1243dSDimitry Andric std::optional<bool> FlagEnum; 421bdd1243dSDimitry Andric std::optional<EnumConvenienceAliasKind> EnumConvenienceKind; 422e8d8bef9SDimitry Andric }; 423e8d8bef9SDimitry Andric 424e8d8bef9SDimitry Andric typedef std::vector<Tag> TagsSeq; 425e8d8bef9SDimitry Andric } // namespace 426e8d8bef9SDimitry Andric 427e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) 428e8d8bef9SDimitry Andric 429e8d8bef9SDimitry Andric namespace llvm { 430e8d8bef9SDimitry Andric namespace yaml { 431e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> { 432e8d8bef9SDimitry Andric static void enumeration(IO &IO, EnumExtensibilityKind &EEK) { 433e8d8bef9SDimitry Andric IO.enumCase(EEK, "none", EnumExtensibilityKind::None); 434e8d8bef9SDimitry Andric IO.enumCase(EEK, "open", EnumExtensibilityKind::Open); 435e8d8bef9SDimitry Andric IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed); 436e8d8bef9SDimitry Andric } 437e8d8bef9SDimitry Andric }; 438e8d8bef9SDimitry Andric 439e8d8bef9SDimitry Andric template <> struct MappingTraits<Tag> { 440e8d8bef9SDimitry Andric static void mapping(IO &IO, Tag &T) { 441e8d8bef9SDimitry Andric IO.mapRequired("Name", T.Name); 442e8d8bef9SDimitry Andric IO.mapOptional("Availability", T.Availability.Mode, 443e8d8bef9SDimitry Andric APIAvailability::Available); 444e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 445e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 446e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 447e8d8bef9SDimitry Andric IO.mapOptional("SwiftBridge", T.SwiftBridge); 448e8d8bef9SDimitry Andric IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 449*5f757f3fSDimitry Andric IO.mapOptional("SwiftImportAs", T.SwiftImportAs); 450*5f757f3fSDimitry Andric IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp); 451*5f757f3fSDimitry Andric IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp); 452e8d8bef9SDimitry Andric IO.mapOptional("EnumExtensibility", T.EnumExtensibility); 453e8d8bef9SDimitry Andric IO.mapOptional("FlagEnum", T.FlagEnum); 454e8d8bef9SDimitry Andric IO.mapOptional("EnumKind", T.EnumConvenienceKind); 455e8d8bef9SDimitry Andric } 456e8d8bef9SDimitry Andric }; 457e8d8bef9SDimitry Andric } // namespace yaml 458e8d8bef9SDimitry Andric } // namespace llvm 459e8d8bef9SDimitry Andric 460e8d8bef9SDimitry Andric namespace { 461e8d8bef9SDimitry Andric struct Typedef { 462e8d8bef9SDimitry Andric StringRef Name; 463e8d8bef9SDimitry Andric AvailabilityItem Availability; 464e8d8bef9SDimitry Andric StringRef SwiftName; 465bdd1243dSDimitry Andric std::optional<bool> SwiftPrivate; 466bdd1243dSDimitry Andric std::optional<StringRef> SwiftBridge; 467bdd1243dSDimitry Andric std::optional<StringRef> NSErrorDomain; 468bdd1243dSDimitry Andric std::optional<SwiftNewTypeKind> SwiftType; 469e8d8bef9SDimitry Andric }; 470e8d8bef9SDimitry Andric 471e8d8bef9SDimitry Andric typedef std::vector<Typedef> TypedefsSeq; 472e8d8bef9SDimitry Andric } // namespace 473e8d8bef9SDimitry Andric 474e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef) 475e8d8bef9SDimitry Andric 476e8d8bef9SDimitry Andric namespace llvm { 477e8d8bef9SDimitry Andric namespace yaml { 478e8d8bef9SDimitry Andric template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> { 479e8d8bef9SDimitry Andric static void enumeration(IO &IO, SwiftNewTypeKind &SWK) { 480e8d8bef9SDimitry Andric IO.enumCase(SWK, "none", SwiftNewTypeKind::None); 481e8d8bef9SDimitry Andric IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct); 482e8d8bef9SDimitry Andric IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum); 483e8d8bef9SDimitry Andric } 484e8d8bef9SDimitry Andric }; 485e8d8bef9SDimitry Andric 486e8d8bef9SDimitry Andric template <> struct MappingTraits<Typedef> { 487e8d8bef9SDimitry Andric static void mapping(IO &IO, Typedef &T) { 488e8d8bef9SDimitry Andric IO.mapRequired("Name", T.Name); 489e8d8bef9SDimitry Andric IO.mapOptional("Availability", T.Availability.Mode, 490e8d8bef9SDimitry Andric APIAvailability::Available); 491e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 492e8d8bef9SDimitry Andric IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 493e8d8bef9SDimitry Andric IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 494e8d8bef9SDimitry Andric IO.mapOptional("SwiftBridge", T.SwiftBridge); 495e8d8bef9SDimitry Andric IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 496e8d8bef9SDimitry Andric IO.mapOptional("SwiftWrapper", T.SwiftType); 497e8d8bef9SDimitry Andric } 498e8d8bef9SDimitry Andric }; 499e8d8bef9SDimitry Andric } // namespace yaml 500e8d8bef9SDimitry Andric } // namespace llvm 501e8d8bef9SDimitry Andric 502e8d8bef9SDimitry Andric namespace { 503*5f757f3fSDimitry Andric struct Namespace; 504*5f757f3fSDimitry Andric typedef std::vector<Namespace> NamespacesSeq; 505*5f757f3fSDimitry Andric 506e8d8bef9SDimitry Andric struct TopLevelItems { 507e8d8bef9SDimitry Andric ClassesSeq Classes; 508e8d8bef9SDimitry Andric ClassesSeq Protocols; 509e8d8bef9SDimitry Andric FunctionsSeq Functions; 510e8d8bef9SDimitry Andric GlobalVariablesSeq Globals; 511e8d8bef9SDimitry Andric EnumConstantsSeq EnumConstants; 512e8d8bef9SDimitry Andric TagsSeq Tags; 513e8d8bef9SDimitry Andric TypedefsSeq Typedefs; 514*5f757f3fSDimitry Andric NamespacesSeq Namespaces; 515e8d8bef9SDimitry Andric }; 516e8d8bef9SDimitry Andric } // namespace 517e8d8bef9SDimitry Andric 518e8d8bef9SDimitry Andric namespace llvm { 519e8d8bef9SDimitry Andric namespace yaml { 520e8d8bef9SDimitry Andric static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) { 521e8d8bef9SDimitry Andric IO.mapOptional("Classes", TLI.Classes); 522e8d8bef9SDimitry Andric IO.mapOptional("Protocols", TLI.Protocols); 523e8d8bef9SDimitry Andric IO.mapOptional("Functions", TLI.Functions); 524e8d8bef9SDimitry Andric IO.mapOptional("Globals", TLI.Globals); 525e8d8bef9SDimitry Andric IO.mapOptional("Enumerators", TLI.EnumConstants); 526e8d8bef9SDimitry Andric IO.mapOptional("Tags", TLI.Tags); 527e8d8bef9SDimitry Andric IO.mapOptional("Typedefs", TLI.Typedefs); 528*5f757f3fSDimitry Andric IO.mapOptional("Namespaces", TLI.Namespaces); 529e8d8bef9SDimitry Andric } 530e8d8bef9SDimitry Andric } // namespace yaml 531e8d8bef9SDimitry Andric } // namespace llvm 532e8d8bef9SDimitry Andric 533e8d8bef9SDimitry Andric namespace { 534*5f757f3fSDimitry Andric struct Namespace { 535*5f757f3fSDimitry Andric StringRef Name; 536*5f757f3fSDimitry Andric AvailabilityItem Availability; 537*5f757f3fSDimitry Andric StringRef SwiftName; 538*5f757f3fSDimitry Andric std::optional<bool> SwiftPrivate; 539*5f757f3fSDimitry Andric TopLevelItems Items; 540*5f757f3fSDimitry Andric }; 541*5f757f3fSDimitry Andric } // namespace 542*5f757f3fSDimitry Andric 543*5f757f3fSDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace) 544*5f757f3fSDimitry Andric 545*5f757f3fSDimitry Andric namespace llvm { 546*5f757f3fSDimitry Andric namespace yaml { 547*5f757f3fSDimitry Andric template <> struct MappingTraits<Namespace> { 548*5f757f3fSDimitry Andric static void mapping(IO &IO, Namespace &T) { 549*5f757f3fSDimitry Andric IO.mapRequired("Name", T.Name); 550*5f757f3fSDimitry Andric IO.mapOptional("Availability", T.Availability.Mode, 551*5f757f3fSDimitry Andric APIAvailability::Available); 552*5f757f3fSDimitry Andric IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 553*5f757f3fSDimitry Andric IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 554*5f757f3fSDimitry Andric IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 555*5f757f3fSDimitry Andric mapTopLevelItems(IO, T.Items); 556*5f757f3fSDimitry Andric } 557*5f757f3fSDimitry Andric }; 558*5f757f3fSDimitry Andric } // namespace yaml 559*5f757f3fSDimitry Andric } // namespace llvm 560*5f757f3fSDimitry Andric 561*5f757f3fSDimitry Andric namespace { 562e8d8bef9SDimitry Andric struct Versioned { 563e8d8bef9SDimitry Andric VersionTuple Version; 564e8d8bef9SDimitry Andric TopLevelItems Items; 565e8d8bef9SDimitry Andric }; 566e8d8bef9SDimitry Andric 567e8d8bef9SDimitry Andric typedef std::vector<Versioned> VersionedSeq; 568e8d8bef9SDimitry Andric } // namespace 569e8d8bef9SDimitry Andric 570e8d8bef9SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned) 571e8d8bef9SDimitry Andric 572e8d8bef9SDimitry Andric namespace llvm { 573e8d8bef9SDimitry Andric namespace yaml { 574e8d8bef9SDimitry Andric template <> struct MappingTraits<Versioned> { 575e8d8bef9SDimitry Andric static void mapping(IO &IO, Versioned &V) { 576e8d8bef9SDimitry Andric IO.mapRequired("Version", V.Version); 577e8d8bef9SDimitry Andric mapTopLevelItems(IO, V.Items); 578e8d8bef9SDimitry Andric } 579e8d8bef9SDimitry Andric }; 580e8d8bef9SDimitry Andric } // namespace yaml 581e8d8bef9SDimitry Andric } // namespace llvm 582e8d8bef9SDimitry Andric 583e8d8bef9SDimitry Andric namespace { 584e8d8bef9SDimitry Andric struct Module { 585e8d8bef9SDimitry Andric StringRef Name; 586e8d8bef9SDimitry Andric AvailabilityItem Availability; 587e8d8bef9SDimitry Andric TopLevelItems TopLevel; 588e8d8bef9SDimitry Andric VersionedSeq SwiftVersions; 589e8d8bef9SDimitry Andric 590bdd1243dSDimitry Andric std::optional<bool> SwiftInferImportAsMember; 591e8d8bef9SDimitry Andric 592fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 593e8d8bef9SDimitry Andric LLVM_DUMP_METHOD void dump() /*const*/; 594fe6060f1SDimitry Andric #endif 595e8d8bef9SDimitry Andric }; 596e8d8bef9SDimitry Andric } // namespace 597e8d8bef9SDimitry Andric 598e8d8bef9SDimitry Andric namespace llvm { 599e8d8bef9SDimitry Andric namespace yaml { 600e8d8bef9SDimitry Andric template <> struct MappingTraits<Module> { 601e8d8bef9SDimitry Andric static void mapping(IO &IO, Module &M) { 602e8d8bef9SDimitry Andric IO.mapRequired("Name", M.Name); 603e8d8bef9SDimitry Andric IO.mapOptional("Availability", M.Availability.Mode, 604e8d8bef9SDimitry Andric APIAvailability::Available); 605e8d8bef9SDimitry Andric IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 606e8d8bef9SDimitry Andric IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember); 607e8d8bef9SDimitry Andric mapTopLevelItems(IO, M.TopLevel); 608e8d8bef9SDimitry Andric IO.mapOptional("SwiftVersions", M.SwiftVersions); 609e8d8bef9SDimitry Andric } 610e8d8bef9SDimitry Andric }; 611e8d8bef9SDimitry Andric } // namespace yaml 612e8d8bef9SDimitry Andric } // namespace llvm 613e8d8bef9SDimitry Andric 614fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 615fe6060f1SDimitry Andric LLVM_DUMP_METHOD void Module::dump() { 616e8d8bef9SDimitry Andric llvm::yaml::Output OS(llvm::errs()); 617e8d8bef9SDimitry Andric OS << *this; 618e8d8bef9SDimitry Andric } 619fe6060f1SDimitry Andric #endif 620e8d8bef9SDimitry Andric 621e8d8bef9SDimitry Andric namespace { 622e8d8bef9SDimitry Andric bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag, 623e8d8bef9SDimitry Andric void *DiagContext) { 624e8d8bef9SDimitry Andric llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext); 625e8d8bef9SDimitry Andric IS >> M; 626e8d8bef9SDimitry Andric return static_cast<bool>(IS.error()); 627e8d8bef9SDimitry Andric } 628e8d8bef9SDimitry Andric } // namespace 629e8d8bef9SDimitry Andric 630e8d8bef9SDimitry Andric bool clang::api_notes::parseAndDumpAPINotes(StringRef YI, 631e8d8bef9SDimitry Andric llvm::raw_ostream &OS) { 632e8d8bef9SDimitry Andric Module M; 633e8d8bef9SDimitry Andric if (parseAPINotes(YI, M, nullptr, nullptr)) 634e8d8bef9SDimitry Andric return true; 635e8d8bef9SDimitry Andric 636e8d8bef9SDimitry Andric llvm::yaml::Output YOS(OS); 637e8d8bef9SDimitry Andric YOS << M; 638e8d8bef9SDimitry Andric 639e8d8bef9SDimitry Andric return false; 640e8d8bef9SDimitry Andric } 641*5f757f3fSDimitry Andric 642*5f757f3fSDimitry Andric namespace { 643*5f757f3fSDimitry Andric using namespace api_notes; 644*5f757f3fSDimitry Andric 645*5f757f3fSDimitry Andric class YAMLConverter { 646*5f757f3fSDimitry Andric const Module &M; 647*5f757f3fSDimitry Andric APINotesWriter Writer; 648*5f757f3fSDimitry Andric llvm::raw_ostream &OS; 649*5f757f3fSDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler; 650*5f757f3fSDimitry Andric void *DiagHandlerCtxt; 651*5f757f3fSDimitry Andric bool ErrorOccured; 652*5f757f3fSDimitry Andric 653*5f757f3fSDimitry Andric /// Emit a diagnostic 654*5f757f3fSDimitry Andric bool emitError(llvm::Twine Message) { 655*5f757f3fSDimitry Andric DiagHandler( 656*5f757f3fSDimitry Andric llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()), 657*5f757f3fSDimitry Andric DiagHandlerCtxt); 658*5f757f3fSDimitry Andric ErrorOccured = true; 659*5f757f3fSDimitry Andric return true; 660*5f757f3fSDimitry Andric } 661*5f757f3fSDimitry Andric 662*5f757f3fSDimitry Andric public: 663*5f757f3fSDimitry Andric YAMLConverter(const Module &TheModule, const FileEntry *SourceFile, 664*5f757f3fSDimitry Andric llvm::raw_ostream &OS, 665*5f757f3fSDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler, 666*5f757f3fSDimitry Andric void *DiagHandlerCtxt) 667*5f757f3fSDimitry Andric : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS), 668*5f757f3fSDimitry Andric DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt), 669*5f757f3fSDimitry Andric ErrorOccured(false) {} 670*5f757f3fSDimitry Andric 671*5f757f3fSDimitry Andric void convertAvailability(const AvailabilityItem &Availability, 672*5f757f3fSDimitry Andric CommonEntityInfo &CEI, llvm::StringRef APIName) { 673*5f757f3fSDimitry Andric // Populate the unavailability information. 674*5f757f3fSDimitry Andric CEI.Unavailable = (Availability.Mode == APIAvailability::None); 675*5f757f3fSDimitry Andric CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift); 676*5f757f3fSDimitry Andric if (CEI.Unavailable || CEI.UnavailableInSwift) { 677*5f757f3fSDimitry Andric CEI.UnavailableMsg = std::string(Availability.Msg); 678*5f757f3fSDimitry Andric } else { 679*5f757f3fSDimitry Andric if (!Availability.Msg.empty()) 680*5f757f3fSDimitry Andric emitError(llvm::Twine("availability message for available API '") + 681*5f757f3fSDimitry Andric APIName + "' will not be used"); 682*5f757f3fSDimitry Andric } 683*5f757f3fSDimitry Andric } 684*5f757f3fSDimitry Andric 685*5f757f3fSDimitry Andric void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) { 686*5f757f3fSDimitry Andric for (const auto &P : Params) { 687*5f757f3fSDimitry Andric ParamInfo PI; 688*5f757f3fSDimitry Andric if (P.Nullability) 689*5f757f3fSDimitry Andric PI.setNullabilityAudited(*P.Nullability); 690*5f757f3fSDimitry Andric PI.setNoEscape(P.NoEscape); 691*5f757f3fSDimitry Andric PI.setType(std::string(P.Type)); 692*5f757f3fSDimitry Andric PI.setRetainCountConvention(P.RetainCountConvention); 693*5f757f3fSDimitry Andric if (OutInfo.Params.size() <= P.Position) 694*5f757f3fSDimitry Andric OutInfo.Params.resize(P.Position + 1); 695*5f757f3fSDimitry Andric OutInfo.Params[P.Position] |= PI; 696*5f757f3fSDimitry Andric } 697*5f757f3fSDimitry Andric } 698*5f757f3fSDimitry Andric 699*5f757f3fSDimitry Andric void convertNullability(const NullabilitySeq &Nullability, 700*5f757f3fSDimitry Andric std::optional<NullabilityKind> ReturnNullability, 701*5f757f3fSDimitry Andric FunctionInfo &OutInfo, llvm::StringRef APIName) { 702*5f757f3fSDimitry Andric if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) { 703*5f757f3fSDimitry Andric emitError(llvm::Twine("nullability info for '") + APIName + 704*5f757f3fSDimitry Andric "' does not fit"); 705*5f757f3fSDimitry Andric return; 706*5f757f3fSDimitry Andric } 707*5f757f3fSDimitry Andric 708*5f757f3fSDimitry Andric bool audited = false; 709*5f757f3fSDimitry Andric unsigned int idx = 1; 710*5f757f3fSDimitry Andric for (const auto &N : Nullability) 711*5f757f3fSDimitry Andric OutInfo.addTypeInfo(idx++, N); 712*5f757f3fSDimitry Andric audited = Nullability.size() > 0 || ReturnNullability; 713*5f757f3fSDimitry Andric if (audited) 714*5f757f3fSDimitry Andric OutInfo.addTypeInfo(0, ReturnNullability ? *ReturnNullability 715*5f757f3fSDimitry Andric : NullabilityKind::NonNull); 716*5f757f3fSDimitry Andric if (!audited) 717*5f757f3fSDimitry Andric return; 718*5f757f3fSDimitry Andric OutInfo.NullabilityAudited = audited; 719*5f757f3fSDimitry Andric OutInfo.NumAdjustedNullable = idx; 720*5f757f3fSDimitry Andric } 721*5f757f3fSDimitry Andric 722*5f757f3fSDimitry Andric /// Convert the common parts of an entity from YAML. 723*5f757f3fSDimitry Andric template <typename T> 724*5f757f3fSDimitry Andric void convertCommonEntity(const T &Common, CommonEntityInfo &Info, 725*5f757f3fSDimitry Andric StringRef APIName) { 726*5f757f3fSDimitry Andric convertAvailability(Common.Availability, Info, APIName); 727*5f757f3fSDimitry Andric Info.setSwiftPrivate(Common.SwiftPrivate); 728*5f757f3fSDimitry Andric Info.SwiftName = std::string(Common.SwiftName); 729*5f757f3fSDimitry Andric } 730*5f757f3fSDimitry Andric 731*5f757f3fSDimitry Andric /// Convert the common parts of a type entity from YAML. 732*5f757f3fSDimitry Andric template <typename T> 733*5f757f3fSDimitry Andric void convertCommonType(const T &Common, CommonTypeInfo &Info, 734*5f757f3fSDimitry Andric StringRef APIName) { 735*5f757f3fSDimitry Andric convertCommonEntity(Common, Info, APIName); 736*5f757f3fSDimitry Andric if (Common.SwiftBridge) 737*5f757f3fSDimitry Andric Info.setSwiftBridge(std::string(*Common.SwiftBridge)); 738*5f757f3fSDimitry Andric Info.setNSErrorDomain(Common.NSErrorDomain); 739*5f757f3fSDimitry Andric } 740*5f757f3fSDimitry Andric 741*5f757f3fSDimitry Andric // Translate from Method into ObjCMethodInfo and write it out. 742*5f757f3fSDimitry Andric void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName, 743*5f757f3fSDimitry Andric VersionTuple SwiftVersion) { 744*5f757f3fSDimitry Andric ObjCMethodInfo MI; 745*5f757f3fSDimitry Andric convertCommonEntity(M, MI, M.Selector); 746*5f757f3fSDimitry Andric 747*5f757f3fSDimitry Andric // Check if the selector ends with ':' to determine if it takes arguments. 748*5f757f3fSDimitry Andric bool takesArguments = M.Selector.ends_with(":"); 749*5f757f3fSDimitry Andric 750*5f757f3fSDimitry Andric // Split the selector into pieces. 751*5f757f3fSDimitry Andric llvm::SmallVector<StringRef, 4> Args; 752*5f757f3fSDimitry Andric M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false); 753*5f757f3fSDimitry Andric if (!takesArguments && Args.size() > 1) { 754*5f757f3fSDimitry Andric emitError("selector '" + M.Selector + "' is missing a ':' at the end"); 755*5f757f3fSDimitry Andric return; 756*5f757f3fSDimitry Andric } 757*5f757f3fSDimitry Andric 758*5f757f3fSDimitry Andric // Construct ObjCSelectorRef. 759*5f757f3fSDimitry Andric api_notes::ObjCSelectorRef Selector; 760*5f757f3fSDimitry Andric Selector.NumArgs = !takesArguments ? 0 : Args.size(); 761*5f757f3fSDimitry Andric Selector.Identifiers = Args; 762*5f757f3fSDimitry Andric 763*5f757f3fSDimitry Andric // Translate the initializer info. 764*5f757f3fSDimitry Andric MI.DesignatedInit = M.DesignatedInit; 765*5f757f3fSDimitry Andric MI.RequiredInit = M.Required; 766*5f757f3fSDimitry Andric if (M.FactoryAsInit != FactoryAsInitKind::Infer) 767*5f757f3fSDimitry Andric emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead"); 768*5f757f3fSDimitry Andric 769*5f757f3fSDimitry Andric MI.ResultType = std::string(M.ResultType); 770*5f757f3fSDimitry Andric 771*5f757f3fSDimitry Andric // Translate parameter information. 772*5f757f3fSDimitry Andric convertParams(M.Params, MI); 773*5f757f3fSDimitry Andric 774*5f757f3fSDimitry Andric // Translate nullability info. 775*5f757f3fSDimitry Andric convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector); 776*5f757f3fSDimitry Andric 777*5f757f3fSDimitry Andric MI.setRetainCountConvention(M.RetainCountConvention); 778*5f757f3fSDimitry Andric 779*5f757f3fSDimitry Andric // Write it. 780*5f757f3fSDimitry Andric Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI, 781*5f757f3fSDimitry Andric SwiftVersion); 782*5f757f3fSDimitry Andric } 783*5f757f3fSDimitry Andric 784*5f757f3fSDimitry Andric void convertContext(std::optional<ContextID> ParentContextID, const Class &C, 785*5f757f3fSDimitry Andric ContextKind Kind, VersionTuple SwiftVersion) { 786*5f757f3fSDimitry Andric // Write the class. 787*5f757f3fSDimitry Andric ObjCContextInfo CI; 788*5f757f3fSDimitry Andric convertCommonType(C, CI, C.Name); 789*5f757f3fSDimitry Andric 790*5f757f3fSDimitry Andric if (C.AuditedForNullability) 791*5f757f3fSDimitry Andric CI.setDefaultNullability(NullabilityKind::NonNull); 792*5f757f3fSDimitry Andric if (C.SwiftImportAsNonGeneric) 793*5f757f3fSDimitry Andric CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric); 794*5f757f3fSDimitry Andric if (C.SwiftObjCMembers) 795*5f757f3fSDimitry Andric CI.setSwiftObjCMembers(*C.SwiftObjCMembers); 796*5f757f3fSDimitry Andric 797*5f757f3fSDimitry Andric ContextID CtxID = 798*5f757f3fSDimitry Andric Writer.addObjCContext(ParentContextID, C.Name, Kind, CI, SwiftVersion); 799*5f757f3fSDimitry Andric 800*5f757f3fSDimitry Andric // Write all methods. 801*5f757f3fSDimitry Andric llvm::StringMap<std::pair<bool, bool>> KnownMethods; 802*5f757f3fSDimitry Andric for (const auto &method : C.Methods) { 803*5f757f3fSDimitry Andric // Check for duplicate method definitions. 804*5f757f3fSDimitry Andric bool IsInstanceMethod = method.Kind == MethodKind::Instance; 805*5f757f3fSDimitry Andric bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first 806*5f757f3fSDimitry Andric : KnownMethods[method.Selector].second; 807*5f757f3fSDimitry Andric if (Known) { 808*5f757f3fSDimitry Andric emitError(llvm::Twine("duplicate definition of method '") + 809*5f757f3fSDimitry Andric (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " + 810*5f757f3fSDimitry Andric method.Selector + "]'"); 811*5f757f3fSDimitry Andric continue; 812*5f757f3fSDimitry Andric } 813*5f757f3fSDimitry Andric Known = true; 814*5f757f3fSDimitry Andric 815*5f757f3fSDimitry Andric convertMethod(method, CtxID, C.Name, SwiftVersion); 816*5f757f3fSDimitry Andric } 817*5f757f3fSDimitry Andric 818*5f757f3fSDimitry Andric // Write all properties. 819*5f757f3fSDimitry Andric llvm::StringSet<> KnownInstanceProperties; 820*5f757f3fSDimitry Andric llvm::StringSet<> KnownClassProperties; 821*5f757f3fSDimitry Andric for (const auto &Property : C.Properties) { 822*5f757f3fSDimitry Andric // Check for duplicate property definitions. 823*5f757f3fSDimitry Andric if ((!Property.Kind || *Property.Kind == MethodKind::Instance) && 824*5f757f3fSDimitry Andric !KnownInstanceProperties.insert(Property.Name).second) { 825*5f757f3fSDimitry Andric emitError(llvm::Twine("duplicate definition of instance property '") + 826*5f757f3fSDimitry Andric C.Name + "." + Property.Name + "'"); 827*5f757f3fSDimitry Andric continue; 828*5f757f3fSDimitry Andric } 829*5f757f3fSDimitry Andric 830*5f757f3fSDimitry Andric if ((!Property.Kind || *Property.Kind == MethodKind::Class) && 831*5f757f3fSDimitry Andric !KnownClassProperties.insert(Property.Name).second) { 832*5f757f3fSDimitry Andric emitError(llvm::Twine("duplicate definition of class property '") + 833*5f757f3fSDimitry Andric C.Name + "." + Property.Name + "'"); 834*5f757f3fSDimitry Andric continue; 835*5f757f3fSDimitry Andric } 836*5f757f3fSDimitry Andric 837*5f757f3fSDimitry Andric // Translate from Property into ObjCPropertyInfo. 838*5f757f3fSDimitry Andric ObjCPropertyInfo PI; 839*5f757f3fSDimitry Andric convertAvailability(Property.Availability, PI, Property.Name); 840*5f757f3fSDimitry Andric PI.setSwiftPrivate(Property.SwiftPrivate); 841*5f757f3fSDimitry Andric PI.SwiftName = std::string(Property.SwiftName); 842*5f757f3fSDimitry Andric if (Property.Nullability) 843*5f757f3fSDimitry Andric PI.setNullabilityAudited(*Property.Nullability); 844*5f757f3fSDimitry Andric if (Property.SwiftImportAsAccessors) 845*5f757f3fSDimitry Andric PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors); 846*5f757f3fSDimitry Andric PI.setType(std::string(Property.Type)); 847*5f757f3fSDimitry Andric 848*5f757f3fSDimitry Andric // Add both instance and class properties with this name. 849*5f757f3fSDimitry Andric if (Property.Kind) { 850*5f757f3fSDimitry Andric Writer.addObjCProperty(CtxID, Property.Name, 851*5f757f3fSDimitry Andric *Property.Kind == MethodKind::Instance, PI, 852*5f757f3fSDimitry Andric SwiftVersion); 853*5f757f3fSDimitry Andric } else { 854*5f757f3fSDimitry Andric Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion); 855*5f757f3fSDimitry Andric Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion); 856*5f757f3fSDimitry Andric } 857*5f757f3fSDimitry Andric } 858*5f757f3fSDimitry Andric } 859*5f757f3fSDimitry Andric 860*5f757f3fSDimitry Andric void convertNamespaceContext(std::optional<ContextID> ParentContextID, 861*5f757f3fSDimitry Andric const Namespace &TheNamespace, 862*5f757f3fSDimitry Andric VersionTuple SwiftVersion) { 863*5f757f3fSDimitry Andric // Write the namespace. 864*5f757f3fSDimitry Andric ObjCContextInfo CI; 865*5f757f3fSDimitry Andric convertCommonEntity(TheNamespace, CI, TheNamespace.Name); 866*5f757f3fSDimitry Andric 867*5f757f3fSDimitry Andric ContextID CtxID = 868*5f757f3fSDimitry Andric Writer.addObjCContext(ParentContextID, TheNamespace.Name, 869*5f757f3fSDimitry Andric ContextKind::Namespace, CI, SwiftVersion); 870*5f757f3fSDimitry Andric 871*5f757f3fSDimitry Andric convertTopLevelItems(Context(CtxID, ContextKind::Namespace), 872*5f757f3fSDimitry Andric TheNamespace.Items, SwiftVersion); 873*5f757f3fSDimitry Andric } 874*5f757f3fSDimitry Andric 875*5f757f3fSDimitry Andric void convertTopLevelItems(std::optional<Context> Ctx, 876*5f757f3fSDimitry Andric const TopLevelItems &TLItems, 877*5f757f3fSDimitry Andric VersionTuple SwiftVersion) { 878*5f757f3fSDimitry Andric std::optional<ContextID> CtxID = 879*5f757f3fSDimitry Andric Ctx ? std::optional(Ctx->id) : std::nullopt; 880*5f757f3fSDimitry Andric 881*5f757f3fSDimitry Andric // Write all classes. 882*5f757f3fSDimitry Andric llvm::StringSet<> KnownClasses; 883*5f757f3fSDimitry Andric for (const auto &Class : TLItems.Classes) { 884*5f757f3fSDimitry Andric // Check for duplicate class definitions. 885*5f757f3fSDimitry Andric if (!KnownClasses.insert(Class.Name).second) { 886*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of class '") + Class.Name + 887*5f757f3fSDimitry Andric "'"); 888*5f757f3fSDimitry Andric continue; 889*5f757f3fSDimitry Andric } 890*5f757f3fSDimitry Andric 891*5f757f3fSDimitry Andric convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion); 892*5f757f3fSDimitry Andric } 893*5f757f3fSDimitry Andric 894*5f757f3fSDimitry Andric // Write all protocols. 895*5f757f3fSDimitry Andric llvm::StringSet<> KnownProtocols; 896*5f757f3fSDimitry Andric for (const auto &Protocol : TLItems.Protocols) { 897*5f757f3fSDimitry Andric // Check for duplicate protocol definitions. 898*5f757f3fSDimitry Andric if (!KnownProtocols.insert(Protocol.Name).second) { 899*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of protocol '") + 900*5f757f3fSDimitry Andric Protocol.Name + "'"); 901*5f757f3fSDimitry Andric continue; 902*5f757f3fSDimitry Andric } 903*5f757f3fSDimitry Andric 904*5f757f3fSDimitry Andric convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion); 905*5f757f3fSDimitry Andric } 906*5f757f3fSDimitry Andric 907*5f757f3fSDimitry Andric // Write all namespaces. 908*5f757f3fSDimitry Andric llvm::StringSet<> KnownNamespaces; 909*5f757f3fSDimitry Andric for (const auto &Namespace : TLItems.Namespaces) { 910*5f757f3fSDimitry Andric // Check for duplicate namespace definitions. 911*5f757f3fSDimitry Andric if (!KnownNamespaces.insert(Namespace.Name).second) { 912*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of namespace '") + 913*5f757f3fSDimitry Andric Namespace.Name + "'"); 914*5f757f3fSDimitry Andric continue; 915*5f757f3fSDimitry Andric } 916*5f757f3fSDimitry Andric 917*5f757f3fSDimitry Andric convertNamespaceContext(CtxID, Namespace, SwiftVersion); 918*5f757f3fSDimitry Andric } 919*5f757f3fSDimitry Andric 920*5f757f3fSDimitry Andric // Write all global variables. 921*5f757f3fSDimitry Andric llvm::StringSet<> KnownGlobals; 922*5f757f3fSDimitry Andric for (const auto &Global : TLItems.Globals) { 923*5f757f3fSDimitry Andric // Check for duplicate global variables. 924*5f757f3fSDimitry Andric if (!KnownGlobals.insert(Global.Name).second) { 925*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of global variable '") + 926*5f757f3fSDimitry Andric Global.Name + "'"); 927*5f757f3fSDimitry Andric continue; 928*5f757f3fSDimitry Andric } 929*5f757f3fSDimitry Andric 930*5f757f3fSDimitry Andric GlobalVariableInfo GVI; 931*5f757f3fSDimitry Andric convertAvailability(Global.Availability, GVI, Global.Name); 932*5f757f3fSDimitry Andric GVI.setSwiftPrivate(Global.SwiftPrivate); 933*5f757f3fSDimitry Andric GVI.SwiftName = std::string(Global.SwiftName); 934*5f757f3fSDimitry Andric if (Global.Nullability) 935*5f757f3fSDimitry Andric GVI.setNullabilityAudited(*Global.Nullability); 936*5f757f3fSDimitry Andric GVI.setType(std::string(Global.Type)); 937*5f757f3fSDimitry Andric Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion); 938*5f757f3fSDimitry Andric } 939*5f757f3fSDimitry Andric 940*5f757f3fSDimitry Andric // Write all global functions. 941*5f757f3fSDimitry Andric llvm::StringSet<> KnownFunctions; 942*5f757f3fSDimitry Andric for (const auto &Function : TLItems.Functions) { 943*5f757f3fSDimitry Andric // Check for duplicate global functions. 944*5f757f3fSDimitry Andric if (!KnownFunctions.insert(Function.Name).second) { 945*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of global function '") + 946*5f757f3fSDimitry Andric Function.Name + "'"); 947*5f757f3fSDimitry Andric continue; 948*5f757f3fSDimitry Andric } 949*5f757f3fSDimitry Andric 950*5f757f3fSDimitry Andric GlobalFunctionInfo GFI; 951*5f757f3fSDimitry Andric convertAvailability(Function.Availability, GFI, Function.Name); 952*5f757f3fSDimitry Andric GFI.setSwiftPrivate(Function.SwiftPrivate); 953*5f757f3fSDimitry Andric GFI.SwiftName = std::string(Function.SwiftName); 954*5f757f3fSDimitry Andric convertParams(Function.Params, GFI); 955*5f757f3fSDimitry Andric convertNullability(Function.Nullability, Function.NullabilityOfRet, GFI, 956*5f757f3fSDimitry Andric Function.Name); 957*5f757f3fSDimitry Andric GFI.ResultType = std::string(Function.ResultType); 958*5f757f3fSDimitry Andric GFI.setRetainCountConvention(Function.RetainCountConvention); 959*5f757f3fSDimitry Andric Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion); 960*5f757f3fSDimitry Andric } 961*5f757f3fSDimitry Andric 962*5f757f3fSDimitry Andric // Write all enumerators. 963*5f757f3fSDimitry Andric llvm::StringSet<> KnownEnumConstants; 964*5f757f3fSDimitry Andric for (const auto &EnumConstant : TLItems.EnumConstants) { 965*5f757f3fSDimitry Andric // Check for duplicate enumerators 966*5f757f3fSDimitry Andric if (!KnownEnumConstants.insert(EnumConstant.Name).second) { 967*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of enumerator '") + 968*5f757f3fSDimitry Andric EnumConstant.Name + "'"); 969*5f757f3fSDimitry Andric continue; 970*5f757f3fSDimitry Andric } 971*5f757f3fSDimitry Andric 972*5f757f3fSDimitry Andric EnumConstantInfo ECI; 973*5f757f3fSDimitry Andric convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name); 974*5f757f3fSDimitry Andric ECI.setSwiftPrivate(EnumConstant.SwiftPrivate); 975*5f757f3fSDimitry Andric ECI.SwiftName = std::string(EnumConstant.SwiftName); 976*5f757f3fSDimitry Andric Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion); 977*5f757f3fSDimitry Andric } 978*5f757f3fSDimitry Andric 979*5f757f3fSDimitry Andric // Write all tags. 980*5f757f3fSDimitry Andric llvm::StringSet<> KnownTags; 981*5f757f3fSDimitry Andric for (const auto &Tag : TLItems.Tags) { 982*5f757f3fSDimitry Andric // Check for duplicate tag definitions. 983*5f757f3fSDimitry Andric if (!KnownTags.insert(Tag.Name).second) { 984*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name + 985*5f757f3fSDimitry Andric "'"); 986*5f757f3fSDimitry Andric continue; 987*5f757f3fSDimitry Andric } 988*5f757f3fSDimitry Andric 989*5f757f3fSDimitry Andric TagInfo TI; 990*5f757f3fSDimitry Andric convertCommonType(Tag, TI, Tag.Name); 991*5f757f3fSDimitry Andric 992*5f757f3fSDimitry Andric if ((Tag.SwiftRetainOp || Tag.SwiftReleaseOp) && !Tag.SwiftImportAs) { 993*5f757f3fSDimitry Andric emitError(llvm::Twine("should declare SwiftImportAs to use " 994*5f757f3fSDimitry Andric "SwiftRetainOp and SwiftReleaseOp (for ") + 995*5f757f3fSDimitry Andric Tag.Name + ")"); 996*5f757f3fSDimitry Andric continue; 997*5f757f3fSDimitry Andric } 998*5f757f3fSDimitry Andric if (Tag.SwiftReleaseOp.has_value() != Tag.SwiftRetainOp.has_value()) { 999*5f757f3fSDimitry Andric emitError(llvm::Twine("should declare both SwiftReleaseOp and " 1000*5f757f3fSDimitry Andric "SwiftRetainOp (for ") + 1001*5f757f3fSDimitry Andric Tag.Name + ")"); 1002*5f757f3fSDimitry Andric continue; 1003*5f757f3fSDimitry Andric } 1004*5f757f3fSDimitry Andric 1005*5f757f3fSDimitry Andric if (Tag.SwiftImportAs) 1006*5f757f3fSDimitry Andric TI.SwiftImportAs = Tag.SwiftImportAs; 1007*5f757f3fSDimitry Andric if (Tag.SwiftRetainOp) 1008*5f757f3fSDimitry Andric TI.SwiftRetainOp = Tag.SwiftRetainOp; 1009*5f757f3fSDimitry Andric if (Tag.SwiftReleaseOp) 1010*5f757f3fSDimitry Andric TI.SwiftReleaseOp = Tag.SwiftReleaseOp; 1011*5f757f3fSDimitry Andric 1012*5f757f3fSDimitry Andric if (Tag.EnumConvenienceKind) { 1013*5f757f3fSDimitry Andric if (Tag.EnumExtensibility) { 1014*5f757f3fSDimitry Andric emitError( 1015*5f757f3fSDimitry Andric llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") + 1016*5f757f3fSDimitry Andric Tag.Name + ")"); 1017*5f757f3fSDimitry Andric continue; 1018*5f757f3fSDimitry Andric } 1019*5f757f3fSDimitry Andric if (Tag.FlagEnum) { 1020*5f757f3fSDimitry Andric emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") + 1021*5f757f3fSDimitry Andric Tag.Name + ")"); 1022*5f757f3fSDimitry Andric continue; 1023*5f757f3fSDimitry Andric } 1024*5f757f3fSDimitry Andric switch (*Tag.EnumConvenienceKind) { 1025*5f757f3fSDimitry Andric case EnumConvenienceAliasKind::None: 1026*5f757f3fSDimitry Andric TI.EnumExtensibility = EnumExtensibilityKind::None; 1027*5f757f3fSDimitry Andric TI.setFlagEnum(false); 1028*5f757f3fSDimitry Andric break; 1029*5f757f3fSDimitry Andric case EnumConvenienceAliasKind::CFEnum: 1030*5f757f3fSDimitry Andric TI.EnumExtensibility = EnumExtensibilityKind::Open; 1031*5f757f3fSDimitry Andric TI.setFlagEnum(false); 1032*5f757f3fSDimitry Andric break; 1033*5f757f3fSDimitry Andric case EnumConvenienceAliasKind::CFOptions: 1034*5f757f3fSDimitry Andric TI.EnumExtensibility = EnumExtensibilityKind::Open; 1035*5f757f3fSDimitry Andric TI.setFlagEnum(true); 1036*5f757f3fSDimitry Andric break; 1037*5f757f3fSDimitry Andric case EnumConvenienceAliasKind::CFClosedEnum: 1038*5f757f3fSDimitry Andric TI.EnumExtensibility = EnumExtensibilityKind::Closed; 1039*5f757f3fSDimitry Andric TI.setFlagEnum(false); 1040*5f757f3fSDimitry Andric break; 1041*5f757f3fSDimitry Andric } 1042*5f757f3fSDimitry Andric } else { 1043*5f757f3fSDimitry Andric TI.EnumExtensibility = Tag.EnumExtensibility; 1044*5f757f3fSDimitry Andric TI.setFlagEnum(Tag.FlagEnum); 1045*5f757f3fSDimitry Andric } 1046*5f757f3fSDimitry Andric 1047*5f757f3fSDimitry Andric Writer.addTag(Ctx, Tag.Name, TI, SwiftVersion); 1048*5f757f3fSDimitry Andric } 1049*5f757f3fSDimitry Andric 1050*5f757f3fSDimitry Andric // Write all typedefs. 1051*5f757f3fSDimitry Andric llvm::StringSet<> KnownTypedefs; 1052*5f757f3fSDimitry Andric for (const auto &Typedef : TLItems.Typedefs) { 1053*5f757f3fSDimitry Andric // Check for duplicate typedef definitions. 1054*5f757f3fSDimitry Andric if (!KnownTypedefs.insert(Typedef.Name).second) { 1055*5f757f3fSDimitry Andric emitError(llvm::Twine("multiple definitions of typedef '") + 1056*5f757f3fSDimitry Andric Typedef.Name + "'"); 1057*5f757f3fSDimitry Andric continue; 1058*5f757f3fSDimitry Andric } 1059*5f757f3fSDimitry Andric 1060*5f757f3fSDimitry Andric TypedefInfo TInfo; 1061*5f757f3fSDimitry Andric convertCommonType(Typedef, TInfo, Typedef.Name); 1062*5f757f3fSDimitry Andric TInfo.SwiftWrapper = Typedef.SwiftType; 1063*5f757f3fSDimitry Andric 1064*5f757f3fSDimitry Andric Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion); 1065*5f757f3fSDimitry Andric } 1066*5f757f3fSDimitry Andric } 1067*5f757f3fSDimitry Andric 1068*5f757f3fSDimitry Andric bool convertModule() { 1069*5f757f3fSDimitry Andric // Write the top-level items. 1070*5f757f3fSDimitry Andric convertTopLevelItems(/* context */ std::nullopt, M.TopLevel, 1071*5f757f3fSDimitry Andric VersionTuple()); 1072*5f757f3fSDimitry Andric 1073*5f757f3fSDimitry Andric // Convert the versioned information. 1074*5f757f3fSDimitry Andric for (const auto &Versioned : M.SwiftVersions) 1075*5f757f3fSDimitry Andric convertTopLevelItems(/* context */ std::nullopt, Versioned.Items, 1076*5f757f3fSDimitry Andric Versioned.Version); 1077*5f757f3fSDimitry Andric 1078*5f757f3fSDimitry Andric if (!ErrorOccured) 1079*5f757f3fSDimitry Andric Writer.writeToStream(OS); 1080*5f757f3fSDimitry Andric 1081*5f757f3fSDimitry Andric return ErrorOccured; 1082*5f757f3fSDimitry Andric } 1083*5f757f3fSDimitry Andric }; 1084*5f757f3fSDimitry Andric } // namespace 1085*5f757f3fSDimitry Andric 1086*5f757f3fSDimitry Andric static bool compile(const Module &M, const FileEntry *SourceFile, 1087*5f757f3fSDimitry Andric llvm::raw_ostream &OS, 1088*5f757f3fSDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler, 1089*5f757f3fSDimitry Andric void *DiagHandlerCtxt) { 1090*5f757f3fSDimitry Andric YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt); 1091*5f757f3fSDimitry Andric return C.convertModule(); 1092*5f757f3fSDimitry Andric } 1093*5f757f3fSDimitry Andric 1094*5f757f3fSDimitry Andric /// Simple diagnostic handler that prints diagnostics to standard error. 1095*5f757f3fSDimitry Andric static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) { 1096*5f757f3fSDimitry Andric Diag.print(nullptr, llvm::errs()); 1097*5f757f3fSDimitry Andric } 1098*5f757f3fSDimitry Andric 1099*5f757f3fSDimitry Andric bool api_notes::compileAPINotes(StringRef YAMLInput, 1100*5f757f3fSDimitry Andric const FileEntry *SourceFile, 1101*5f757f3fSDimitry Andric llvm::raw_ostream &OS, 1102*5f757f3fSDimitry Andric llvm::SourceMgr::DiagHandlerTy DiagHandler, 1103*5f757f3fSDimitry Andric void *DiagHandlerCtxt) { 1104*5f757f3fSDimitry Andric Module TheModule; 1105*5f757f3fSDimitry Andric 1106*5f757f3fSDimitry Andric if (!DiagHandler) 1107*5f757f3fSDimitry Andric DiagHandler = &printDiagnostic; 1108*5f757f3fSDimitry Andric 1109*5f757f3fSDimitry Andric if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt)) 1110*5f757f3fSDimitry Andric return true; 1111*5f757f3fSDimitry Andric 1112*5f757f3fSDimitry Andric return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt); 1113*5f757f3fSDimitry Andric } 1114