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