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