[clang] f6b02ec - APINotes: add property models for YAML attributes

Saleem Abdulrasool via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 23 13:33:39 PST 2020


Author: Saleem Abdulrasool
Date: 2020-11-23T21:29:17Z
New Revision: f6b02ecd027a825f1f4a1804c464f9f96d9372c9

URL: https://github.com/llvm/llvm-project/commit/f6b02ecd027a825f1f4a1804c464f9f96d9372c9
DIFF: https://github.com/llvm/llvm-project/commit/f6b02ecd027a825f1f4a1804c464f9f96d9372c9.diff

LOG: APINotes: add property models for YAML attributes

This adds internal representation of the attributes in a more usable
form.  This is meant to allow programmatic access to the attributes that
are specified in the YAML data.

This is based upon the work contributed by Apple at
https://github.com/llvm/llvm-project-staging/tree/staging/swift/apinotes.

Differential Revision: https://reviews.llvm.org/D91104
Reviewed By: Gabor Marton

Added: 
    clang/lib/APINotes/APINotesTypes.cpp

Modified: 
    clang/include/clang/APINotes/Types.h
    clang/lib/APINotes/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h
index be2a99ad6fd0..3095bfbf1718 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -9,6 +9,12 @@
 #ifndef LLVM_CLANG_APINOTES_TYPES_H
 #define LLVM_CLANG_APINOTES_TYPES_H
 
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <climits>
+#include <vector>
+
 namespace clang {
 namespace api_notes {
 enum class RetainCountConventionKind {
@@ -34,6 +40,694 @@ enum class SwiftNewTypeKind {
   Struct,
   Enum,
 };
+
+/// Describes API notes data for any entity.
+///
+/// This is used as the base of all API notes.
+class CommonEntityInfo {
+public:
+  /// Message to use when this entity is unavailable.
+  std::string UnavailableMsg;
+
+  /// Whether this entity is marked unavailable.
+  unsigned Unavailable : 1;
+
+  /// Whether this entity is marked unavailable in Swift.
+  unsigned UnavailableInSwift : 1;
+
+private:
+  /// Whether SwiftPrivate was specified.
+  unsigned SwiftPrivateSpecified : 1;
+
+  /// Whether this entity is considered "private" to a Swift overlay.
+  unsigned SwiftPrivate : 1;
+
+public:
+  /// Swift name of this entity.
+  std::string SwiftName;
+
+  CommonEntityInfo()
+      : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
+        SwiftPrivate(0) {}
+
+  llvm::Optional<bool> isSwiftPrivate() const {
+    return SwiftPrivateSpecified ? llvm::Optional<bool>(SwiftPrivate)
+                                 : llvm::None;
+  }
+
+  void setSwiftPrivate(llvm::Optional<bool> Private) {
+    SwiftPrivateSpecified = Private.hasValue();
+    SwiftPrivate = Private.hasValue() ? *Private : 0;
+  }
+
+  friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &);
+
+  CommonEntityInfo &operator|=(const CommonEntityInfo &RHS) {
+    // Merge unavailability.
+    if (RHS.Unavailable) {
+      Unavailable = true;
+      if (UnavailableMsg.empty())
+        UnavailableMsg = RHS.UnavailableMsg;
+    }
+
+    if (RHS.UnavailableInSwift) {
+      UnavailableInSwift = true;
+      if (UnavailableMsg.empty())
+        UnavailableMsg = RHS.UnavailableMsg;
+    }
+
+    if (!SwiftPrivateSpecified)
+      setSwiftPrivate(RHS.isSwiftPrivate());
+
+    if (SwiftName.empty())
+      SwiftName = RHS.SwiftName;
+
+    return *this;
+  }
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const CommonEntityInfo &LHS,
+                       const CommonEntityInfo &RHS) {
+  return LHS.UnavailableMsg == RHS.UnavailableMsg &&
+         LHS.Unavailable == RHS.Unavailable &&
+         LHS.UnavailableInSwift == RHS.UnavailableInSwift &&
+         LHS.SwiftPrivateSpecified == RHS.SwiftPrivateSpecified &&
+         LHS.SwiftPrivate == RHS.SwiftPrivate && LHS.SwiftName == RHS.SwiftName;
+}
+
+inline bool operator!=(const CommonEntityInfo &LHS,
+                       const CommonEntityInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes API notes for types.
+class CommonTypeInfo : public CommonEntityInfo {
+  /// The Swift type to which a given type is bridged.
+  ///
+  /// Reflects the swift_bridge attribute.
+  llvm::Optional<std::string> SwiftBridge;
+
+  /// The NS error domain for this type.
+  llvm::Optional<std::string> NSErrorDomain;
+
+public:
+  CommonTypeInfo() : CommonEntityInfo() {}
+
+  const llvm::Optional<std::string> &getSwiftBridge() const {
+    return SwiftBridge;
+  }
+
+  void setSwiftBridge(const llvm::Optional<std::string> &SwiftType) {
+    SwiftBridge = SwiftType;
+  }
+
+  void setSwiftBridge(const llvm::Optional<llvm::StringRef> &SwiftType) {
+    SwiftBridge = SwiftType
+                      ? llvm::Optional<std::string>(std::string(*SwiftType))
+                      : llvm::None;
+  }
+
+  const llvm::Optional<std::string> &getNSErrorDomain() const {
+    return NSErrorDomain;
+  }
+
+  void setNSErrorDomain(const llvm::Optional<std::string> &Domain) {
+    NSErrorDomain = Domain;
+  }
+
+  void setNSErrorDomain(const llvm::Optional<llvm::StringRef> &Domain) {
+    NSErrorDomain =
+        Domain ? llvm::Optional<std::string>(std::string(*Domain)) : llvm::None;
+  }
+
+  friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &);
+
+  CommonTypeInfo &operator|=(const CommonTypeInfo &RHS) {
+    // Merge inherited info.
+    static_cast<CommonEntityInfo &>(*this) |= RHS;
+
+    if (!SwiftBridge)
+      setSwiftBridge(RHS.getSwiftBridge());
+    if (!NSErrorDomain)
+      setNSErrorDomain(RHS.getNSErrorDomain());
+
+    return *this;
+  }
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
+  return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
+         LHS.SwiftBridge == RHS.SwiftBridge &&
+         LHS.NSErrorDomain == RHS.NSErrorDomain;
+}
+
+inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes API notes data for an Objective-C class or protocol.
+class ObjCContextInfo : public CommonTypeInfo {
+  /// Whether this class has a default nullability.
+  unsigned HasDefaultNullability : 1;
+
+  /// The default nullability.
+  unsigned DefaultNullability : 2;
+
+  /// Whether this class has designated initializers recorded.
+  unsigned HasDesignatedInits : 1;
+
+  unsigned SwiftImportAsNonGenericSpecified : 1;
+  unsigned SwiftImportAsNonGeneric : 1;
+
+  unsigned SwiftObjCMembersSpecified : 1;
+  unsigned SwiftObjCMembers : 1;
+
+public:
+  ObjCContextInfo()
+      : CommonTypeInfo(), HasDefaultNullability(0), DefaultNullability(0),
+        HasDesignatedInits(0), SwiftImportAsNonGenericSpecified(false),
+        SwiftImportAsNonGeneric(false), SwiftObjCMembersSpecified(false),
+        SwiftObjCMembers(false) {}
+
+  /// Determine the default nullability for properties and methods of this
+  /// class.
+  ///
+  /// eturns the default nullability, if implied, or None if there is no
+  llvm::Optional<NullabilityKind> getDefaultNullability() const {
+    return HasDefaultNullability
+               ? llvm::Optional<NullabilityKind>(
+                     static_cast<NullabilityKind>(DefaultNullability))
+               : llvm::None;
+  }
+
+  /// Set the default nullability for properties and methods of this class.
+  void setDefaultNullability(NullabilityKind Kind) {
+    HasDefaultNullability = true;
+    DefaultNullability = static_cast<unsigned>(Kind);
+  }
+
+  bool hasDesignatedInits() const { return HasDesignatedInits; }
+  void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
+
+  llvm::Optional<bool> getSwiftImportAsNonGeneric() const {
+    return SwiftImportAsNonGenericSpecified
+               ? llvm::Optional<bool>(SwiftImportAsNonGeneric)
+               : llvm::None;
+  }
+  void setSwiftImportAsNonGeneric(llvm::Optional<bool> Value) {
+    SwiftImportAsNonGenericSpecified = Value.hasValue();
+    SwiftImportAsNonGeneric = Value.hasValue() ? *Value : false;
+  }
+
+  llvm::Optional<bool> getSwiftObjCMembers() const {
+    return SwiftObjCMembersSpecified ? llvm::Optional<bool>(SwiftObjCMembers)
+                                     : llvm::None;
+  }
+  void setSwiftObjCMembers(llvm::Optional<bool> Value) {
+    SwiftObjCMembersSpecified = Value.hasValue();
+    SwiftObjCMembers = Value.hasValue() ? *Value : false;
+  }
+
+  /// Strip off any information within the class information structure that is
+  /// module-local, such as 'audited' flags.
+  void stripModuleLocalInfo() {
+    HasDefaultNullability = false;
+    DefaultNullability = 0;
+  }
+
+  friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &);
+
+  ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) {
+    // Merge inherited info.
+    static_cast<CommonTypeInfo &>(*this) |= RHS;
+
+    // Merge nullability.
+    if (!getDefaultNullability())
+      if (auto Nullability = RHS.getDefaultNullability())
+        setDefaultNullability(*Nullability);
+
+    if (!SwiftImportAsNonGenericSpecified)
+      setSwiftImportAsNonGeneric(RHS.getSwiftImportAsNonGeneric());
+
+    if (!SwiftObjCMembersSpecified)
+      setSwiftObjCMembers(RHS.getSwiftObjCMembers());
+
+    HasDesignatedInits |= RHS.HasDesignatedInits;
+
+    return *this;
+  }
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
+  return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
+         LHS.getDefaultNullability() == RHS.getDefaultNullability() &&
+         LHS.HasDesignatedInits == RHS.HasDesignatedInits &&
+         LHS.getSwiftImportAsNonGeneric() == RHS.getSwiftImportAsNonGeneric() &&
+         LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers();
+}
+
+inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// API notes for a variable/property.
+class VariableInfo : public CommonEntityInfo {
+  /// Whether this property has been audited for nullability.
+  unsigned NullabilityAudited : 1;
+
+  /// The kind of nullability for this property. Only valid if the nullability
+  /// has been audited.
+  unsigned Nullable : 2;
+
+  /// The C type of the variable, as a string.
+  std::string Type;
+
+public:
+  VariableInfo() : CommonEntityInfo(), NullabilityAudited(false), Nullable(0) {}
+
+  llvm::Optional<NullabilityKind> getNullability() const {
+    return NullabilityAudited ? llvm::Optional<NullabilityKind>(
+                                    static_cast<NullabilityKind>(Nullable))
+                              : llvm::None;
+  }
+
+  void setNullabilityAudited(NullabilityKind kind) {
+    NullabilityAudited = true;
+    Nullable = static_cast<unsigned>(kind);
+  }
+
+  const std::string &getType() const { return Type; }
+  void setType(const std::string &type) { Type = type; }
+
+  friend bool operator==(const VariableInfo &, const VariableInfo &);
+
+  VariableInfo &operator|=(const VariableInfo &RHS) {
+    static_cast<CommonEntityInfo &>(*this) |= RHS;
+
+    if (!NullabilityAudited && RHS.NullabilityAudited)
+      setNullabilityAudited(*RHS.getNullability());
+    if (Type.empty())
+      Type = RHS.Type;
+
+    return *this;
+  }
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const VariableInfo &LHS, const VariableInfo &RHS) {
+  return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
+         LHS.NullabilityAudited == RHS.NullabilityAudited &&
+         LHS.Nullable == RHS.Nullable && LHS.Type == RHS.Type;
+}
+
+inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes API notes data for an Objective-C property.
+class ObjCPropertyInfo : public VariableInfo {
+  unsigned SwiftImportAsAccessorsSpecified : 1;
+  unsigned SwiftImportAsAccessors : 1;
+
+public:
+  ObjCPropertyInfo()
+      : VariableInfo(), SwiftImportAsAccessorsSpecified(false),
+        SwiftImportAsAccessors(false) {}
+
+  llvm::Optional<bool> getSwiftImportAsAccessors() const {
+    return SwiftImportAsAccessorsSpecified
+               ? llvm::Optional<bool>(SwiftImportAsAccessors)
+               : llvm::None;
+  }
+  void setSwiftImportAsAccessors(llvm::Optional<bool> Value) {
+    SwiftImportAsAccessorsSpecified = Value.hasValue();
+    SwiftImportAsAccessors = Value.hasValue() ? *Value : false;
+  }
+
+  friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);
+
+  /// Merge class-wide information into the given property.
+  ObjCPropertyInfo &operator|=(const ObjCContextInfo &RHS) {
+    static_cast<CommonEntityInfo &>(*this) |= RHS;
+
+    // Merge nullability.
+    if (!getNullability())
+      if (auto Nullable = RHS.getDefaultNullability())
+        setNullabilityAudited(*Nullable);
+
+    return *this;
+  }
+
+  ObjCPropertyInfo &operator|=(const ObjCPropertyInfo &RHS) {
+    static_cast<VariableInfo &>(*this) |= RHS;
+
+    if (!SwiftImportAsAccessorsSpecified)
+      setSwiftImportAsAccessors(RHS.getSwiftImportAsAccessors());
+
+    return *this;
+  }
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const ObjCPropertyInfo &LHS,
+                       const ObjCPropertyInfo &RHS) {
+  return static_cast<const VariableInfo &>(LHS) == RHS &&
+         LHS.getSwiftImportAsAccessors() == RHS.getSwiftImportAsAccessors();
+}
+
+inline bool operator!=(const ObjCPropertyInfo &LHS,
+                       const ObjCPropertyInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes a function or method parameter.
+class ParamInfo : public VariableInfo {
+  /// Whether noescape was specified.
+  unsigned NoEscapeSpecified : 1;
+
+  /// Whether the this parameter has the 'noescape' attribute.
+  unsigned NoEscape : 1;
+
+  /// A biased RetainCountConventionKind, where 0 means "unspecified".
+  ///
+  /// Only relevant for out-parameters.
+  unsigned RawRetainCountConvention : 3;
+
+public:
+  ParamInfo()
+      : VariableInfo(), NoEscapeSpecified(false), NoEscape(false),
+        RawRetainCountConvention() {}
+
+  llvm::Optional<bool> isNoEscape() const {
+    if (!NoEscapeSpecified)
+      return llvm::None;
+    return NoEscape;
+  }
+  void setNoEscape(llvm::Optional<bool> Value) {
+    NoEscapeSpecified = Value.hasValue();
+    NoEscape = Value.hasValue() ? *Value : false;
+  }
+
+  llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
+    if (!RawRetainCountConvention)
+      return llvm::None;
+    return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
+  }
+  void
+  setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
+    RawRetainCountConvention =
+        Value.hasValue() ? static_cast<unsigned>(Value.getValue()) + 1 : 0;
+    assert(getRetainCountConvention() == Value && "bitfield too small");
+  }
+
+  ParamInfo &operator|=(const ParamInfo &RHS) {
+    static_cast<VariableInfo &>(*this) |= RHS;
+
+    if (!NoEscapeSpecified && RHS.NoEscapeSpecified) {
+      NoEscapeSpecified = true;
+      NoEscape = RHS.NoEscape;
+    }
+
+    if (!RawRetainCountConvention)
+      RawRetainCountConvention = RHS.RawRetainCountConvention;
+
+    return *this;
+  }
+
+  friend bool operator==(const ParamInfo &, const ParamInfo &);
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
+  return static_cast<const VariableInfo &>(LHS) == RHS &&
+         LHS.NoEscapeSpecified == RHS.NoEscapeSpecified &&
+         LHS.NoEscape == RHS.NoEscape &&
+         LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
+}
+
+inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// API notes for a function or method.
+class FunctionInfo : public CommonEntityInfo {
+private:
+  static constexpr const unsigned NullabilityKindMask = 0x3;
+  static constexpr const unsigned NullabilityKindSize = 2;
+
+  static constexpr const unsigned ReturnInfoIndex = 0;
+
+public:
+  // If yes, we consider all types to be non-nullable unless otherwise noted.
+  // If this flag is not set, the pointer types are considered to have
+  // unknown nullability.
+
+  /// Whether the signature has been audited with respect to nullability.
+  unsigned NullabilityAudited : 1;
+
+  /// Number of types whose nullability is encoded with the NullabilityPayload.
+  unsigned NumAdjustedNullable : 8;
+
+  /// A biased RetainCountConventionKind, where 0 means "unspecified".
+  unsigned RawRetainCountConvention : 3;
+
+  // NullabilityKindSize bits are used to encode the nullability. The info
+  // about the return type is stored at position 0, followed by the nullability
+  // of the parameters.
+
+  /// Stores the nullability of the return type and the parameters.
+  uint64_t NullabilityPayload = 0;
+
+  /// The result type of this function, as a C type.
+  std::string ResultType;
+
+  /// The function parameters.
+  std::vector<ParamInfo> Params;
+
+  FunctionInfo()
+      : CommonEntityInfo(), NullabilityAudited(false), NumAdjustedNullable(0),
+        RawRetainCountConvention() {}
+
+  static unsigned getMaxNullabilityIndex() {
+    return ((sizeof(NullabilityPayload) * CHAR_BIT) / NullabilityKindSize);
+  }
+
+  void addTypeInfo(unsigned index, NullabilityKind kind) {
+    assert(index <= getMaxNullabilityIndex());
+    assert(static_cast<unsigned>(kind) < NullabilityKindMask);
+
+    NullabilityAudited = true;
+    if (NumAdjustedNullable < index + 1)
+      NumAdjustedNullable = index + 1;
+
+    // Mask the bits.
+    NullabilityPayload &=
+        ~(NullabilityKindMask << (index * NullabilityKindSize));
+
+    // Set the value.
+    unsigned kindValue = (static_cast<unsigned>(kind))
+                         << (index * NullabilityKindSize);
+    NullabilityPayload |= kindValue;
+  }
+
+  /// Adds the return type info.
+  void addReturnTypeInfo(NullabilityKind kind) {
+    addTypeInfo(ReturnInfoIndex, kind);
+  }
+
+  /// Adds the parameter type info.
+  void addParamTypeInfo(unsigned index, NullabilityKind kind) {
+    addTypeInfo(index + 1, kind);
+  }
+
+  NullabilityKind getParamTypeInfo(unsigned index) const {
+    return getTypeInfo(index + 1);
+  }
+
+  NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
+
+  llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
+    if (!RawRetainCountConvention)
+      return llvm::None;
+    return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
+  }
+  void
+  setRetainCountConvention(llvm::Optional<RetainCountConventionKind> Value) {
+    RawRetainCountConvention =
+        Value.hasValue() ? static_cast<unsigned>(Value.getValue()) + 1 : 0;
+    assert(getRetainCountConvention() == Value && "bitfield too small");
+  }
+
+  friend bool operator==(const FunctionInfo &, const FunctionInfo &);
+
+private:
+  NullabilityKind getTypeInfo(unsigned index) const {
+    assert(NullabilityAudited &&
+           "Checking the type adjustment on non-audited method.");
+
+    // If we don't have info about this parameter, return the default.
+    if (index > NumAdjustedNullable)
+      return NullabilityKind::NonNull;
+    auto nullability = NullabilityPayload >> (index * NullabilityKindSize);
+    return static_cast<NullabilityKind>(nullability & NullabilityKindMask);
+  }
+
+public:
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
+  return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
+         LHS.NullabilityAudited == RHS.NullabilityAudited &&
+         LHS.NumAdjustedNullable == RHS.NumAdjustedNullable &&
+         LHS.NullabilityPayload == RHS.NullabilityPayload &&
+         LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params &&
+         LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
+}
+
+inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes API notes data for an Objective-C method.
+class ObjCMethodInfo : public FunctionInfo {
+public:
+  /// Whether this is a designated initializer of its class.
+  unsigned DesignatedInit : 1;
+
+  /// Whether this is a required initializer.
+  unsigned RequiredInit : 1;
+
+  ObjCMethodInfo()
+      : FunctionInfo(), DesignatedInit(false), RequiredInit(false) {}
+
+  friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);
+
+  ObjCMethodInfo &operator|=(const ObjCContextInfo &RHS) {
+    // Merge Nullability.
+    if (!NullabilityAudited) {
+      if (auto Nullable = RHS.getDefaultNullability()) {
+        NullabilityAudited = true;
+        addTypeInfo(0, *Nullable);
+      }
+    }
+    return *this;
+  }
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
+  return static_cast<const FunctionInfo &>(LHS) == RHS &&
+         LHS.DesignatedInit == RHS.DesignatedInit &&
+         LHS.RequiredInit == RHS.RequiredInit;
+}
+
+inline bool operator!=(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes API notes data for a global variable.
+class GlobalVariableInfo : public VariableInfo {
+public:
+  GlobalVariableInfo() : VariableInfo() {}
+};
+
+/// Describes API notes data for a global function.
+class GlobalFunctionInfo : public FunctionInfo {
+public:
+  GlobalFunctionInfo() : FunctionInfo() {}
+};
+
+/// Describes API notes data for an enumerator.
+class EnumConstantInfo : public CommonEntityInfo {
+public:
+  EnumConstantInfo() : CommonEntityInfo() {}
+};
+
+/// Describes API notes data for a tag.
+class TagInfo : public CommonTypeInfo {
+  unsigned HasFlagEnum : 1;
+  unsigned IsFlagEnum : 1;
+
+public:
+  llvm::Optional<EnumExtensibilityKind> EnumExtensibility;
+
+  TagInfo() : CommonTypeInfo(), HasFlagEnum(0), IsFlagEnum(0) {}
+
+  llvm::Optional<bool> isFlagEnum() const {
+    if (HasFlagEnum)
+      return IsFlagEnum;
+    return llvm::None;
+  }
+  void setFlagEnum(llvm::Optional<bool> Value) {
+    HasFlagEnum = Value.hasValue();
+    IsFlagEnum = Value.hasValue() ? *Value : false;
+  }
+
+  TagInfo &operator|=(const TagInfo &RHS) {
+    static_cast<CommonTypeInfo &>(*this) |= RHS;
+
+    if (!HasFlagEnum && HasFlagEnum)
+      setFlagEnum(RHS.isFlagEnum());
+
+    if (!EnumExtensibility.hasValue())
+      EnumExtensibility = RHS.EnumExtensibility;
+
+    return *this;
+  }
+
+  friend bool operator==(const TagInfo &, const TagInfo &);
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
+  return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
+         LHS.isFlagEnum() == RHS.isFlagEnum() &&
+         LHS.EnumExtensibility == RHS.EnumExtensibility;
+}
+
+inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
+  return !(LHS == RHS);
+}
+
+/// Describes API notes data for a typedef.
+class TypedefInfo : public CommonTypeInfo {
+public:
+  llvm::Optional<SwiftNewTypeKind> SwiftWrapper;
+
+  TypedefInfo() : CommonTypeInfo() {}
+
+  TypedefInfo &operator|=(const TypedefInfo &RHS) {
+    static_cast<CommonTypeInfo &>(*this) |= RHS;
+    if (!SwiftWrapper.hasValue())
+      SwiftWrapper = RHS.SwiftWrapper;
+    return *this;
+  }
+
+  friend bool operator==(const TypedefInfo &, const TypedefInfo &);
+
+  LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
+};
+
+inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) {
+  return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
+         LHS.SwiftWrapper == RHS.SwiftWrapper;
+}
+
+inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) {
+  return !(LHS == RHS);
+}
 } // namespace api_notes
 } // namespace clang
 

