xref: /freebsd/contrib/llvm-project/clang/include/clang/APINotes/Types.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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   /// 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:
ParamInfo()442   ParamInfo()
443       : NoEscapeSpecified(false), NoEscape(false),
444         LifetimeboundSpecified(false), Lifetimebound(false),
445         RawRetainCountConvention() {}
446 
isNoEscape()447   std::optional<bool> isNoEscape() const {
448     return NoEscapeSpecified ? std::optional<bool>(NoEscape) : std::nullopt;
449   }
setNoEscape(std::optional<bool> Value)450   void setNoEscape(std::optional<bool> Value) {
451     NoEscapeSpecified = Value.has_value();
452     NoEscape = Value.value_or(false);
453   }
454 
isLifetimebound()455   std::optional<bool> isLifetimebound() const {
456     return LifetimeboundSpecified ? std::optional<bool>(Lifetimebound)
457                                   : std::nullopt;
458   }
setLifetimebound(std::optional<bool> Value)459   void setLifetimebound(std::optional<bool> Value) {
460     LifetimeboundSpecified = Value.has_value();
461     Lifetimebound = Value.value_or(false);
462   }
463 
getRetainCountConvention()464   std::optional<RetainCountConventionKind> getRetainCountConvention() const {
465     if (!RawRetainCountConvention)
466       return std::nullopt;
467     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
468   }
469   void
setRetainCountConvention(std::optional<RetainCountConventionKind> Value)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 
FunctionInfo()551   FunctionInfo()
552       : NullabilityAudited(false), NumAdjustedNullable(0),
553         RawRetainCountConvention() {}
554 
getMaxNullabilityIndex()555   static unsigned getMaxNullabilityIndex() {
556     return ((sizeof(NullabilityPayload) * CHAR_BIT) / NullabilityKindSize);
557   }
558 
addTypeInfo(unsigned index,NullabilityKind kind)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.
addReturnTypeInfo(NullabilityKind kind)578   void addReturnTypeInfo(NullabilityKind kind) {
579     addTypeInfo(ReturnInfoIndex, kind);
580   }
581 
582   /// Adds the parameter type info.
addParamTypeInfo(unsigned index,NullabilityKind kind)583   void addParamTypeInfo(unsigned index, NullabilityKind kind) {
584     addTypeInfo(index + 1, kind);
585   }
586 
getParamTypeInfo(unsigned index)587   NullabilityKind getParamTypeInfo(unsigned index) const {
588     return getTypeInfo(index + 1);
589   }
590 
getReturnTypeInfo()591   NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
592 
getRetainCountConvention()593   std::optional<RetainCountConventionKind> getRetainCountConvention() const {
594     if (!RawRetainCountConvention)
595       return std::nullopt;
596     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
597   }
598   void
setRetainCountConvention(std::optional<RetainCountConventionKind> Value)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:
getTypeInfo(unsigned index)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 
ObjCMethodInfo()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:
GlobalVariableInfo()680   GlobalVariableInfo() {}
681 };
682 
683 /// Describes API notes data for a global function.
684 class GlobalFunctionInfo : public FunctionInfo {
685 public:
GlobalFunctionInfo()686   GlobalFunctionInfo() {}
687 };
688 
689 /// Describes API notes data for a C/C++ record field.
690 class FieldInfo : public VariableInfo {
691 public:
FieldInfo()692   FieldInfo() {}
693 };
694 
695 /// Describes API notes data for a C++ method.
696 class CXXMethodInfo : public FunctionInfo {
697 public:
CXXMethodInfo()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:
EnumConstantInfo()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   std::optional<std::string> SwiftDefaultOwnership;
741 
742   /// The Swift protocol that this type should be automatically conformed to.
743   std::optional<std::string> SwiftConformance;
744 
745   std::optional<EnumExtensibilityKind> EnumExtensibility;
746 
TagInfo()747   TagInfo()
748       : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false),
749         SwiftCopyable(false), SwiftEscapableSpecified(false),
750         SwiftEscapable(false) {}
751 
isFlagEnum()752   std::optional<bool> isFlagEnum() const {
753     if (HasFlagEnum)
754       return IsFlagEnum;
755     return std::nullopt;
756   }
setFlagEnum(std::optional<bool> Value)757   void setFlagEnum(std::optional<bool> Value) {
758     HasFlagEnum = Value.has_value();
759     IsFlagEnum = Value.value_or(false);
760   }
761 
isSwiftCopyable()762   std::optional<bool> isSwiftCopyable() const {
763     return SwiftCopyableSpecified ? std::optional<bool>(SwiftCopyable)
764                                   : std::nullopt;
765   }
setSwiftCopyable(std::optional<bool> Value)766   void setSwiftCopyable(std::optional<bool> Value) {
767     SwiftCopyableSpecified = Value.has_value();
768     SwiftCopyable = Value.value_or(false);
769   }
770 
isSwiftEscapable()771   std::optional<bool> isSwiftEscapable() const {
772     return SwiftEscapableSpecified ? std::optional<bool>(SwiftEscapable)
773                                    : std::nullopt;
774   }
775 
setSwiftEscapable(std::optional<bool> Value)776   void setSwiftEscapable(std::optional<bool> Value) {
777     SwiftEscapableSpecified = Value.has_value();
778     SwiftEscapable = Value.value_or(false);
779   }
780 
781   TagInfo &operator|=(const TagInfo &RHS) {
782     static_cast<CommonTypeInfo &>(*this) |= RHS;
783 
784     if (!SwiftImportAs)
785       SwiftImportAs = RHS.SwiftImportAs;
786     if (!SwiftRetainOp)
787       SwiftRetainOp = RHS.SwiftRetainOp;
788     if (!SwiftReleaseOp)
789       SwiftReleaseOp = RHS.SwiftReleaseOp;
790     if (!SwiftDefaultOwnership)
791       SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
792 
793     if (!SwiftConformance)
794       SwiftConformance = RHS.SwiftConformance;
795 
796     if (!HasFlagEnum)
797       setFlagEnum(RHS.isFlagEnum());
798 
799     if (!EnumExtensibility)
800       EnumExtensibility = RHS.EnumExtensibility;
801 
802     if (!SwiftCopyableSpecified)
803       setSwiftCopyable(RHS.isSwiftCopyable());
804 
805     if (!SwiftEscapableSpecified)
806       setSwiftEscapable(RHS.isSwiftEscapable());
807 
808     return *this;
809   }
810 
811   friend bool operator==(const TagInfo &, const TagInfo &);
812 
813   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
814 };
815 
816 inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
817   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
818          LHS.SwiftImportAs == RHS.SwiftImportAs &&
819          LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
820          LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
821          LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
822          LHS.SwiftConformance == RHS.SwiftConformance &&
823          LHS.isFlagEnum() == RHS.isFlagEnum() &&
824          LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
825          LHS.isSwiftEscapable() == RHS.isSwiftEscapable() &&
826          LHS.EnumExtensibility == RHS.EnumExtensibility;
827 }
828 
829 inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
830   return !(LHS == RHS);
831 }
832 
833 /// Describes API notes data for a typedef.
834 class TypedefInfo : public CommonTypeInfo {
835 public:
836   std::optional<SwiftNewTypeKind> SwiftWrapper;
837 
TypedefInfo()838   TypedefInfo() {}
839 
840   TypedefInfo &operator|=(const TypedefInfo &RHS) {
841     static_cast<CommonTypeInfo &>(*this) |= RHS;
842     if (!SwiftWrapper)
843       SwiftWrapper = RHS.SwiftWrapper;
844     return *this;
845   }
846 
847   friend bool operator==(const TypedefInfo &, const TypedefInfo &);
848 
849   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
850 };
851 
852 inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) {
853   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
854          LHS.SwiftWrapper == RHS.SwiftWrapper;
855 }
856 
857 inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) {
858   return !(LHS == RHS);
859 }
860 
861 /// The file extension used for the source representation of API notes.
862 static const constexpr char SOURCE_APINOTES_EXTENSION[] = "apinotes";
863 
864 /// Opaque context ID used to refer to an Objective-C class or protocol or a C++
865 /// namespace.
866 class ContextID {
867 public:
868   unsigned Value;
869 
ContextID(unsigned value)870   explicit ContextID(unsigned value) : Value(value) {}
871 };
872 
873 enum class ContextKind : uint8_t {
874   ObjCClass = 0,
875   ObjCProtocol = 1,
876   Namespace = 2,
877   Tag = 3,
878 };
879 
880 struct Context {
881   ContextID id;
882   ContextKind kind;
883 
ContextContext884   Context(ContextID id, ContextKind kind) : id(id), kind(kind) {}
885 };
886 
887 /// A temporary reference to an Objective-C selector, suitable for
888 /// referencing selector data on the stack.
889 ///
890 /// Instances of this struct do not store references to any of the
891 /// data they contain; it is up to the user to ensure that the data
892 /// referenced by the identifier list persists.
893 struct ObjCSelectorRef {
894   unsigned NumArgs;
895   llvm::ArrayRef<llvm::StringRef> Identifiers;
896 };
897 } // namespace api_notes
898 } // namespace clang
899 
900 #endif
901