xref: /freebsd/contrib/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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