xref: /llvm-project/clang/include/clang/APINotes/Types.h (revision 48f7f63ac723a5001b74627493d360ff3d8d1186)
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 
78   CommonEntityInfo()
79       : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
80         SwiftPrivate(0) {}
81 
82   std::optional<bool> isSwiftPrivate() const {
83     return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate)
84                                  : std::nullopt;
85   }
86 
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:
145   CommonTypeInfo() {}
146 
147   const std::optional<std::string> &getSwiftBridge() const {
148     return SwiftBridge;
149   }
150 
151   void setSwiftBridge(std::optional<std::string> SwiftType) {
152     SwiftBridge = SwiftType;
153   }
154 
155   const std::optional<std::string> &getNSErrorDomain() const {
156     return NSErrorDomain;
157   }
158 
159   void setNSErrorDomain(const std::optional<std::string> &Domain) {
160     NSErrorDomain = Domain;
161   }
162 
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:
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.
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.
239   void setDefaultNullability(NullabilityKind Kind) {
240     HasDefaultNullability = true;
241     DefaultNullability = static_cast<unsigned>(Kind);
242   }
243 
244   bool hasDesignatedInits() const { return HasDesignatedInits; }
245   void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
246 
247   std::optional<bool> getSwiftImportAsNonGeneric() const {
248     return SwiftImportAsNonGenericSpecified
249                ? std::optional<bool>(SwiftImportAsNonGeneric)
250                : std::nullopt;
251   }
252   void setSwiftImportAsNonGeneric(std::optional<bool> Value) {
253     SwiftImportAsNonGenericSpecified = Value.has_value();
254     SwiftImportAsNonGeneric = Value.value_or(false);
255   }
256 
257   std::optional<bool> getSwiftObjCMembers() const {
258     return SwiftObjCMembersSpecified ? std::optional<bool>(SwiftObjCMembers)
259                                      : std::nullopt;
260   }
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:
318   VariableInfo() : NullabilityAudited(false), Nullable(0) {}
319 
320   std::optional<NullabilityKind> getNullability() const {
321     return NullabilityAudited ? std::optional<NullabilityKind>(
322                                     static_cast<NullabilityKind>(Nullable))
323                               : std::nullopt;
324   }
325 
326   void setNullabilityAudited(NullabilityKind kind) {
327     NullabilityAudited = true;
328     Nullable = static_cast<unsigned>(kind);
329   }
330 
331   const std::string &getType() const { return 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:
368   ObjCPropertyInfo()
369       : SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
370 
371   std::optional<bool> getSwiftImportAsAccessors() const {
372     return SwiftImportAsAccessorsSpecified
373                ? std::optional<bool>(SwiftImportAsAccessors)
374                : std::nullopt;
375   }
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   /// Whether lifetimebound was specified.
429   LLVM_PREFERRED_TYPE(bool)
430   unsigned LifetimeboundSpecified : 1;
431 
432   /// Whether the this parameter has the 'lifetimebound' attribute.
433   LLVM_PREFERRED_TYPE(bool)
434   unsigned Lifetimebound : 1;
435 
436   /// A biased RetainCountConventionKind, where 0 means "unspecified".
437   ///
438   /// Only relevant for out-parameters.
439   unsigned RawRetainCountConvention : 3;
440 
441 public:
442   ParamInfo()
443       : NoEscapeSpecified(false), NoEscape(false),
444         LifetimeboundSpecified(false), Lifetimebound(false),
445         RawRetainCountConvention() {}
446 
447   std::optional<bool> isNoEscape() const {
448     return NoEscapeSpecified ? std::optional<bool>(NoEscape) : std::nullopt;
449   }
450   void setNoEscape(std::optional<bool> Value) {
451     NoEscapeSpecified = Value.has_value();
452     NoEscape = Value.value_or(false);
453   }
454 
455   std::optional<bool> isLifetimebound() const {
456     return LifetimeboundSpecified ? std::optional<bool>(Lifetimebound)
457                                   : std::nullopt;
458   }
459   void setLifetimebound(std::optional<bool> Value) {
460     LifetimeboundSpecified = Value.has_value();
461     Lifetimebound = Value.value_or(false);
462   }
463 
464   std::optional<RetainCountConventionKind> getRetainCountConvention() const {
465     if (!RawRetainCountConvention)
466       return std::nullopt;
467     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
468   }
469   void
470   setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
471     RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
472     assert(getRetainCountConvention() == Value && "bitfield too small");
473   }
474 
475   ParamInfo &operator|=(const ParamInfo &RHS) {
476     static_cast<VariableInfo &>(*this) |= RHS;
477 
478     if (!NoEscapeSpecified && RHS.NoEscapeSpecified) {
479       NoEscapeSpecified = true;
480       NoEscape = RHS.NoEscape;
481     }
482 
483     if (!LifetimeboundSpecified && RHS.LifetimeboundSpecified) {
484       LifetimeboundSpecified = true;
485       Lifetimebound = RHS.Lifetimebound;
486     }
487 
488     if (!RawRetainCountConvention)
489       RawRetainCountConvention = RHS.RawRetainCountConvention;
490 
491     return *this;
492   }
493 
494   friend bool operator==(const ParamInfo &, const ParamInfo &);
495 
496   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
497 };
498 
499 inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
500   return static_cast<const VariableInfo &>(LHS) == RHS &&
501          LHS.NoEscapeSpecified == RHS.NoEscapeSpecified &&
502          LHS.NoEscape == RHS.NoEscape &&
503          LHS.LifetimeboundSpecified == RHS.LifetimeboundSpecified &&
504          LHS.Lifetimebound == RHS.Lifetimebound &&
505          LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
506 }
507 
508 inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
509   return !(LHS == RHS);
510 }
511 
512 /// API notes for a function or method.
513 class FunctionInfo : public CommonEntityInfo {
514 private:
515   static constexpr const uint64_t NullabilityKindMask = 0x3;
516   static constexpr const unsigned NullabilityKindSize = 2;
517 
518   static constexpr const unsigned ReturnInfoIndex = 0;
519 
520 public:
521   // If yes, we consider all types to be non-nullable unless otherwise noted.
522   // If this flag is not set, the pointer types are considered to have
523   // unknown nullability.
524 
525   /// Whether the signature has been audited with respect to nullability.
526   LLVM_PREFERRED_TYPE(bool)
527   unsigned NullabilityAudited : 1;
528 
529   /// Number of types whose nullability is encoded with the NullabilityPayload.
530   unsigned NumAdjustedNullable : 8;
531 
532   /// A biased RetainCountConventionKind, where 0 means "unspecified".
533   unsigned RawRetainCountConvention : 3;
534 
535   // NullabilityKindSize bits are used to encode the nullability. The info
536   // about the return type is stored at position 0, followed by the nullability
537   // of the parameters.
538 
539   /// Stores the nullability of the return type and the parameters.
540   uint64_t NullabilityPayload = 0;
541 
542   /// The result type of this function, as a C type.
543   std::string ResultType;
544 
545   /// Ownership convention for return value
546   std::string SwiftReturnOwnership;
547 
548   /// The function parameters.
549   std::vector<ParamInfo> Params;
550 
551   FunctionInfo()
552       : NullabilityAudited(false), NumAdjustedNullable(0),
553         RawRetainCountConvention() {}
554 
555   static unsigned getMaxNullabilityIndex() {
556     return ((sizeof(NullabilityPayload) * CHAR_BIT) / NullabilityKindSize);
557   }
558 
559   void addTypeInfo(unsigned index, NullabilityKind kind) {
560     assert(index <= getMaxNullabilityIndex());
561     assert(static_cast<unsigned>(kind) < NullabilityKindMask);
562 
563     NullabilityAudited = true;
564     if (NumAdjustedNullable < index + 1)
565       NumAdjustedNullable = index + 1;
566 
567     // Mask the bits.
568     NullabilityPayload &=
569         ~(NullabilityKindMask << (index * NullabilityKindSize));
570 
571     // Set the value.
572     unsigned kindValue = (static_cast<unsigned>(kind))
573                          << (index * NullabilityKindSize);
574     NullabilityPayload |= kindValue;
575   }
576 
577   /// Adds the return type info.
578   void addReturnTypeInfo(NullabilityKind kind) {
579     addTypeInfo(ReturnInfoIndex, kind);
580   }
581 
582   /// Adds the parameter type info.
583   void addParamTypeInfo(unsigned index, NullabilityKind kind) {
584     addTypeInfo(index + 1, kind);
585   }
586 
587   NullabilityKind getParamTypeInfo(unsigned index) const {
588     return getTypeInfo(index + 1);
589   }
590 
591   NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
592 
593   std::optional<RetainCountConventionKind> getRetainCountConvention() const {
594     if (!RawRetainCountConvention)
595       return std::nullopt;
596     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
597   }
598   void
599   setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
600     RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
601     assert(getRetainCountConvention() == Value && "bitfield too small");
602   }
603 
604   friend bool operator==(const FunctionInfo &, const FunctionInfo &);
605 
606 private:
607   NullabilityKind getTypeInfo(unsigned index) const {
608     assert(NullabilityAudited &&
609            "Checking the type adjustment on non-audited method.");
610 
611     // If we don't have info about this parameter, return the default.
612     if (index > NumAdjustedNullable)
613       return NullabilityKind::NonNull;
614     auto nullability = NullabilityPayload >> (index * NullabilityKindSize);
615     return static_cast<NullabilityKind>(nullability & NullabilityKindMask);
616   }
617 
618 public:
619   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
620 };
621 
622 inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
623   return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
624          LHS.NullabilityAudited == RHS.NullabilityAudited &&
625          LHS.NumAdjustedNullable == RHS.NumAdjustedNullable &&
626          LHS.NullabilityPayload == RHS.NullabilityPayload &&
627          LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params &&
628          LHS.RawRetainCountConvention == RHS.RawRetainCountConvention &&
629          LHS.SwiftReturnOwnership == RHS.SwiftReturnOwnership;
630 }
631 
632 inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
633   return !(LHS == RHS);
634 }
635 
636 /// Describes API notes data for an Objective-C method.
637 class ObjCMethodInfo : public FunctionInfo {
638 public:
639   /// Whether this is a designated initializer of its class.
640   LLVM_PREFERRED_TYPE(bool)
641   unsigned DesignatedInit : 1;
642 
643   /// Whether this is a required initializer.
644   LLVM_PREFERRED_TYPE(bool)
645   unsigned RequiredInit : 1;
646 
647   std::optional<ParamInfo> Self;
648 
649   ObjCMethodInfo() : DesignatedInit(false), RequiredInit(false) {}
650 
651   friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);
652 
653   ObjCMethodInfo &operator|=(const ContextInfo &RHS) {
654     // Merge Nullability.
655     if (!NullabilityAudited) {
656       if (auto Nullable = RHS.getDefaultNullability()) {
657         NullabilityAudited = true;
658         addTypeInfo(0, *Nullable);
659       }
660     }
661     return *this;
662   }
663 
664   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
665 };
666 
667 inline bool operator==(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
668   return static_cast<const FunctionInfo &>(LHS) == RHS &&
669          LHS.DesignatedInit == RHS.DesignatedInit &&
670          LHS.RequiredInit == RHS.RequiredInit && LHS.Self == RHS.Self;
671 }
672 
673 inline bool operator!=(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
674   return !(LHS == RHS);
675 }
676 
677 /// Describes API notes data for a global variable.
678 class GlobalVariableInfo : public VariableInfo {
679 public:
680   GlobalVariableInfo() {}
681 };
682 
683 /// Describes API notes data for a global function.
684 class GlobalFunctionInfo : public FunctionInfo {
685 public:
686   GlobalFunctionInfo() {}
687 };
688 
689 /// Describes API notes data for a C/C++ record field.
690 class FieldInfo : public VariableInfo {
691 public:
692   FieldInfo() {}
693 };
694 
695 /// Describes API notes data for a C++ method.
696 class CXXMethodInfo : public FunctionInfo {
697 public:
698   CXXMethodInfo() {}
699 
700   std::optional<ParamInfo> This;
701 
702   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
703 };
704 
705 inline bool operator==(const CXXMethodInfo &LHS, const CXXMethodInfo &RHS) {
706   return static_cast<const FunctionInfo &>(LHS) == RHS && LHS.This == RHS.This;
707 }
708 
709 inline bool operator!=(const CXXMethodInfo &LHS, const CXXMethodInfo &RHS) {
710   return !(LHS == RHS);
711 }
712 
713 /// Describes API notes data for an enumerator.
714 class EnumConstantInfo : public CommonEntityInfo {
715 public:
716   EnumConstantInfo() {}
717 };
718 
719 /// Describes API notes data for a tag.
720 class TagInfo : public CommonTypeInfo {
721   LLVM_PREFERRED_TYPE(bool)
722   unsigned HasFlagEnum : 1;
723   LLVM_PREFERRED_TYPE(bool)
724   unsigned IsFlagEnum : 1;
725 
726   LLVM_PREFERRED_TYPE(bool)
727   unsigned SwiftCopyableSpecified : 1;
728   LLVM_PREFERRED_TYPE(bool)
729   unsigned SwiftCopyable : 1;
730 
731   LLVM_PREFERRED_TYPE(bool)
732   unsigned SwiftEscapableSpecified : 1;
733   LLVM_PREFERRED_TYPE(bool)
734   unsigned SwiftEscapable : 1;
735 
736 public:
737   std::optional<std::string> SwiftImportAs;
738   std::optional<std::string> SwiftRetainOp;
739   std::optional<std::string> SwiftReleaseOp;
740 
741   /// The Swift protocol that this type should be automatically conformed to.
742   std::optional<std::string> SwiftConformance;
743 
744   std::optional<EnumExtensibilityKind> EnumExtensibility;
745 
746   TagInfo()
747       : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false),
748         SwiftCopyable(false), SwiftEscapableSpecified(false),
749         SwiftEscapable(false) {}
750 
751   std::optional<bool> isFlagEnum() const {
752     if (HasFlagEnum)
753       return IsFlagEnum;
754     return std::nullopt;
755   }
756   void setFlagEnum(std::optional<bool> Value) {
757     HasFlagEnum = Value.has_value();
758     IsFlagEnum = Value.value_or(false);
759   }
760 
761   std::optional<bool> isSwiftCopyable() const {
762     return SwiftCopyableSpecified ? std::optional<bool>(SwiftCopyable)
763                                   : std::nullopt;
764   }
765   void setSwiftCopyable(std::optional<bool> Value) {
766     SwiftCopyableSpecified = Value.has_value();
767     SwiftCopyable = Value.value_or(false);
768   }
769 
770   std::optional<bool> isSwiftEscapable() const {
771     return SwiftEscapableSpecified ? std::optional<bool>(SwiftEscapable)
772                                    : std::nullopt;
773   }
774 
775   void setSwiftEscapable(std::optional<bool> Value) {
776     SwiftEscapableSpecified = Value.has_value();
777     SwiftEscapable = Value.value_or(false);
778   }
779 
780   TagInfo &operator|=(const TagInfo &RHS) {
781     static_cast<CommonTypeInfo &>(*this) |= RHS;
782 
783     if (!SwiftImportAs)
784       SwiftImportAs = RHS.SwiftImportAs;
785     if (!SwiftRetainOp)
786       SwiftRetainOp = RHS.SwiftRetainOp;
787     if (!SwiftReleaseOp)
788       SwiftReleaseOp = RHS.SwiftReleaseOp;
789 
790     if (!SwiftConformance)
791       SwiftConformance = RHS.SwiftConformance;
792 
793     if (!HasFlagEnum)
794       setFlagEnum(RHS.isFlagEnum());
795 
796     if (!EnumExtensibility)
797       EnumExtensibility = RHS.EnumExtensibility;
798 
799     if (!SwiftCopyableSpecified)
800       setSwiftCopyable(RHS.isSwiftCopyable());
801 
802     if (!SwiftEscapableSpecified)
803       setSwiftEscapable(RHS.isSwiftEscapable());
804 
805     return *this;
806   }
807 
808   friend bool operator==(const TagInfo &, const TagInfo &);
809 
810   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
811 };
812 
813 inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
814   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
815          LHS.SwiftImportAs == RHS.SwiftImportAs &&
816          LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
817          LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
818          LHS.SwiftConformance == RHS.SwiftConformance &&
819          LHS.isFlagEnum() == RHS.isFlagEnum() &&
820          LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
821          LHS.isSwiftEscapable() == RHS.isSwiftEscapable() &&
822          LHS.EnumExtensibility == RHS.EnumExtensibility;
823 }
824 
825 inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
826   return !(LHS == RHS);
827 }
828 
829 /// Describes API notes data for a typedef.
830 class TypedefInfo : public CommonTypeInfo {
831 public:
832   std::optional<SwiftNewTypeKind> SwiftWrapper;
833 
834   TypedefInfo() {}
835 
836   TypedefInfo &operator|=(const TypedefInfo &RHS) {
837     static_cast<CommonTypeInfo &>(*this) |= RHS;
838     if (!SwiftWrapper)
839       SwiftWrapper = RHS.SwiftWrapper;
840     return *this;
841   }
842 
843   friend bool operator==(const TypedefInfo &, const TypedefInfo &);
844 
845   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
846 };
847 
848 inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) {
849   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
850          LHS.SwiftWrapper == RHS.SwiftWrapper;
851 }
852 
853 inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) {
854   return !(LHS == RHS);
855 }
856 
857 /// The file extension used for the source representation of API notes.
858 static const constexpr char SOURCE_APINOTES_EXTENSION[] = "apinotes";
859 
860 /// Opaque context ID used to refer to an Objective-C class or protocol or a C++
861 /// namespace.
862 class ContextID {
863 public:
864   unsigned Value;
865 
866   explicit ContextID(unsigned value) : Value(value) {}
867 };
868 
869 enum class ContextKind : uint8_t {
870   ObjCClass = 0,
871   ObjCProtocol = 1,
872   Namespace = 2,
873   Tag = 3,
874 };
875 
876 struct Context {
877   ContextID id;
878   ContextKind kind;
879 
880   Context(ContextID id, ContextKind kind) : id(id), kind(kind) {}
881 };
882 
883 /// A temporary reference to an Objective-C selector, suitable for
884 /// referencing selector data on the stack.
885 ///
886 /// Instances of this struct do not store references to any of the
887 /// data they contain; it is up to the user to ensure that the data
888 /// referenced by the identifier list persists.
889 struct ObjCSelectorRef {
890   unsigned NumArgs;
891   llvm::ArrayRef<llvm::StringRef> Identifiers;
892 };
893 } // namespace api_notes
894 } // namespace clang
895 
896 #endif
897