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
29using namespace clang;
30using namespace api_notes;
31
32namespace {
33enum class APIAvailability {
34 Available = 0,
35 None,
36 NonSwift,
37};
38} // namespace
39
40namespace llvm {
41namespace yaml {
42template <> 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
52namespace {
53enum class MethodKind {
54 Class,
55 Instance,
56};
57} // namespace
58
59namespace llvm {
60namespace yaml {
61template <> 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
70namespace {
71struct 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
80typedef std::vector<Param> ParamsSeq;
81} // namespace
82
83LLVM_YAML_IS_SEQUENCE_VECTOR(Param)
84LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind)
85
86namespace llvm {
87namespace yaml {
88template <> 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
106template <> 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
120template <> 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
133namespace {
134typedef std::vector<NullabilityKind> NullabilitySeq;
135
136struct AvailabilityItem {
137 APIAvailability Mode = APIAvailability::Available;
138 StringRef Msg;
139};
140
141/// Old attribute deprecated in favor of SwiftName.
142enum 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
151struct 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
168typedef std::vector<Method> MethodsSeq;
169} // namespace
170
171LLVM_YAML_IS_SEQUENCE_VECTOR(Method)
172
173namespace llvm {
174namespace yaml {
175template <> 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
183template <> 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
207namespace {
208struct 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
219typedef std::vector<Property> PropertiesSeq;
220} // namespace
221
222LLVM_YAML_IS_SEQUENCE_VECTOR(Property)
223
224namespace llvm {
225namespace yaml {
226template <> 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
243namespace {
244struct 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
258typedef std::vector<Class> ClassesSeq;
259} // namespace
260
261LLVM_YAML_IS_SEQUENCE_VECTOR(Class)
262
263namespace llvm {
264namespace yaml {
265template <> 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
285namespace {
286struct 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
300typedef std::vector<Function> FunctionsSeq;
301} // namespace
302
303LLVM_YAML_IS_SEQUENCE_VECTOR(Function)
304
305namespace llvm {
306namespace yaml {
307template <> 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
327namespace {
328struct 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
337typedef std::vector<GlobalVariable> GlobalVariablesSeq;
338} // namespace
339
340LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable)
341
342namespace llvm {
343namespace yaml {
344template <> 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
359namespace {
360struct EnumConstant {
361 StringRef Name;
362 AvailabilityItem Availability;
363 std::optional<bool> SwiftPrivate;
364 StringRef SwiftName;
365};
366
367typedef std::vector<EnumConstant> EnumConstantsSeq;
368} // namespace
369
370LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant)
371
372namespace llvm {
373namespace yaml {
374template <> 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
387namespace {
388/// Syntactic sugar for EnumExtensibility and FlagEnum
389enum 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
401namespace llvm {
402namespace yaml {
403template <> 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
417namespace {
418struct 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
427typedef std::vector<Field> FieldsSeq;
428} // namespace
429
430LLVM_YAML_IS_SEQUENCE_VECTOR(Field)
431
432namespace llvm {
433namespace yaml {
434template <> 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
449namespace {
450struct Tag;
451typedef std::vector<Tag> TagsSeq;
452
453struct 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
479LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)
480
481namespace llvm {
482namespace yaml {
483template <> 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
491template <> 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
519namespace {
520struct 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
530typedef std::vector<Typedef> TypedefsSeq;
531} // namespace
532
533LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)
534
535namespace llvm {
536namespace yaml {
537template <> 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
545template <> 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
561namespace {
562struct Namespace;
563typedef std::vector<Namespace> NamespacesSeq;
564
565struct 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
577namespace llvm {
578namespace yaml {
579static 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
592namespace {
593struct Namespace {
594 StringRef Name;
595 AvailabilityItem Availability;
596 StringRef SwiftName;
597 std::optional<bool> SwiftPrivate;
598 TopLevelItems Items;
599};
600} // namespace
601
602LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)
603
604namespace llvm {
605namespace yaml {
606template <> 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
620namespace {
621struct Versioned {
622 VersionTuple Version;
623 TopLevelItems Items;
624};
625
626typedef std::vector<Versioned> VersionedSeq;
627} // namespace
628
629LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)
630
631namespace llvm {
632namespace yaml {
633template <> 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
642namespace {
643struct 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
657namespace llvm {
658namespace yaml {
659template <> 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)
674LLVM_DUMP_METHOD void Module::dump() {
675 llvm::yaml::Output OS(llvm::errs());
676 OS << *this;
677}
678#endif
679
680namespace {
681bool 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
689bool 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
701namespace {
702using namespace api_notes;
703
704class 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
721public:
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
1203static 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.
1212static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) {
1213 Diag.print(ProgName: nullptr, S&: llvm::errs());
1214}
1215
1216bool 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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/APINotes/APINotesYAMLCompiler.cpp