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