diff  --git a/clang/lib/APINotes/APINotesTypes.cpp b/clang/lib/APINotes/APINotesTypes.cpp
new file mode 100644
index 000000000000..f443d90effb3
--- /dev/null
+++ b/clang/lib/APINotes/APINotesTypes.cpp
@@ -0,0 +1,107 @@
+//===-- APINotesTypes.cpp - API Notes Data Types ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/APINotes/Types.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace api_notes {
+void CommonEntityInfo::dump(llvm::raw_ostream &OS) {
+  if (Unavailable)
+    OS << "[Unavailable] (" << UnavailableMsg << ")" << ' ';
+  if (UnavailableInSwift)
+    OS << "[UnavailableInSwift] ";
+  if (SwiftPrivateSpecified)
+    OS << (SwiftPrivate ? "[SwiftPrivate] " : "");
+  if (!SwiftName.empty())
+    OS << "Swift Name: " << SwiftName << ' ';
+  OS << '\n';
+}
+
+void CommonTypeInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<CommonEntityInfo &>(*this).dump(OS);
+  if (SwiftBridge)
+    OS << "Swift Briged Type: " << *SwiftBridge << ' ';
+  if (NSErrorDomain)
+    OS << "NSError Domain: " << *NSErrorDomain << ' ';
+  OS << '\n';
+}
+
+void ObjCContextInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<CommonTypeInfo &>(*this).dump(OS);
+  if (HasDefaultNullability)
+    OS << "DefaultNullability: " << DefaultNullability << ' ';
+  if (HasDesignatedInits)
+    OS << "[HasDesignatedInits] ";
+  if (SwiftImportAsNonGenericSpecified)
+    OS << (SwiftImportAsNonGeneric ? "[SwiftImportAsNonGeneric] " : "");
+  if (SwiftObjCMembersSpecified)
+    OS << (SwiftObjCMembers ? "[SwiftObjCMembers] " : "");
+  OS << '\n';
+}
+
+void VariableInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<CommonEntityInfo &>(*this).dump(OS);
+  if (NullabilityAudited)
+    OS << "Audited Nullability: " << Nullable << ' ';
+  if (!Type.empty())
+    OS << "C Type: " << Type << ' ';
+  OS << '\n';
+}
+
+void ObjCPropertyInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<VariableInfo &>(*this).dump(OS);
+  if (SwiftImportAsAccessorsSpecified)
+    OS << (SwiftImportAsAccessors ? "[SwiftImportAsAccessors] " : "");
+  OS << '\n';
+}
+
+void ParamInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<VariableInfo &>(*this).dump(OS);
+  if (NoEscapeSpecified)
+    OS << (NoEscape ? "[NoEscape] " : "");
+  OS << "RawRetainCountConvention: " << RawRetainCountConvention << ' ';
+  OS << '\n';
+}
+
+void FunctionInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<CommonEntityInfo &>(*this).dump(OS);
+  OS << (NullabilityAudited ? "[NullabilityAudited] " : "")
+     << "RawRetainCountConvention: " << RawRetainCountConvention << ' ';
+  if (!ResultType.empty())
+    OS << "Result Type: " << ResultType << ' ';
+  if (!Params.empty())
+    OS << '\n';
+  for (auto &PI : Params)
+    PI.dump(OS);
+}
+
+void ObjCMethodInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<FunctionInfo &>(*this).dump(OS);
+  OS << (DesignatedInit ? "[DesignatedInit] " : "")
+     << (RequiredInit ? "[RequiredInit] " : "") << '\n';
+}
+
+void TagInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<CommonTypeInfo &>(*this).dump(OS);
+  if (HasFlagEnum)
+    OS << (IsFlagEnum ? "[FlagEnum] " : "");
+  if (EnumExtensibility)
+    OS << "Enum Extensibility: " << static_cast<long>(*EnumExtensibility)
+       << ' ';
+  OS << '\n';
+}
+
+void TypedefInfo::dump(llvm::raw_ostream &OS) {
+  static_cast<CommonTypeInfo &>(*this).dump(OS);
+  if (SwiftWrapper)
+    OS << "Swift Type: " << static_cast<long>(*SwiftWrapper) << ' ';
+  OS << '\n';
+}
+} // namespace api_notes
+} // namespace clang

diff  --git a/clang/lib/APINotes/CMakeLists.txt b/clang/lib/APINotes/CMakeLists.txt
index 3ce511a0de22..3fd0e976ab78 100644
--- a/clang/lib/APINotes/CMakeLists.txt
+++ b/clang/lib/APINotes/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(LLVM_LINK_COMPONENTS
   Support)
 add_clang_library(clangAPINotes
+  APINotesTypes.cpp
   APINotesYAMLCompiler.cpp
   LINK_LIBS
     clangBasic)


        


More information about the cfe-commits mailing list