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