Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp
35260 views
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
1144