1 //===-- Types.h - API Notes Data Types --------------------------*- 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 #ifndef LLVM_CLANG_APINOTES_TYPES_H
10 #define LLVM_CLANG_APINOTES_TYPES_H
11 
12 #include "clang/Basic/Specifiers.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/StringRef.h"
15 #include <climits>
16 #include <optional>
17 #include <vector>
18 
19 namespace llvm {
20 class raw_ostream;
21 } // namespace llvm
22 
23 namespace clang {
24 namespace api_notes {
25 enum class RetainCountConventionKind {
26   None,
27   CFReturnsRetained,
28   CFReturnsNotRetained,
29   NSReturnsRetained,
30   NSReturnsNotRetained,
31 };
32 
33 /// The payload for an enum_extensibility attribute. This is a tri-state rather
34 /// than just a boolean because the presence of the attribute indicates
35 /// auditing.
36 enum class EnumExtensibilityKind {
37   None,
38   Open,
39   Closed,
40 };
41 
42 /// The kind of a swift_wrapper/swift_newtype.
43 enum class SwiftNewTypeKind {
44   None,
45   Struct,
46   Enum,
47 };
48 
49 /// Describes API notes data for any entity.
50 ///
51 /// This is used as the base of all API notes.
52 class CommonEntityInfo {
53 public:
54   /// Message to use when this entity is unavailable.
55   std::string UnavailableMsg;
56 
57   /// Whether this entity is marked unavailable.
58   unsigned Unavailable : 1;
59 
60   /// Whether this entity is marked unavailable in Swift.
61   unsigned UnavailableInSwift : 1;
62 
63 private:
64   /// Whether SwiftPrivate was specified.
65   unsigned SwiftPrivateSpecified : 1;
66 
67   /// Whether this entity is considered "private" to a Swift overlay.
68   unsigned SwiftPrivate : 1;
69 
70 public:
71   /// Swift name of this entity.
72   std::string SwiftName;
73 
CommonEntityInfo()74   CommonEntityInfo()
75       : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
76         SwiftPrivate(0) {}
77 
isSwiftPrivate()78   std::optional<bool> isSwiftPrivate() const {
79     return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate)
80                                  : std::nullopt;
81   }
82 
setSwiftPrivate(std::optional<bool> Private)83   void setSwiftPrivate(std::optional<bool> Private) {
84     SwiftPrivateSpecified = Private.has_value();
85     SwiftPrivate = Private.value_or(0);
86   }
87 
88   friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &);
89 
90   CommonEntityInfo &operator|=(const CommonEntityInfo &RHS) {
91     // Merge unavailability.
92     if (RHS.Unavailable) {
93       Unavailable = true;
94       if (UnavailableMsg.empty())
95         UnavailableMsg = RHS.UnavailableMsg;
96     }
97 
98     if (RHS.UnavailableInSwift) {
99       UnavailableInSwift = true;
100       if (UnavailableMsg.empty())
101         UnavailableMsg = RHS.UnavailableMsg;
102     }
103 
104     if (!SwiftPrivateSpecified)
105       setSwiftPrivate(RHS.isSwiftPrivate());
106 
107     if (SwiftName.empty())
108       SwiftName = RHS.SwiftName;
109 
110     return *this;
111   }
112 
113   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
114 };
115 
116 inline bool operator==(const CommonEntityInfo &LHS,
117                        const CommonEntityInfo &RHS) {
118   return LHS.UnavailableMsg == RHS.UnavailableMsg &&
119          LHS.Unavailable == RHS.Unavailable &&
120          LHS.UnavailableInSwift == RHS.UnavailableInSwift &&
121          LHS.SwiftPrivateSpecified == RHS.SwiftPrivateSpecified &&
122          LHS.SwiftPrivate == RHS.SwiftPrivate && LHS.SwiftName == RHS.SwiftName;
123 }
124 
125 inline bool operator!=(const CommonEntityInfo &LHS,
126                        const CommonEntityInfo &RHS) {
127   return !(LHS == RHS);
128 }
129 
130 /// Describes API notes for types.
131 class CommonTypeInfo : public CommonEntityInfo {
132   /// The Swift type to which a given type is bridged.
133   ///
134   /// Reflects the swift_bridge attribute.
135   std::optional<std::string> SwiftBridge;
136 
137   /// The NS error domain for this type.
138   std::optional<std::string> NSErrorDomain;
139 
140 public:
CommonTypeInfo()141   CommonTypeInfo() {}
142 
getSwiftBridge()143   const std::optional<std::string> &getSwiftBridge() const {
144     return SwiftBridge;
145   }
146 
setSwiftBridge(std::optional<std::string> SwiftType)147   void setSwiftBridge(std::optional<std::string> SwiftType) {
148     SwiftBridge = SwiftType;
149   }
150 
getNSErrorDomain()151   const std::optional<std::string> &getNSErrorDomain() const {
152     return NSErrorDomain;
153   }
154 
setNSErrorDomain(const std::optional<std::string> & Domain)155   void setNSErrorDomain(const std::optional<std::string> &Domain) {
156     NSErrorDomain = Domain;
157   }
158 
setNSErrorDomain(const std::optional<llvm::StringRef> & Domain)159   void setNSErrorDomain(const std::optional<llvm::StringRef> &Domain) {
160     NSErrorDomain = Domain ? std::optional<std::string>(std::string(*Domain))
161                            : std::nullopt;
162   }
163 
164   friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &);
165 
166   CommonTypeInfo &operator|=(const CommonTypeInfo &RHS) {
167     // Merge inherited info.
168     static_cast<CommonEntityInfo &>(*this) |= RHS;
169 
170     if (!SwiftBridge)
171       setSwiftBridge(RHS.getSwiftBridge());
172     if (!NSErrorDomain)
173       setNSErrorDomain(RHS.getNSErrorDomain());
174 
175     return *this;
176   }
177 
178   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
179 };
180 
181 inline bool operator==(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
182   return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
183          LHS.SwiftBridge == RHS.SwiftBridge &&
184          LHS.NSErrorDomain == RHS.NSErrorDomain;
185 }
186 
187 inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
188   return !(LHS == RHS);
189 }
190 
191 /// Describes API notes data for an Objective-C class or protocol.
192 class ObjCContextInfo : public CommonTypeInfo {
193   /// Whether this class has a default nullability.
194   unsigned HasDefaultNullability : 1;
195 
196   /// The default nullability.
197   unsigned DefaultNullability : 2;
198 
199   /// Whether this class has designated initializers recorded.
200   unsigned HasDesignatedInits : 1;
201 
202   unsigned SwiftImportAsNonGenericSpecified : 1;
203   unsigned SwiftImportAsNonGeneric : 1;
204 
205   unsigned SwiftObjCMembersSpecified : 1;
206   unsigned SwiftObjCMembers : 1;
207 
208 public:
ObjCContextInfo()209   ObjCContextInfo()
210       : HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0),
211         SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false),
212         SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {}
213 
214   /// Determine the default nullability for properties and methods of this
215   /// class.
216   ///
217   /// Returns the default nullability, if implied, or std::nullopt if there is
218   /// none.
getDefaultNullability()219   std::optional<NullabilityKind> getDefaultNullability() const {
220     return HasDefaultNullability
221                ? std::optional<NullabilityKind>(
222                      static_cast<NullabilityKind>(DefaultNullability))
223                : std::nullopt;
224   }
225 
226   /// Set the default nullability for properties and methods of this class.
setDefaultNullability(NullabilityKind Kind)227   void setDefaultNullability(NullabilityKind Kind) {
228     HasDefaultNullability = true;
229     DefaultNullability = static_cast<unsigned>(Kind);
230   }
231 
hasDesignatedInits()232   bool hasDesignatedInits() const { return HasDesignatedInits; }
setHasDesignatedInits(bool Value)233   void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
234 
getSwiftImportAsNonGeneric()235   std::optional<bool> getSwiftImportAsNonGeneric() const {
236     return SwiftImportAsNonGenericSpecified
237                ? std::optional<bool>(SwiftImportAsNonGeneric)
238                : std::nullopt;
239   }
setSwiftImportAsNonGeneric(std::optional<bool> Value)240   void setSwiftImportAsNonGeneric(std::optional<bool> Value) {
241     SwiftImportAsNonGenericSpecified = Value.has_value();
242     SwiftImportAsNonGeneric = Value.value_or(false);
243   }
244 
getSwiftObjCMembers()245   std::optional<bool> getSwiftObjCMembers() const {
246     return SwiftObjCMembersSpecified ? std::optional<bool>(SwiftObjCMembers)
247                                      : std::nullopt;
248   }
setSwiftObjCMembers(std::optional<bool> Value)249   void setSwiftObjCMembers(std::optional<bool> Value) {
250     SwiftObjCMembersSpecified = Value.has_value();
251     SwiftObjCMembers = Value.value_or(false);
252   }
253 
254   /// Strip off any information within the class information structure that is
255   /// module-local, such as 'audited' flags.
stripModuleLocalInfo()256   void stripModuleLocalInfo() {
257     HasDefaultNullability = false;
258     DefaultNullability = 0;
259   }
260 
261   friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &);
262 
263   ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) {
264     // Merge inherited info.
265     static_cast<CommonTypeInfo &>(*this) |= RHS;
266 
267     // Merge nullability.
268     if (!getDefaultNullability())
269       if (auto Nullability = RHS.getDefaultNullability())
270         setDefaultNullability(*Nullability);
271 
272     if (!SwiftImportAsNonGenericSpecified)
273       setSwiftImportAsNonGeneric(RHS.getSwiftImportAsNonGeneric());
274 
275     if (!SwiftObjCMembersSpecified)
276       setSwiftObjCMembers(RHS.getSwiftObjCMembers());
277 
278     HasDesignatedInits |= RHS.HasDesignatedInits;
279 
280     return *this;
281   }
282 
283   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
284 };
285 
286 inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
287   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
288          LHS.getDefaultNullability() == RHS.getDefaultNullability() &&
289          LHS.HasDesignatedInits == RHS.HasDesignatedInits &&
290          LHS.getSwiftImportAsNonGeneric() == RHS.getSwiftImportAsNonGeneric() &&
291          LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers();
292 }
293 
294 inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
295   return !(LHS == RHS);
296 }
297 
298 /// API notes for a variable/property.
299 class VariableInfo : public CommonEntityInfo {
300   /// Whether this property has been audited for nullability.
301   unsigned NullabilityAudited : 1;
302 
303   /// The kind of nullability for this property. Only valid if the nullability
304   /// has been audited.
305   unsigned Nullable : 2;
306 
307   /// The C type of the variable, as a string.
308   std::string Type;
309 
310 public:
VariableInfo()311   VariableInfo() : NullabilityAudited(false), Nullable(0) {}
312 
getNullability()313   std::optional<NullabilityKind> getNullability() const {
314     return NullabilityAudited ? std::optional<NullabilityKind>(
315                                     static_cast<NullabilityKind>(Nullable))
316                               : std::nullopt;
317   }
318 
setNullabilityAudited(NullabilityKind kind)319   void setNullabilityAudited(NullabilityKind kind) {
320     NullabilityAudited = true;
321     Nullable = static_cast<unsigned>(kind);
322   }
323 
getType()324   const std::string &getType() const { return Type; }
setType(const std::string & type)325   void setType(const std::string &type) { Type = type; }
326 
327   friend bool operator==(const VariableInfo &, const VariableInfo &);
328 
329   VariableInfo &operator|=(const VariableInfo &RHS) {
330     static_cast<CommonEntityInfo &>(*this) |= RHS;
331 
332     if (!NullabilityAudited && RHS.NullabilityAudited)
333       setNullabilityAudited(*RHS.getNullability());
334     if (Type.empty())
335       Type = RHS.Type;
336 
337     return *this;
338   }
339 
340   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
341 };
342 
343 inline bool operator==(const VariableInfo &LHS, const VariableInfo &RHS) {
344   return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
345          LHS.NullabilityAudited == RHS.NullabilityAudited &&
346          LHS.Nullable == RHS.Nullable && LHS.Type == RHS.Type;
347 }
348 
349 inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) {
350   return !(LHS == RHS);
351 }
352 
353 /// Describes API notes data for an Objective-C property.
354 class ObjCPropertyInfo : public VariableInfo {
355   unsigned SwiftImportAsAccessorsSpecified : 1;
356   unsigned SwiftImportAsAccessors : 1;
357 
358 public:
ObjCPropertyInfo()359   ObjCPropertyInfo()
360       : SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
361 
getSwiftImportAsAccessors()362   std::optional<bool> getSwiftImportAsAccessors() const {
363     return SwiftImportAsAccessorsSpecified
364                ? std::optional<bool>(SwiftImportAsAccessors)
365                : std::nullopt;
366   }
setSwiftImportAsAccessors(std::optional<bool> Value)367   void setSwiftImportAsAccessors(std::optional<bool> Value) {
368     SwiftImportAsAccessorsSpecified = Value.has_value();
369     SwiftImportAsAccessors = Value.value_or(false);
370   }
371 
372   friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);
373 
374   /// Merge class-wide information into the given property.
375   ObjCPropertyInfo &operator|=(const ObjCContextInfo &RHS) {
376     static_cast<CommonEntityInfo &>(*this) |= RHS;
377 
378     // Merge nullability.
379     if (!getNullability())
380       if (auto Nullable = RHS.getDefaultNullability())
381         setNullabilityAudited(*Nullable);
382 
383     return *this;
384   }
385 
386   ObjCPropertyInfo &operator|=(const ObjCPropertyInfo &RHS) {
387     static_cast<VariableInfo &>(*this) |= RHS;
388 
389     if (!SwiftImportAsAccessorsSpecified)
390       setSwiftImportAsAccessors(RHS.getSwiftImportAsAccessors());
391 
392     return *this;
393   }
394 
395   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
396 };
397 
398 inline bool operator==(const ObjCPropertyInfo &LHS,
399                        const ObjCPropertyInfo &RHS) {
400   return static_cast<const VariableInfo &>(LHS) == RHS &&
401          LHS.getSwiftImportAsAccessors() == RHS.getSwiftImportAsAccessors();
402 }
403 
404 inline bool operator!=(const ObjCPropertyInfo &LHS,
405                        const ObjCPropertyInfo &RHS) {
406   return !(LHS == RHS);
407 }
408 
409 /// Describes a function or method parameter.
410 class ParamInfo : public VariableInfo {
411   /// Whether noescape was specified.
412   unsigned NoEscapeSpecified : 1;
413 
414   /// Whether the this parameter has the 'noescape' attribute.
415   unsigned NoEscape : 1;
416 
417   /// A biased RetainCountConventionKind, where 0 means "unspecified".
418   ///
419   /// Only relevant for out-parameters.
420   unsigned RawRetainCountConvention : 3;
421 
422 public:
ParamInfo()423   ParamInfo()
424       : NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {}
425 
isNoEscape()426   std::optional<bool> isNoEscape() const {
427     if (!NoEscapeSpecified)
428       return std::nullopt;
429     return NoEscape;
430   }
setNoEscape(std::optional<bool> Value)431   void setNoEscape(std::optional<bool> Value) {
432     NoEscapeSpecified = Value.has_value();
433     NoEscape = Value.value_or(false);
434   }
435 
getRetainCountConvention()436   std::optional<RetainCountConventionKind> getRetainCountConvention() const {
437     if (!RawRetainCountConvention)
438       return std::nullopt;
439     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
440   }
441   void
setRetainCountConvention(std::optional<RetainCountConventionKind> Value)442   setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
443     RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
444     assert(getRetainCountConvention() == Value && "bitfield too small");
445   }
446 
447   ParamInfo &operator|=(const ParamInfo &RHS) {
448     static_cast<VariableInfo &>(*this) |= RHS;
449 
450     if (!NoEscapeSpecified && RHS.NoEscapeSpecified) {
451       NoEscapeSpecified = true;
452       NoEscape = RHS.NoEscape;
453     }
454 
455     if (!RawRetainCountConvention)
456       RawRetainCountConvention = RHS.RawRetainCountConvention;
457 
458     return *this;
459   }
460 
461   friend bool operator==(const ParamInfo &, const ParamInfo &);
462 
463   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
464 };
465 
466 inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
467   return static_cast<const VariableInfo &>(LHS) == RHS &&
468          LHS.NoEscapeSpecified == RHS.NoEscapeSpecified &&
469          LHS.NoEscape == RHS.NoEscape &&
470          LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
471 }
472 
473 inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
474   return !(LHS == RHS);
475 }
476 
477 /// API notes for a function or method.
478 class FunctionInfo : public CommonEntityInfo {
479 private:
480   static constexpr const uint64_t NullabilityKindMask = 0x3;
481   static constexpr const unsigned NullabilityKindSize = 2;
482 
483   static constexpr const unsigned ReturnInfoIndex = 0;
484 
485 public:
486   // If yes, we consider all types to be non-nullable unless otherwise noted.
487   // If this flag is not set, the pointer types are considered to have
488   // unknown nullability.
489 
490   /// Whether the signature has been audited with respect to nullability.
491   unsigned NullabilityAudited : 1;
492 
493   /// Number of types whose nullability is encoded with the NullabilityPayload.
494   unsigned NumAdjustedNullable : 8;
495 
496   /// A biased RetainCountConventionKind, where 0 means "unspecified".
497   unsigned RawRetainCountConvention : 3;
498 
499   // NullabilityKindSize bits are used to encode the nullability. The info
500   // about the return type is stored at position 0, followed by the nullability
501   // of the parameters.
502 
503   /// Stores the nullability of the return type and the parameters.
504   uint64_t NullabilityPayload = 0;
505 
506   /// The result type of this function, as a C type.
507   std::string ResultType;
508 
509   /// The function parameters.
510   std::vector<ParamInfo> Params;
511 
FunctionInfo()512   FunctionInfo()
513       : NullabilityAudited(false), NumAdjustedNullable(0),
514         RawRetainCountConvention() {}
515 
getMaxNullabilityIndex()516   static unsigned getMaxNullabilityIndex() {
517     return ((sizeof(NullabilityPayload) * CHAR_BIT) / NullabilityKindSize);
518   }
519 
addTypeInfo(unsigned index,NullabilityKind kind)520   void addTypeInfo(unsigned index, NullabilityKind kind) {
521     assert(index <= getMaxNullabilityIndex());
522     assert(static_cast<unsigned>(kind) < NullabilityKindMask);
523 
524     NullabilityAudited = true;
525     if (NumAdjustedNullable < index + 1)
526       NumAdjustedNullable = index + 1;
527 
528     // Mask the bits.
529     NullabilityPayload &=
530         ~(NullabilityKindMask << (index * NullabilityKindSize));
531 
532     // Set the value.
533     unsigned kindValue = (static_cast<unsigned>(kind))
534                          << (index * NullabilityKindSize);
535     NullabilityPayload |= kindValue;
536   }
537 
538   /// Adds the return type info.
addReturnTypeInfo(NullabilityKind kind)539   void addReturnTypeInfo(NullabilityKind kind) {
540     addTypeInfo(ReturnInfoIndex, kind);
541   }
542 
543   /// Adds the parameter type info.
addParamTypeInfo(unsigned index,NullabilityKind kind)544   void addParamTypeInfo(unsigned index, NullabilityKind kind) {
545     addTypeInfo(index + 1, kind);
546   }
547 
getParamTypeInfo(unsigned index)548   NullabilityKind getParamTypeInfo(unsigned index) const {
549     return getTypeInfo(index + 1);
550   }
551 
getReturnTypeInfo()552   NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
553 
getRetainCountConvention()554   std::optional<RetainCountConventionKind> getRetainCountConvention() const {
555     if (!RawRetainCountConvention)
556       return std::nullopt;
557     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
558   }
559   void
setRetainCountConvention(std::optional<RetainCountConventionKind> Value)560   setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
561     RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
562     assert(getRetainCountConvention() == Value && "bitfield too small");
563   }
564 
565   friend bool operator==(const FunctionInfo &, const FunctionInfo &);
566 
567 private:
getTypeInfo(unsigned index)568   NullabilityKind getTypeInfo(unsigned index) const {
569     assert(NullabilityAudited &&
570            "Checking the type adjustment on non-audited method.");
571 
572     // If we don't have info about this parameter, return the default.
573     if (index > NumAdjustedNullable)
574       return NullabilityKind::NonNull;
575     auto nullability = NullabilityPayload >> (index * NullabilityKindSize);
576     return static_cast<NullabilityKind>(nullability & NullabilityKindMask);
577   }
578 
579 public:
580   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
581 };
582 
583 inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
584   return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
585          LHS.NullabilityAudited == RHS.NullabilityAudited &&
586          LHS.NumAdjustedNullable == RHS.NumAdjustedNullable &&
587          LHS.NullabilityPayload == RHS.NullabilityPayload &&
588          LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params &&
589          LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
590 }
591 
592 inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
593   return !(LHS == RHS);
594 }
595 
596 /// Describes API notes data for an Objective-C method.
597 class ObjCMethodInfo : public FunctionInfo {
598 public:
599   /// Whether this is a designated initializer of its class.
600   unsigned DesignatedInit : 1;
601 
602   /// Whether this is a required initializer.
603   unsigned RequiredInit : 1;
604 
ObjCMethodInfo()605   ObjCMethodInfo() : DesignatedInit(false), RequiredInit(false) {}
606 
607   friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);
608 
609   ObjCMethodInfo &operator|=(const ObjCContextInfo &RHS) {
610     // Merge Nullability.
611     if (!NullabilityAudited) {
612       if (auto Nullable = RHS.getDefaultNullability()) {
613         NullabilityAudited = true;
614         addTypeInfo(0, *Nullable);
615       }
616     }
617     return *this;
618   }
619 
620   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
621 };
622 
623 inline bool operator==(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
624   return static_cast<const FunctionInfo &>(LHS) == RHS &&
625          LHS.DesignatedInit == RHS.DesignatedInit &&
626          LHS.RequiredInit == RHS.RequiredInit;
627 }
628 
629 inline bool operator!=(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
630   return !(LHS == RHS);
631 }
632 
633 /// Describes API notes data for a global variable.
634 class GlobalVariableInfo : public VariableInfo {
635 public:
GlobalVariableInfo()636   GlobalVariableInfo() {}
637 };
638 
639 /// Describes API notes data for a global function.
640 class GlobalFunctionInfo : public FunctionInfo {
641 public:
GlobalFunctionInfo()642   GlobalFunctionInfo() {}
643 };
644 
645 /// Describes API notes data for an enumerator.
646 class EnumConstantInfo : public CommonEntityInfo {
647 public:
EnumConstantInfo()648   EnumConstantInfo() {}
649 };
650 
651 /// Describes API notes data for a tag.
652 class TagInfo : public CommonTypeInfo {
653   unsigned HasFlagEnum : 1;
654   unsigned IsFlagEnum : 1;
655 
656 public:
657   std::optional<std::string> SwiftImportAs;
658   std::optional<std::string> SwiftRetainOp;
659   std::optional<std::string> SwiftReleaseOp;
660 
661   std::optional<EnumExtensibilityKind> EnumExtensibility;
662 
TagInfo()663   TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
664 
isFlagEnum()665   std::optional<bool> isFlagEnum() const {
666     if (HasFlagEnum)
667       return IsFlagEnum;
668     return std::nullopt;
669   }
setFlagEnum(std::optional<bool> Value)670   void setFlagEnum(std::optional<bool> Value) {
671     HasFlagEnum = Value.has_value();
672     IsFlagEnum = Value.value_or(false);
673   }
674 
675   TagInfo &operator|=(const TagInfo &RHS) {
676     static_cast<CommonTypeInfo &>(*this) |= RHS;
677 
678     if (!SwiftImportAs)
679       SwiftImportAs = RHS.SwiftImportAs;
680     if (!SwiftRetainOp)
681       SwiftRetainOp = RHS.SwiftRetainOp;
682     if (!SwiftReleaseOp)
683       SwiftReleaseOp = RHS.SwiftReleaseOp;
684 
685     if (!HasFlagEnum)
686       setFlagEnum(RHS.isFlagEnum());
687 
688     if (!EnumExtensibility)
689       EnumExtensibility = RHS.EnumExtensibility;
690 
691     return *this;
692   }
693 
694   friend bool operator==(const TagInfo &, const TagInfo &);
695 
696   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
697 };
698 
699 inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
700   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
701          LHS.SwiftImportAs == RHS.SwiftImportAs &&
702          LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
703          LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
704          LHS.isFlagEnum() == RHS.isFlagEnum() &&
705          LHS.EnumExtensibility == RHS.EnumExtensibility;
706 }
707 
708 inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
709   return !(LHS == RHS);
710 }
711 
712 /// Describes API notes data for a typedef.
713 class TypedefInfo : public CommonTypeInfo {
714 public:
715   std::optional<SwiftNewTypeKind> SwiftWrapper;
716 
TypedefInfo()717   TypedefInfo() {}
718 
719   TypedefInfo &operator|=(const TypedefInfo &RHS) {
720     static_cast<CommonTypeInfo &>(*this) |= RHS;
721     if (!SwiftWrapper)
722       SwiftWrapper = RHS.SwiftWrapper;
723     return *this;
724   }
725 
726   friend bool operator==(const TypedefInfo &, const TypedefInfo &);
727 
728   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
729 };
730 
731 inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) {
732   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
733          LHS.SwiftWrapper == RHS.SwiftWrapper;
734 }
735 
736 inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) {
737   return !(LHS == RHS);
738 }
739 
740 /// The file extension used for the source representation of API notes.
741 static const constexpr char SOURCE_APINOTES_EXTENSION[] = "apinotes";
742 
743 /// Opaque context ID used to refer to an Objective-C class or protocol or a C++
744 /// namespace.
745 class ContextID {
746 public:
747   unsigned Value;
748 
ContextID(unsigned value)749   explicit ContextID(unsigned value) : Value(value) {}
750 };
751 
752 enum class ContextKind : uint8_t {
753   ObjCClass = 0,
754   ObjCProtocol = 1,
755   Namespace = 2,
756 };
757 
758 struct Context {
759   ContextID id;
760   ContextKind kind;
761 
ContextContext762   Context(ContextID id, ContextKind kind) : id(id), kind(kind) {}
763 };
764 
765 /// A temporary reference to an Objective-C selector, suitable for
766 /// referencing selector data on the stack.
767 ///
768 /// Instances of this struct do not store references to any of the
769 /// data they contain; it is up to the user to ensure that the data
770 /// referenced by the identifier list persists.
771 struct ObjCSelectorRef {
772   unsigned NumArgs;
773   llvm::ArrayRef<llvm::StringRef> Identifiers;
774 };
775 } // namespace api_notes
776 } // namespace clang
777 
778 #endif
779