clang 24.0.0git
APINotesYAMLCompiler.cpp
Go to the documentation of this file.
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
19#include "clang/Basic/LLVM.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallString.h"
23#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringSet.h"
25#include "llvm/Support/SourceMgr.h"
26#include "llvm/Support/VersionTuple.h"
27#include "llvm/Support/YAMLTraits.h"
28#include "llvm/Support/raw_ostream.h"
29#include <optional>
30#include <string>
31#include <type_traits>
32#include <vector>
33
34using namespace clang;
35using namespace api_notes;
36
37namespace llvm {
38namespace yaml {
39template <> struct ScalarEnumerationTraits<SwiftSafetyKind> {
40 static void enumeration(IO &IO, SwiftSafetyKind &SK) {
41 IO.enumCase(SK, "unspecified", SwiftSafetyKind::Unspecified);
42 IO.enumCase(SK, "safe", SwiftSafetyKind::Safe);
43 IO.enumCase(SK, "unsafe", SwiftSafetyKind::Unsafe);
44 }
45};
46} // namespace yaml
47} // namespace llvm
48
49namespace {
50enum class APIAvailability {
51 Available = 0,
52 None,
53 NonSwift,
54};
55} // namespace
56
57namespace {
58struct BoundsSafetyNotes {
60 std::optional<unsigned> Level;
61 StringRef BoundsExpr = "";
62};
63} // namespace
64
65namespace llvm {
66namespace yaml {
67template <> struct ScalarEnumerationTraits<BoundsSafetyInfo::BoundsSafetyKind> {
69 IO.enumCase(AA, "counted_by",
71 IO.enumCase(AA, "counted_by_or_null",
73 IO.enumCase(AA, "sized_by", BoundsSafetyInfo::BoundsSafetyKind::SizedBy);
74 IO.enumCase(AA, "sized_by_or_null",
76 IO.enumCase(AA, "ended_by", BoundsSafetyInfo::BoundsSafetyKind::EndedBy);
77 }
78};
79} // namespace yaml
80} // namespace llvm
81
82namespace llvm {
83namespace yaml {
84template <> struct ScalarEnumerationTraits<APIAvailability> {
85 static void enumeration(IO &IO, APIAvailability &AA) {
86 IO.enumCase(AA, "none", APIAvailability::None);
87 IO.enumCase(AA, "nonswift", APIAvailability::NonSwift);
88 IO.enumCase(AA, "available", APIAvailability::Available);
89 }
90};
91} // namespace yaml
92} // namespace llvm
93
94namespace {
95enum class MethodKind {
96 Class,
97 Instance,
98};
99} // namespace
100
101namespace llvm {
102namespace yaml {
103template <> struct ScalarEnumerationTraits<MethodKind> {
104 static void enumeration(IO &IO, MethodKind &MK) {
105 IO.enumCase(MK, "Class", MethodKind::Class);
106 IO.enumCase(MK, "Instance", MethodKind::Instance);
107 }
108};
109} // namespace yaml
110} // namespace llvm
111
112namespace {
113struct Param {
114 int Position;
115 std::optional<bool> NoEscape = false;
116 std::optional<bool> Lifetimebound = false;
117 std::optional<NullabilityKind> Nullability;
118 std::optional<RetainCountConventionKind> RetainCountConvention;
119 std::optional<BoundsSafetyNotes> BoundsSafety;
120 StringRef Type;
121};
122
123typedef std::vector<Param> ParamsSeq;
124} // namespace
125
126LLVM_YAML_IS_SEQUENCE_VECTOR(Param)
127LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind)
128
129namespace llvm {
130namespace yaml {
131template <> struct ScalarEnumerationTraits<NullabilityKind> {
132 static void enumeration(IO &IO, NullabilityKind &NK) {
133 IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull);
134 IO.enumCase(NK, "Optional", NullabilityKind::Nullable);
135 IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified);
136 IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult);
137 // TODO: Mapping this to its own value would allow for better cross
138 // checking. Also the default should be Unknown.
139 IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified);
140
141 // Aliases for compatibility with existing APINotes.
142 IO.enumCase(NK, "N", NullabilityKind::NonNull);
143 IO.enumCase(NK, "O", NullabilityKind::Nullable);
144 IO.enumCase(NK, "U", NullabilityKind::Unspecified);
145 IO.enumCase(NK, "S", NullabilityKind::Unspecified);
146 }
147};
148
149template <> struct ScalarEnumerationTraits<RetainCountConventionKind> {
150 static void enumeration(IO &IO, RetainCountConventionKind &RCCK) {
151 IO.enumCase(RCCK, "none", RetainCountConventionKind::None);
152 IO.enumCase(RCCK, "CFReturnsRetained",
154 IO.enumCase(RCCK, "CFReturnsNotRetained",
156 IO.enumCase(RCCK, "NSReturnsRetained",
158 IO.enumCase(RCCK, "NSReturnsNotRetained",
160 }
161};
162
163template <> struct MappingTraits<Param> {
164 static void mapping(IO &IO, Param &P) {
165 IO.mapRequired("Position", P.Position);
166 IO.mapOptional("Nullability", P.Nullability, std::nullopt);
167 IO.mapOptional("RetainCountConvention", P.RetainCountConvention);
168 IO.mapOptional("NoEscape", P.NoEscape);
169 IO.mapOptional("Lifetimebound", P.Lifetimebound);
170 IO.mapOptional("Type", P.Type, StringRef(""));
171 IO.mapOptional("BoundsSafety", P.BoundsSafety);
172 }
173};
174
175template <> struct MappingTraits<BoundsSafetyNotes> {
176 static void mapping(IO &IO, BoundsSafetyNotes &BS) {
177 IO.mapRequired("Kind", BS.Kind);
178 IO.mapRequired("BoundedBy", BS.BoundsExpr);
179 IO.mapOptional("Level", BS.Level);
180 }
181};
182} // namespace yaml
183} // namespace llvm
184
185namespace {
186typedef std::vector<NullabilityKind> NullabilitySeq;
187
188struct AvailabilityItem {
189 APIAvailability Mode = APIAvailability::Available;
190 StringRef Msg;
191};
192
193/// Old attribute deprecated in favor of SwiftName.
194enum class FactoryAsInitKind {
195 /// Infer based on name and type (the default).
196 Infer,
197 /// Treat as a class method.
198 AsClassMethod,
199 /// Treat as an initializer.
200 AsInitializer,
201};
202
203struct Method {
204 StringRef Selector;
205 MethodKind Kind;
206 ParamsSeq Params;
207 NullabilitySeq Nullability;
208 std::optional<NullabilityKind> NullabilityOfRet;
209 std::optional<RetainCountConventionKind> RetainCountConvention;
210 AvailabilityItem Availability;
211 std::optional<bool> SwiftPrivate;
212 StringRef SwiftName;
213 FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer;
214 bool DesignatedInit = false;
215 bool Required = false;
216 StringRef ResultType;
217 StringRef SwiftReturnOwnership;
218 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
219};
220
221typedef std::vector<Method> MethodsSeq;
222} // namespace
223
224LLVM_YAML_IS_SEQUENCE_VECTOR(Method)
225
226namespace llvm {
227namespace yaml {
228template <> struct ScalarEnumerationTraits<FactoryAsInitKind> {
229 static void enumeration(IO &IO, FactoryAsInitKind &FIK) {
230 IO.enumCase(FIK, "A", FactoryAsInitKind::Infer);
231 IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod);
232 IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer);
233 }
234};
235
236template <> struct MappingTraits<Method> {
237 static void mapping(IO &IO, Method &M) {
238 IO.mapRequired("Selector", M.Selector);
239 IO.mapRequired("MethodKind", M.Kind);
240 IO.mapOptional("Parameters", M.Params);
241 IO.mapOptional("Nullability", M.Nullability);
242 IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, std::nullopt);
243 IO.mapOptional("RetainCountConvention", M.RetainCountConvention);
244 IO.mapOptional("Availability", M.Availability.Mode,
245 APIAvailability::Available);
246 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
247 IO.mapOptional("SwiftPrivate", M.SwiftPrivate);
248 IO.mapOptional("SwiftName", M.SwiftName, StringRef(""));
249 IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer);
250 IO.mapOptional("DesignatedInit", M.DesignatedInit, false);
251 IO.mapOptional("Required", M.Required, false);
252 IO.mapOptional("ResultType", M.ResultType, StringRef(""));
253 IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership,
254 StringRef(""));
255 IO.mapOptional("SwiftSafety", M.SafetyKind, SwiftSafetyKind::None);
256 }
257};
258} // namespace yaml
259} // namespace llvm
260
261namespace {
262struct Property {
263 StringRef Name;
264 std::optional<MethodKind> Kind;
265 std::optional<NullabilityKind> Nullability;
266 AvailabilityItem Availability;
267 std::optional<bool> SwiftPrivate;
268 StringRef SwiftName;
269 std::optional<bool> SwiftImportAsAccessors;
270 StringRef Type;
271 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
272};
273
274typedef std::vector<Property> PropertiesSeq;
275} // namespace
276
277LLVM_YAML_IS_SEQUENCE_VECTOR(Property)
278
279namespace llvm {
280namespace yaml {
281template <> struct MappingTraits<Property> {
282 static void mapping(IO &IO, Property &P) {
283 IO.mapRequired("Name", P.Name);
284 IO.mapOptional("PropertyKind", P.Kind);
285 IO.mapOptional("Nullability", P.Nullability, std::nullopt);
286 IO.mapOptional("Availability", P.Availability.Mode,
287 APIAvailability::Available);
288 IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef(""));
289 IO.mapOptional("SwiftPrivate", P.SwiftPrivate);
290 IO.mapOptional("SwiftName", P.SwiftName, StringRef(""));
291 IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors);
292 IO.mapOptional("Type", P.Type, StringRef(""));
293 IO.mapOptional("SwiftSafety", P.SafetyKind, SwiftSafetyKind::None);
294 }
295};
296} // namespace yaml
297} // namespace llvm
298
299namespace {
300struct Class {
301 StringRef Name;
302 bool AuditedForNullability = false;
303 AvailabilityItem Availability;
304 std::optional<bool> SwiftPrivate;
305 StringRef SwiftName;
306 std::optional<StringRef> SwiftBridge;
307 std::optional<StringRef> NSErrorDomain;
308 std::optional<bool> SwiftImportAsNonGeneric;
309 std::optional<bool> SwiftObjCMembers;
310 std::optional<std::string> SwiftConformance;
311 MethodsSeq Methods;
312 PropertiesSeq Properties;
313 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
314};
315
316typedef std::vector<Class> ClassesSeq;
317} // namespace
318
319LLVM_YAML_IS_SEQUENCE_VECTOR(Class)
320
321namespace llvm {
322namespace yaml {
323template <> struct MappingTraits<Class> {
324 static void mapping(IO &IO, Class &C) {
325 IO.mapRequired("Name", C.Name);
326 IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false);
327 IO.mapOptional("Availability", C.Availability.Mode,
328 APIAvailability::Available);
329 IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef(""));
330 IO.mapOptional("SwiftPrivate", C.SwiftPrivate);
331 IO.mapOptional("SwiftName", C.SwiftName, StringRef(""));
332 IO.mapOptional("SwiftBridge", C.SwiftBridge);
333 IO.mapOptional("NSErrorDomain", C.NSErrorDomain);
334 IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric);
335 IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers);
336 IO.mapOptional("SwiftConformsTo", C.SwiftConformance);
337 IO.mapOptional("Methods", C.Methods);
338 IO.mapOptional("Properties", C.Properties);
339 IO.mapOptional("SwiftSafety", C.SafetyKind, SwiftSafetyKind::None);
340 }
341};
342} // namespace yaml
343} // namespace llvm
344
345namespace {
346typedef std::vector<StringRef> WhereParamsSeq;
347
348struct FunctionWhere {
349 std::optional<WhereParamsSeq> Parameters;
350};
351
352struct Function {
353 StringRef Name;
354 std::optional<FunctionWhere> Where;
355 ParamsSeq Params;
356 NullabilitySeq Nullability;
357 std::optional<NullabilityKind> NullabilityOfRet;
358 std::optional<api_notes::RetainCountConventionKind> RetainCountConvention;
359 AvailabilityItem Availability;
360 std::optional<bool> SwiftPrivate;
361 StringRef SwiftName;
362 StringRef Type;
363 StringRef ResultType;
364 StringRef SwiftReturnOwnership;
365 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
366 bool UnsafeBufferUsage = false;
367};
368
369typedef std::vector<Function> FunctionsSeq;
370} // namespace
371
372LLVM_YAML_IS_SEQUENCE_VECTOR(Function)
373
374namespace llvm {
375namespace yaml {
376template <> struct MappingTraits<FunctionWhere> {
377 static void mapping(IO &IO, FunctionWhere &W) {
378 IO.mapOptional("Parameters", W.Parameters);
379 }
380};
381
382template <> struct MappingTraits<Function> {
383 static void mapping(IO &IO, Function &F) {
384 IO.mapRequired("Name", F.Name);
385 IO.mapOptional("Where", F.Where);
386 IO.mapOptional("Parameters", F.Params);
387 IO.mapOptional("Nullability", F.Nullability);
388 IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt);
389 IO.mapOptional("RetainCountConvention", F.RetainCountConvention);
390 IO.mapOptional("Availability", F.Availability.Mode,
391 APIAvailability::Available);
392 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));
393 IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
394 IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
395 IO.mapOptional("ResultType", F.ResultType, StringRef(""));
396 IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership,
397 StringRef(""));
398 IO.mapOptional("SwiftSafety", F.SafetyKind, SwiftSafetyKind::None);
399 IO.mapOptional("UnsafeBufferUsage", F.UnsafeBufferUsage, false);
400 }
401};
402} // namespace yaml
403} // namespace llvm
404
405namespace {
406struct GlobalVariable {
407 StringRef Name;
408 std::optional<NullabilityKind> Nullability;
409 AvailabilityItem Availability;
410 std::optional<bool> SwiftPrivate;
411 StringRef SwiftName;
412 StringRef Type;
413 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
414};
415
416typedef std::vector<GlobalVariable> GlobalVariablesSeq;
417} // namespace
418
419LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable)
420
421namespace llvm {
422namespace yaml {
423template <> struct MappingTraits<GlobalVariable> {
424 static void mapping(IO &IO, GlobalVariable &GV) {
425 IO.mapRequired("Name", GV.Name);
426 IO.mapOptional("Nullability", GV.Nullability, std::nullopt);
427 IO.mapOptional("Availability", GV.Availability.Mode,
428 APIAvailability::Available);
429 IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef(""));
430 IO.mapOptional("SwiftPrivate", GV.SwiftPrivate);
431 IO.mapOptional("SwiftName", GV.SwiftName, StringRef(""));
432 IO.mapOptional("Type", GV.Type, StringRef(""));
433 IO.mapOptional("SwiftSafety", GV.SafetyKind, SwiftSafetyKind::None);
434 }
435};
436} // namespace yaml
437} // namespace llvm
438
439namespace {
440struct EnumConstant {
441 StringRef Name;
442 AvailabilityItem Availability;
443 std::optional<bool> SwiftPrivate;
444 StringRef SwiftName;
445 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
446};
447
448typedef std::vector<EnumConstant> EnumConstantsSeq;
449} // namespace
450
451LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant)
452
453namespace llvm {
454namespace yaml {
455template <> struct MappingTraits<EnumConstant> {
456 static void mapping(IO &IO, EnumConstant &EC) {
457 IO.mapRequired("Name", EC.Name);
458 IO.mapOptional("Availability", EC.Availability.Mode,
459 APIAvailability::Available);
460 IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef(""));
461 IO.mapOptional("SwiftPrivate", EC.SwiftPrivate);
462 IO.mapOptional("SwiftName", EC.SwiftName, StringRef(""));
463 IO.mapOptional("SwiftSafety", EC.SafetyKind, SwiftSafetyKind::None);
464 }
465};
466} // namespace yaml
467} // namespace llvm
468
469namespace {
470/// Syntactic sugar for EnumExtensibility and FlagEnum
471enum class EnumConvenienceAliasKind {
472 /// EnumExtensibility: none, FlagEnum: false
473 None,
474 /// EnumExtensibility: open, FlagEnum: false
475 CFEnum,
476 /// EnumExtensibility: open, FlagEnum: true
477 CFOptions,
478 /// EnumExtensibility: closed, FlagEnum: false
479 CFClosedEnum
480};
481} // namespace
482
483namespace llvm {
484namespace yaml {
485template <> struct ScalarEnumerationTraits<EnumConvenienceAliasKind> {
486 static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) {
487 IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None);
488 IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum);
489 IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum);
490 IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions);
491 IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions);
492 IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
493 IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
494 }
495};
496} // namespace yaml
497} // namespace llvm
498
499namespace {
500struct Field {
501 StringRef Name;
502 std::optional<NullabilityKind> Nullability;
503 AvailabilityItem Availability;
504 std::optional<bool> SwiftPrivate;
505 StringRef SwiftName;
506 StringRef Type;
507 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
508};
509
510typedef std::vector<Field> FieldsSeq;
511} // namespace
512
513LLVM_YAML_IS_SEQUENCE_VECTOR(Field)
514
515namespace llvm {
516namespace yaml {
517template <> struct MappingTraits<Field> {
518 static void mapping(IO &IO, Field &F) {
519 IO.mapRequired("Name", F.Name);
520 IO.mapOptional("Nullability", F.Nullability, std::nullopt);
521 IO.mapOptional("Availability", F.Availability.Mode,
522 APIAvailability::Available);
523 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));
524 IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
525 IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
526 IO.mapOptional("Type", F.Type, StringRef(""));
527 IO.mapOptional("SwiftSafety", F.SafetyKind, SwiftSafetyKind::None);
528 }
529};
530} // namespace yaml
531} // namespace llvm
532
533namespace {
534struct Tag;
535typedef std::vector<Tag> TagsSeq;
536
537struct Tag {
538 StringRef Name;
539 AvailabilityItem Availability;
540 StringRef SwiftName;
541 std::optional<bool> SwiftPrivate;
542 std::optional<StringRef> SwiftBridge;
543 std::optional<StringRef> NSErrorDomain;
544 std::optional<std::string> SwiftImportAs;
545 std::optional<std::string> SwiftRetainOp;
546 std::optional<std::string> SwiftReleaseOp;
547 std::optional<std::string> SwiftDestroyOp;
548 std::optional<std::string> SwiftDefaultOwnership;
549 std::optional<std::string> SwiftConformance;
550 std::optional<EnumExtensibilityKind> EnumExtensibility;
551 std::optional<bool> FlagEnum;
552 std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
553 std::optional<bool> SwiftCopyable;
554 std::optional<bool> SwiftEscapable;
555 SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
556 FunctionsSeq Methods;
557 FieldsSeq Fields;
558
559 /// Tags that are declared within the current tag. Only the tags that have
560 /// corresponding API Notes will be listed.
561 TagsSeq Tags;
562};
563} // namespace
564
565LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)
566
567namespace llvm {
568namespace yaml {
569template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> {
570 static void enumeration(IO &IO, EnumExtensibilityKind &EEK) {
571 IO.enumCase(EEK, "none", EnumExtensibilityKind::None);
572 IO.enumCase(EEK, "open", EnumExtensibilityKind::Open);
573 IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed);
574 }
575};
576
577template <> struct MappingTraits<Tag> {
578 static void mapping(IO &IO, Tag &T) {
579 IO.mapRequired("Name", T.Name);
580 IO.mapOptional("Availability", T.Availability.Mode,
581 APIAvailability::Available);
582 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
583 IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
584 IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
585 IO.mapOptional("SwiftBridge", T.SwiftBridge);
586 IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
587 IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
588 IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
589 IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
590 IO.mapOptional("SwiftDestroyOp", T.SwiftDestroyOp);
591 IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership);
592 IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
593 IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
594 IO.mapOptional("FlagEnum", T.FlagEnum);
595 IO.mapOptional("EnumKind", T.EnumConvenienceKind);
596 IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
597 IO.mapOptional("SwiftEscapable", T.SwiftEscapable);
598 IO.mapOptional("Methods", T.Methods);
599 IO.mapOptional("Fields", T.Fields);
600 IO.mapOptional("Tags", T.Tags);
601 IO.mapOptional("SwiftSafety", T.SafetyKind, SwiftSafetyKind::None);
602 }
603};
604} // namespace yaml
605} // namespace llvm
606
607namespace {
608struct Typedef {
609 StringRef Name;
610 AvailabilityItem Availability;
611 StringRef SwiftName;
612 std::optional<bool> SwiftPrivate;
613 std::optional<StringRef> SwiftBridge;
614 std::optional<StringRef> NSErrorDomain;
615 std::optional<SwiftNewTypeKind> SwiftType;
616 std::optional<std::string> SwiftConformance;
617 const SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
618};
619
620typedef std::vector<Typedef> TypedefsSeq;
621} // namespace
622
623LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)
624
625namespace llvm {
626namespace yaml {
627template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> {
628 static void enumeration(IO &IO, SwiftNewTypeKind &SWK) {
629 IO.enumCase(SWK, "none", SwiftNewTypeKind::None);
630 IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct);
631 IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum);
632 }
633};
634
635template <> struct MappingTraits<Typedef> {
636 static void mapping(IO &IO, Typedef &T) {
637 IO.mapRequired("Name", T.Name);
638 IO.mapOptional("Availability", T.Availability.Mode,
639 APIAvailability::Available);
640 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
641 IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
642 IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
643 IO.mapOptional("SwiftBridge", T.SwiftBridge);
644 IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
645 IO.mapOptional("SwiftWrapper", T.SwiftType);
646 IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
647 }
648};
649} // namespace yaml
650} // namespace llvm
651
652namespace {
653struct Namespace;
654typedef std::vector<Namespace> NamespacesSeq;
655
656struct TopLevelItems {
657 ClassesSeq Classes;
658 ClassesSeq Protocols;
659 FunctionsSeq Functions;
660 GlobalVariablesSeq Globals;
661 EnumConstantsSeq EnumConstants;
662 TagsSeq Tags;
663 TypedefsSeq Typedefs;
664 NamespacesSeq Namespaces;
665};
666} // namespace
667
668namespace llvm {
669namespace yaml {
670static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) {
671 IO.mapOptional("Classes", TLI.Classes);
672 IO.mapOptional("Protocols", TLI.Protocols);
673 IO.mapOptional("Functions", TLI.Functions);
674 IO.mapOptional("Globals", TLI.Globals);
675 IO.mapOptional("Enumerators", TLI.EnumConstants);
676 IO.mapOptional("Tags", TLI.Tags);
677 IO.mapOptional("Typedefs", TLI.Typedefs);
678 IO.mapOptional("Namespaces", TLI.Namespaces);
679}
680} // namespace yaml
681} // namespace llvm
682
683namespace {
684struct Namespace {
685 StringRef Name;
686 AvailabilityItem Availability;
687 StringRef SwiftName;
688 std::optional<bool> SwiftPrivate;
689 TopLevelItems Items;
690 const SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
691};
692} // namespace
693
694LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)
695
696namespace llvm {
697namespace yaml {
698template <> struct MappingTraits<Namespace> {
699 static void mapping(IO &IO, Namespace &T) {
700 IO.mapRequired("Name", T.Name);
701 IO.mapOptional("Availability", T.Availability.Mode,
702 APIAvailability::Available);
703 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
704 IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
705 IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
706 mapTopLevelItems(IO, T.Items);
707 }
708};
709} // namespace yaml
710} // namespace llvm
711
712namespace {
713struct Versioned {
714 VersionTuple Version;
715 TopLevelItems Items;
716};
717
718typedef std::vector<Versioned> VersionedSeq;
719} // namespace
720
721LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)
722
723namespace llvm {
724namespace yaml {
725template <> struct MappingTraits<Versioned> {
726 static void mapping(IO &IO, Versioned &V) {
727 IO.mapRequired("Version", V.Version);
728 mapTopLevelItems(IO, V.Items);
729 }
730};
731} // namespace yaml
732} // namespace llvm
733
734namespace {
735struct Module {
736 StringRef Name;
737 AvailabilityItem Availability;
738 TopLevelItems TopLevel;
739 VersionedSeq SwiftVersions;
740
741 std::optional<bool> SwiftInferImportAsMember;
742
743#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
744 LLVM_DUMP_METHOD void dump() /*const*/;
745#endif
746};
747} // namespace
748
749namespace llvm {
750namespace yaml {
751template <> struct MappingTraits<Module> {
752 static void mapping(IO &IO, Module &M) {
753 IO.mapRequired("Name", M.Name);
754 IO.mapOptional("Availability", M.Availability.Mode,
755 APIAvailability::Available);
756 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
757 IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember);
758 mapTopLevelItems(IO, M.TopLevel);
759 IO.mapOptional("SwiftVersions", M.SwiftVersions);
760 }
761};
762} // namespace yaml
763} // namespace llvm
764
765#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
766LLVM_DUMP_METHOD void Module::dump() {
767 llvm::yaml::Output OS(llvm::errs());
768 OS << *this;
769}
770#endif
771
772namespace {
773bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag,
774 void *DiagContext) {
775 llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext);
776 IS >> M;
777 return static_cast<bool>(IS.error());
778}
779} // namespace
780
782 llvm::raw_ostream &OS) {
783 Module M;
784 if (parseAPINotes(YI, M, nullptr, nullptr))
785 return true;
786
787 llvm::yaml::Output YOS(OS);
788 YOS << M;
789
790 return false;
791}
792
793namespace {
794using namespace api_notes;
795
796static std::string
797getFunctionSelectorKey(llvm::StringRef Name,
800 llvm::raw_svector_ostream OS(Key);
801 auto AppendKeyPart = [&OS](llvm::StringRef Part) {
802 OS << Part.size() << ':' << Part;
803 };
804
805 AppendKeyPart(Name);
806 OS << ';';
807 for (llvm::StringRef Parameter : Parameters)
808 AppendKeyPart(Parameter);
809 return Key.str().str();
810}
811
812class YAMLConverter {
813 const Module &M;
814 APINotesWriter Writer;
815 llvm::raw_ostream &OS;
816 llvm::SourceMgr::DiagHandlerTy DiagHandler;
817 void *DiagHandlerCtxt;
818 bool ErrorOccurred;
819
820 /// Emit a diagnostic
821 bool emitError(llvm::Twine Message) {
822 DiagHandler(
823 llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
824 DiagHandlerCtxt);
825 ErrorOccurred = true;
826 return true;
827 }
828
829public:
830 YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
831 llvm::raw_ostream &OS,
832 llvm::SourceMgr::DiagHandlerTy DiagHandler,
833 void *DiagHandlerCtxt)
834 : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
835 DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
836 ErrorOccurred(false) {}
837
838 void convertAvailability(const AvailabilityItem &Availability,
839 CommonEntityInfo &CEI, llvm::StringRef APIName) {
840 // Populate the unavailability information.
841 CEI.Unavailable = (Availability.Mode == APIAvailability::None);
842 CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
843 if (CEI.Unavailable || CEI.UnavailableInSwift) {
844 CEI.UnavailableMsg = std::string(Availability.Msg);
845 } else {
846 if (!Availability.Msg.empty())
847 emitError(llvm::Twine("availability message for available API '") +
848 APIName + "' will not be used");
849 }
850 }
851
852 void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo,
853 std::optional<ParamInfo> &thisOrSelf) {
854 for (const auto &P : Params) {
855 ParamInfo PI;
856 if (P.Nullability)
857 PI.setNullabilityAudited(*P.Nullability);
858 PI.setNoEscape(P.NoEscape);
859 PI.setLifetimebound(P.Lifetimebound);
860 PI.setType(std::string(P.Type));
861 PI.setRetainCountConvention(P.RetainCountConvention);
862 if (P.BoundsSafety) {
863 BoundsSafetyInfo BSI;
864 BSI.setKindAudited(P.BoundsSafety->Kind);
865 if (P.BoundsSafety->Level)
866 BSI.setLevelAudited(*P.BoundsSafety->Level);
867 BSI.ExternalBounds = P.BoundsSafety->BoundsExpr.str();
868 PI.BoundsSafety = BSI;
869 }
870 if (static_cast<int>(OutInfo.Params.size()) <= P.Position)
871 OutInfo.Params.resize(P.Position + 1);
872 if (P.Position == -1)
873 thisOrSelf = PI;
874 else if (P.Position >= 0)
875 OutInfo.Params[P.Position] |= PI;
876 else
877 emitError("invalid parameter position " + llvm::itostr(P.Position));
878 }
879 }
880
881 void convertNullability(const NullabilitySeq &Nullability,
882 std::optional<NullabilityKind> ReturnNullability,
883 FunctionInfo &OutInfo, llvm::StringRef APIName) {
885 emitError(llvm::Twine("nullability info for '") + APIName +
886 "' does not fit");
887 return;
888 }
889
890 bool audited = false;
891 unsigned int idx = 1;
892 for (const auto &N : Nullability)
893 OutInfo.addTypeInfo(idx++, N);
894 audited = Nullability.size() > 0 || ReturnNullability;
895 if (audited)
896 OutInfo.addTypeInfo(0,
897 ReturnNullability.value_or(NullabilityKind::NonNull));
898 if (!audited)
899 return;
900 OutInfo.NullabilityAudited = audited;
901 OutInfo.NumAdjustedNullable = idx;
902 }
903
904 /// Convert the common parts of an entity from YAML.
905 template <typename T>
906 void convertCommonEntity(const T &Common, CommonEntityInfo &Info,
907 StringRef APIName) {
908 convertAvailability(Common.Availability, Info, APIName);
909 Info.setSwiftPrivate(Common.SwiftPrivate);
910 if (Common.SafetyKind != SwiftSafetyKind::None)
911 Info.setSwiftSafety(Common.SafetyKind);
912 Info.SwiftName = std::string(Common.SwiftName);
913 }
914
915 /// Convert the common parts of a type entity from YAML.
916 template <typename T>
917 void convertCommonType(const T &Common, CommonTypeInfo &Info,
918 StringRef APIName) {
919 convertCommonEntity(Common, Info, APIName);
920 if (Common.SwiftBridge)
921 Info.setSwiftBridge(std::string(*Common.SwiftBridge));
922 Info.setNSErrorDomain(Common.NSErrorDomain);
923 if (auto conformance = Common.SwiftConformance)
924 Info.setSwiftConformance(conformance);
925 }
926
927 // Translate from Method into ObjCMethodInfo and write it out.
928 void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName,
929 VersionTuple SwiftVersion) {
930 ObjCMethodInfo MI;
931 convertCommonEntity(M, MI, M.Selector);
932
933 // Check if the selector ends with ':' to determine if it takes arguments.
934 bool takesArguments = M.Selector.ends_with(":");
935
936 // Split the selector into pieces.
937 llvm::SmallVector<StringRef, 4> Args;
938 M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
939 if (!takesArguments && Args.size() > 1) {
940 emitError("selector '" + M.Selector + "' is missing a ':' at the end");
941 return;
942 }
943
944 // Construct ObjCSelectorRef.
945 api_notes::ObjCSelectorRef Selector;
946 Selector.NumArgs = !takesArguments ? 0 : Args.size();
947 Selector.Identifiers = Args;
948
949 // Translate the initializer info.
950 MI.DesignatedInit = M.DesignatedInit;
951 MI.RequiredInit = M.Required;
952 if (M.FactoryAsInit != FactoryAsInitKind::Infer)
953 emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
954
955 MI.ResultType = std::string(M.ResultType);
956 MI.SwiftReturnOwnership = std::string(M.SwiftReturnOwnership);
957
958 // Translate parameter information.
959 convertParams(M.Params, MI, MI.Self);
960
961 // Translate nullability info.
962 convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector);
963
964 MI.setRetainCountConvention(M.RetainCountConvention);
965
966 // Write it.
967 Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI,
968 SwiftVersion);
969 }
970
971 template <typename T>
972 void convertVariable(const T &Entity, VariableInfo &VI) {
973 convertAvailability(Entity.Availability, VI, Entity.Name);
974 VI.setSwiftPrivate(Entity.SwiftPrivate);
975 VI.SwiftName = std::string(Entity.SwiftName);
976 if (Entity.Nullability)
977 VI.setNullabilityAudited(*Entity.Nullability);
978 VI.setType(std::string(Entity.Type));
979 }
980
981 void convertContext(std::optional<ContextID> ParentContextID, const Class &C,
982 ContextKind Kind, VersionTuple SwiftVersion) {
983 // Write the class.
984 ContextInfo CI;
985 convertCommonType(C, CI, C.Name);
986
987 if (C.AuditedForNullability)
988 CI.setDefaultNullability(NullabilityKind::NonNull);
989 if (C.SwiftImportAsNonGeneric)
990 CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric);
991 if (C.SwiftObjCMembers)
992 CI.setSwiftObjCMembers(*C.SwiftObjCMembers);
993
994 ContextID CtxID =
995 Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
996
997 // Write all methods.
998 llvm::StringMap<std::pair<bool, bool>> KnownMethods;
999 for (const auto &method : C.Methods) {
1000 // Check for duplicate method definitions.
1001 bool IsInstanceMethod = method.Kind == MethodKind::Instance;
1002 bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first
1003 : KnownMethods[method.Selector].second;
1004 if (Known) {
1005 emitError(llvm::Twine("duplicate definition of method '") +
1006 (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " +
1007 method.Selector + "]'");
1008 continue;
1009 }
1010 Known = true;
1011
1012 convertMethod(method, CtxID, C.Name, SwiftVersion);
1013 }
1014
1015 // Write all properties.
1016 llvm::StringSet<> KnownInstanceProperties;
1017 llvm::StringSet<> KnownClassProperties;
1018 for (const auto &Property : C.Properties) {
1019 // Check for duplicate property definitions.
1020 if ((!Property.Kind || *Property.Kind == MethodKind::Instance) &&
1021 !KnownInstanceProperties.insert(Property.Name).second) {
1022 emitError(llvm::Twine("duplicate definition of instance property '") +
1023 C.Name + "." + Property.Name + "'");
1024 continue;
1025 }
1026
1027 if ((!Property.Kind || *Property.Kind == MethodKind::Class) &&
1028 !KnownClassProperties.insert(Property.Name).second) {
1029 emitError(llvm::Twine("duplicate definition of class property '") +
1030 C.Name + "." + Property.Name + "'");
1031 continue;
1032 }
1033
1034 // Translate from Property into ObjCPropertyInfo.
1035 ObjCPropertyInfo PI;
1036 convertVariable(Property, PI);
1037 if (Property.SwiftImportAsAccessors)
1038 PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors);
1039
1040 // Add both instance and class properties with this name.
1041 if (Property.Kind) {
1042 Writer.addObjCProperty(CtxID, Property.Name,
1043 *Property.Kind == MethodKind::Instance, PI,
1044 SwiftVersion);
1045 } else {
1046 Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion);
1047 Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion);
1048 }
1049 }
1050 }
1051
1052 void convertNamespaceContext(std::optional<ContextID> ParentContextID,
1053 const Namespace &TheNamespace,
1054 VersionTuple SwiftVersion) {
1055 // Write the namespace.
1056 ContextInfo CI;
1057 convertCommonEntity(TheNamespace, CI, TheNamespace.Name);
1058
1059 ContextID CtxID =
1060 Writer.addContext(ParentContextID, TheNamespace.Name,
1061 ContextKind::Namespace, CI, SwiftVersion);
1062
1063 convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
1064 TheNamespace.Items, SwiftVersion);
1065 }
1066
1067 std::pair<bool, std::optional<llvm::ArrayRef<llvm::StringRef>>>
1068 getWhereParameters(const Function &Function) {
1069 if (!Function.Where)
1070 return {true, std::nullopt};
1071
1072 if (!Function.Where->Parameters) {
1073 emitError("'Where' requires 'Parameters'");
1074 return {false, std::nullopt};
1075 }
1076 return {true, llvm::ArrayRef<llvm::StringRef>(*Function.Where->Parameters)};
1077 }
1078
1079 template <typename FuncOrMethodInfo>
1080 void convertFunction(const Function &Function, FuncOrMethodInfo &FI) {
1081 convertAvailability(Function.Availability, FI, Function.Name);
1082 FI.setSwiftPrivate(Function.SwiftPrivate);
1083 if (Function.SafetyKind != SwiftSafetyKind::None)
1084 FI.setSwiftSafety(Function.SafetyKind);
1085 FI.SwiftName = std::string(Function.SwiftName);
1086 std::optional<ParamInfo> This;
1087 convertParams(Function.Params, FI, This);
1088 if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>)
1089 FI.This = This;
1090 else if (This)
1091 emitError("implicit instance parameter is only permitted on C++ and "
1092 "Objective-C methods");
1093 convertNullability(Function.Nullability, Function.NullabilityOfRet, FI,
1094 Function.Name);
1095 FI.ResultType = std::string(Function.ResultType);
1096 FI.SwiftReturnOwnership = std::string(Function.SwiftReturnOwnership);
1097 FI.setRetainCountConvention(Function.RetainCountConvention);
1098 FI.UnsafeBufferUsage = Function.UnsafeBufferUsage;
1099 }
1100
1101 void convertTagContext(std::optional<Context> ParentContext, const Tag &T,
1102 VersionTuple SwiftVersion) {
1103 TagInfo TI;
1104 std::optional<ContextID> ParentContextID =
1105 ParentContext ? std::optional<ContextID>(ParentContext->id)
1106 : std::nullopt;
1107 convertCommonType(T, TI, T.Name);
1108
1109 if ((T.SwiftRetainOp || T.SwiftReleaseOp) && !T.SwiftImportAs) {
1110 emitError(llvm::Twine("should declare SwiftImportAs to use "
1111 "SwiftRetainOp and SwiftReleaseOp (for ") +
1112 T.Name + ")");
1113 return;
1114 }
1115 if (T.SwiftReleaseOp.has_value() != T.SwiftRetainOp.has_value()) {
1116 emitError(llvm::Twine("should declare both SwiftReleaseOp and "
1117 "SwiftRetainOp (for ") +
1118 T.Name + ")");
1119 return;
1120 }
1121
1122 if (T.SwiftImportAs)
1123 TI.SwiftImportAs = T.SwiftImportAs;
1124 if (T.SwiftRetainOp)
1125 TI.SwiftRetainOp = T.SwiftRetainOp;
1126 if (T.SwiftReleaseOp)
1127 TI.SwiftReleaseOp = T.SwiftReleaseOp;
1128 if (T.SwiftDestroyOp)
1129 TI.SwiftDestroyOp = T.SwiftDestroyOp;
1130 if (T.SwiftDefaultOwnership)
1131 TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
1132
1133 if (T.SwiftCopyable)
1134 TI.setSwiftCopyable(T.SwiftCopyable);
1135 if (T.SwiftEscapable)
1136 TI.setSwiftEscapable(T.SwiftEscapable);
1137
1138 if (T.EnumConvenienceKind) {
1139 if (T.EnumExtensibility) {
1140 emitError(
1141 llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") +
1142 T.Name + ")");
1143 return;
1144 }
1145 if (T.FlagEnum) {
1146 emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") +
1147 T.Name + ")");
1148 return;
1149 }
1150 switch (*T.EnumConvenienceKind) {
1151 case EnumConvenienceAliasKind::None:
1152 TI.EnumExtensibility = EnumExtensibilityKind::None;
1153 TI.setFlagEnum(false);
1154 break;
1155 case EnumConvenienceAliasKind::CFEnum:
1156 TI.EnumExtensibility = EnumExtensibilityKind::Open;
1157 TI.setFlagEnum(false);
1158 break;
1159 case EnumConvenienceAliasKind::CFOptions:
1160 TI.EnumExtensibility = EnumExtensibilityKind::Open;
1161 TI.setFlagEnum(true);
1162 break;
1163 case EnumConvenienceAliasKind::CFClosedEnum:
1164 TI.EnumExtensibility = EnumExtensibilityKind::Closed;
1165 TI.setFlagEnum(false);
1166 break;
1167 }
1168 } else {
1169 TI.EnumExtensibility = T.EnumExtensibility;
1170 TI.setFlagEnum(T.FlagEnum);
1171 }
1172
1173 Writer.addTag(ParentContext, T.Name, TI, SwiftVersion);
1174
1175 ContextInfo CI;
1176 auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag,
1177 CI, SwiftVersion);
1178 Context TagCtx(TagCtxID, ContextKind::Tag);
1179
1180 for (const auto &Field : T.Fields) {
1181 FieldInfo FI;
1182 convertVariable(Field, FI);
1183 Writer.addField(TagCtxID, Field.Name, FI, SwiftVersion);
1184 }
1185
1186 llvm::StringSet<> KnownMethodSelectors;
1187 for (const auto &CXXMethod : T.Methods) {
1188 auto WhereParameters = getWhereParameters(CXXMethod);
1189 if (!WhereParameters.first)
1190 continue;
1191
1192 if (WhereParameters.second) {
1193 if (!KnownMethodSelectors
1194 .insert(getFunctionSelectorKey(CXXMethod.Name,
1195 *WhereParameters.second))
1196 .second) {
1197 emitError(llvm::Twine("multiple API notes entries for C++ method '") +
1198 CXXMethod.Name + "' with Where.Parameters " +
1199 formatAPINotesParameterSelector(*WhereParameters.second));
1200 continue;
1201 }
1202 }
1203
1204 CXXMethodInfo MI;
1205 convertFunction(CXXMethod, MI);
1206 if (WhereParameters.second)
1207 Writer.addCXXMethod(TagCtxID, CXXMethod.Name, *WhereParameters.second,
1208 MI, SwiftVersion);
1209 else
1210 Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
1211 }
1212
1213 // Convert nested tags.
1214 for (const auto &Tag : T.Tags)
1215 convertTagContext(TagCtx, Tag, SwiftVersion);
1216 }
1217
1218 void convertTopLevelItems(std::optional<Context> Ctx,
1219 const TopLevelItems &TLItems,
1220 VersionTuple SwiftVersion) {
1221 std::optional<ContextID> CtxID =
1222 Ctx ? std::optional(Ctx->id) : std::nullopt;
1223
1224 // Write all classes.
1225 llvm::StringSet<> KnownClasses;
1226 for (const auto &Class : TLItems.Classes) {
1227 // Check for duplicate class definitions.
1228 if (!KnownClasses.insert(Class.Name).second) {
1229 emitError(llvm::Twine("multiple definitions of class '") + Class.Name +
1230 "'");
1231 continue;
1232 }
1233
1234 convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion);
1235 }
1236
1237 // Write all protocols.
1238 llvm::StringSet<> KnownProtocols;
1239 for (const auto &Protocol : TLItems.Protocols) {
1240 // Check for duplicate protocol definitions.
1241 if (!KnownProtocols.insert(Protocol.Name).second) {
1242 emitError(llvm::Twine("multiple definitions of protocol '") +
1243 Protocol.Name + "'");
1244 continue;
1245 }
1246
1247 convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion);
1248 }
1249
1250 // Write all namespaces.
1251 llvm::StringSet<> KnownNamespaces;
1252 for (const auto &Namespace : TLItems.Namespaces) {
1253 // Check for duplicate namespace definitions.
1254 if (!KnownNamespaces.insert(Namespace.Name).second) {
1255 emitError(llvm::Twine("multiple definitions of namespace '") +
1256 Namespace.Name + "'");
1257 continue;
1258 }
1259
1260 convertNamespaceContext(CtxID, Namespace, SwiftVersion);
1261 }
1262
1263 // Write all global variables.
1264 llvm::StringSet<> KnownGlobals;
1265 for (const auto &Global : TLItems.Globals) {
1266 // Check for duplicate global variables.
1267 if (!KnownGlobals.insert(Global.Name).second) {
1268 emitError(llvm::Twine("multiple definitions of global variable '") +
1269 Global.Name + "'");
1270 continue;
1271 }
1272
1273 GlobalVariableInfo GVI;
1274 convertVariable(Global, GVI);
1275 Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion);
1276 }
1277
1278 // Write all global functions.
1279 llvm::StringSet<> KnownNameOnlyFunctions;
1280 llvm::StringSet<> KnownFunctionSelectors;
1281 for (const auto &Function : TLItems.Functions) {
1282 auto WhereParameters = getWhereParameters(Function);
1283 if (!WhereParameters.first)
1284 continue;
1285
1286 if (WhereParameters.second) {
1287 if (!KnownFunctionSelectors
1288 .insert(getFunctionSelectorKey(Function.Name,
1289 *WhereParameters.second))
1290 .second) {
1291 emitError(
1292 llvm::Twine("multiple API notes entries for global function '") +
1293 Function.Name + "' with Where.Parameters " +
1294 formatAPINotesParameterSelector(*WhereParameters.second));
1295 continue;
1296 }
1297 }
1298
1299 // Check for duplicate name-only global functions.
1300 if (!WhereParameters.second &&
1301 !KnownNameOnlyFunctions.insert(Function.Name).second) {
1302 emitError(llvm::Twine("multiple definitions of global function '") +
1303 Function.Name + "'");
1304 continue;
1305 }
1306
1307 GlobalFunctionInfo GFI;
1308 convertFunction(Function, GFI);
1309 if (WhereParameters.second)
1310 Writer.addGlobalFunction(Ctx, Function.Name, *WhereParameters.second,
1311 GFI, SwiftVersion);
1312 else
1313 Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion);
1314 }
1315
1316 // Write all enumerators.
1317 llvm::StringSet<> KnownEnumConstants;
1318 for (const auto &EnumConstant : TLItems.EnumConstants) {
1319 // Check for duplicate enumerators
1320 if (!KnownEnumConstants.insert(EnumConstant.Name).second) {
1321 emitError(llvm::Twine("multiple definitions of enumerator '") +
1322 EnumConstant.Name + "'");
1323 continue;
1324 }
1325
1326 EnumConstantInfo ECI;
1327 convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name);
1328 ECI.setSwiftPrivate(EnumConstant.SwiftPrivate);
1329 ECI.SwiftName = std::string(EnumConstant.SwiftName);
1330 Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion);
1331 }
1332
1333 // Write all tags.
1334 llvm::StringSet<> KnownTags;
1335 for (const auto &Tag : TLItems.Tags) {
1336 // Check for duplicate tag definitions.
1337 if (!KnownTags.insert(Tag.Name).second) {
1338 emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name +
1339 "'");
1340 continue;
1341 }
1342
1343 convertTagContext(Ctx, Tag, SwiftVersion);
1344 }
1345
1346 // Write all typedefs.
1347 llvm::StringSet<> KnownTypedefs;
1348 for (const auto &Typedef : TLItems.Typedefs) {
1349 // Check for duplicate typedef definitions.
1350 if (!KnownTypedefs.insert(Typedef.Name).second) {
1351 emitError(llvm::Twine("multiple definitions of typedef '") +
1352 Typedef.Name + "'");
1353 continue;
1354 }
1355
1356 TypedefInfo TInfo;
1357 convertCommonType(Typedef, TInfo, Typedef.Name);
1358 TInfo.SwiftWrapper = Typedef.SwiftType;
1359
1360 Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion);
1361 }
1362 }
1363
1364 bool convertModule() {
1365 // Write the top-level items.
1366 convertTopLevelItems(/* context */ std::nullopt, M.TopLevel,
1367 VersionTuple());
1368
1369 // Convert the versioned information.
1370 for (const auto &Versioned : M.SwiftVersions)
1371 convertTopLevelItems(/* context */ std::nullopt, Versioned.Items,
1372 Versioned.Version);
1373
1374 if (!ErrorOccurred)
1375 Writer.writeToStream(OS);
1376
1377 return ErrorOccurred;
1378 }
1379};
1380} // namespace
1381
1382static bool compile(const Module &M, const FileEntry *SourceFile,
1383 llvm::raw_ostream &OS,
1384 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1385 void *DiagHandlerCtxt) {
1386 YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1387 return C.convertModule();
1388}
1389
1390/// Simple diagnostic handler that prints diagnostics to standard error.
1391static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) {
1392 Diag.print(nullptr, llvm::errs());
1393}
1394
1395bool api_notes::compileAPINotes(StringRef YAMLInput,
1396 const FileEntry *SourceFile,
1397 llvm::raw_ostream &OS,
1398 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1399 void *DiagHandlerCtxt) {
1400 Module TheModule;
1401
1402 if (!DiagHandler)
1403 DiagHandler = &printDiagnostic;
1404
1405 if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt))
1406 return true;
1407
1408 return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1409}
static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context)
Simple diagnostic handler that prints diagnostics to standard error.
static bool compile(const Module &M, const FileEntry *SourceFile, llvm::raw_ostream &OS, llvm::SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
#define V(N, I)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines various enumerations that describe declaration and type specifiers.
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:273
Describes a module or submodule.
Definition Module.h:340
std::string Name
The name of this module.
Definition Module.h:343
void dump() const
Dump the contents of this module to the given output stream.
void addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, bool IsInstanceMethod, const ObjCMethodInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C method.
void addEnumConstant(llvm::StringRef Name, const EnumConstantInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about an enumerator.
ContextID addContext(std::optional< ContextID > ParentCtxID, llvm::StringRef Name, ContextKind Kind, const ContextInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C class or protocol or a C++ namespace.
void addGlobalFunction(std::optional< Context > Ctx, llvm::StringRef Name, const GlobalFunctionInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a global function.
void addObjCProperty(ContextID CtxID, llvm::StringRef Name, bool IsInstanceProperty, const ObjCPropertyInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C property.
void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific C record field.
void addGlobalVariable(std::optional< Context > Ctx, llvm::StringRef Name, const GlobalVariableInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a global variable.
void addTypedef(std::optional< Context > Ctx, llvm::StringRef Name, const TypedefInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a typedef.
void writeToStream(llvm::raw_ostream &OS)
void addCXXMethod(ContextID CtxID, llvm::StringRef Name, const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific C++ method.
void addTag(std::optional< Context > Ctx, llvm::StringRef Name, const TagInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a tag (struct/union/enum/C++ class).
void setKindAudited(BoundsSafetyKind kind)
Definition Types.h:394
void setLevelAudited(unsigned level)
Definition Types.h:403
unsigned UnavailableInSwift
Whether this entity is marked unavailable in Swift.
Definition Types.h:83
unsigned Unavailable
Whether this entity is marked unavailable.
Definition Types.h:79
std::string SwiftName
Swift name of this entity.
Definition Types.h:102
void setSwiftSafety(SwiftSafetyKind Safety)
Definition Types.h:124
void setSwiftPrivate(std::optional< bool > Private)
Definition Types.h:113
std::string UnavailableMsg
Message to use when this entity is unavailable.
Definition Types.h:75
void setSwiftConformance(std::optional< std::string > conformance)
Definition Types.h:217
void setNSErrorDomain(const std::optional< std::string > &Domain)
Definition Types.h:204
void setSwiftBridge(std::optional< std::string > SwiftType)
Definition Types.h:196
void setDefaultNullability(NullabilityKind Kind)
Set the default nullability for properties and methods of this class.
Definition Types.h:289
void setSwiftObjCMembers(std::optional< bool > Value)
Definition Types.h:311
void setSwiftImportAsNonGeneric(std::optional< bool > Value)
Definition Types.h:302
std::string SwiftReturnOwnership
Ownership convention for return value.
Definition Types.h:670
void addTypeInfo(unsigned index, NullabilityKind kind)
Definition Types.h:683
void setRetainCountConvention(std::optional< RetainCountConventionKind > Value)
Definition Types.h:723
std::vector< ParamInfo > Params
The function parameters.
Definition Types.h:673
unsigned NumAdjustedNullable
Number of types whose nullability is encoded with the NullabilityPayload.
Definition Types.h:650
std::string ResultType
The result type of this function, as a C type.
Definition Types.h:667
static unsigned getMaxNullabilityIndex()
Definition Types.h:679
unsigned NullabilityAudited
Whether the signature has been audited with respect to nullability.
Definition Types.h:647
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Definition Types.h:766
std::optional< ParamInfo > Self
Definition Types.h:772
unsigned RequiredInit
Whether this is a required initializer.
Definition Types.h:770
void setSwiftImportAsAccessors(std::optional< bool > Value)
Definition Types.h:490
std::optional< BoundsSafetyInfo > BoundsSafety
Definition Types.h:556
void setNoEscape(std::optional< bool > Value)
Definition Types.h:566
void setLifetimebound(std::optional< bool > Value)
Definition Types.h:575
void setRetainCountConvention(std::optional< RetainCountConventionKind > Value)
Definition Types.h:586
std::optional< std::string > SwiftReleaseOp
Definition Types.h:864
std::optional< std::string > SwiftRetainOp
Definition Types.h:863
std::optional< std::string > SwiftImportAs
Definition Types.h:862
std::optional< std::string > SwiftDefaultOwnership
Definition Types.h:866
std::optional< EnumExtensibilityKind > EnumExtensibility
Definition Types.h:868
void setSwiftCopyable(std::optional< bool > Value)
Definition Types.h:889
std::optional< std::string > SwiftDestroyOp
Definition Types.h:865
void setSwiftEscapable(std::optional< bool > Value)
Definition Types.h:899
void setFlagEnum(std::optional< bool > Value)
Definition Types.h:880
std::optional< SwiftNewTypeKind > SwiftWrapper
Definition Types.h:958
void setNullabilityAudited(NullabilityKind kind)
Definition Types.h:442
void setType(const std::string &type)
Definition Types.h:447
RetainCountConventionKind
Definition Types.h:43
bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile, llvm::raw_ostream &OS, llvm::SourceMgr::DiagHandlerTy DiagHandler=nullptr, void *DiagHandlerCtxt=nullptr)
Converts API notes from YAML format to binary format.
SwiftNewTypeKind
The kind of a swift_wrapper/swift_newtype.
Definition Types.h:61
EnumExtensibilityKind
The payload for an enum_extensibility attribute.
Definition Types.h:54
std::string formatAPINotesParameterSelector(RangeT &&Parameters)
Definition Types.h:34
bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS)
Parses the APINotes YAML content and writes the representation back to the specified stream.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool This(InterpState &S, CodePtr OpPC)
Definition Interp.h:3167
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
Definition Specifiers.h:349
@ Nullable
Values of this type can be null.
Definition Specifiers.h:353
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
Definition Specifiers.h:358
@ NonNull
Values of this type can never be null.
Definition Specifiers.h:351
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Definition Linkage.h:54
@ Property
The type of a property.
Definition TypeBase.h:912
@ Parameter
The parameter type of a method or function.
Definition TypeBase.h:909
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:6016
static void mapTopLevelItems(IO &IO, TopLevelItems &TLI)
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
#define false
Definition stdbool.h:26
llvm::ArrayRef< llvm::StringRef > Identifiers
Definition Types.h:1094
static void mapping(IO &IO, BoundsSafetyNotes &BS)
static void mapping(IO &IO, Class &C)
static void mapping(IO &IO, EnumConstant &EC)
static void mapping(IO &IO, Field &F)
static void mapping(IO &IO, FunctionWhere &W)
static void mapping(IO &IO, Function &F)
static void mapping(IO &IO, GlobalVariable &GV)
static void mapping(IO &IO, Method &M)
static void mapping(IO &IO, Module &M)
static void mapping(IO &IO, Namespace &T)
static void mapping(IO &IO, Param &P)
static void mapping(IO &IO, Property &P)
static void mapping(IO &IO, Tag &T)
static void mapping(IO &IO, Typedef &T)
static void mapping(IO &IO, Versioned &V)
static void enumeration(IO &IO, APIAvailability &AA)
static void enumeration(IO &IO, BoundsSafetyInfo::BoundsSafetyKind &AA)
static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK)
static void enumeration(IO &IO, EnumExtensibilityKind &EEK)
static void enumeration(IO &IO, FactoryAsInitKind &FIK)
static void enumeration(IO &IO, RetainCountConventionKind &RCCK)
static void enumeration(IO &IO, SwiftNewTypeKind &SWK)
static void enumeration(IO &IO, SwiftSafetyKind &SK)