diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h --- 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 +#include + namespace clang { namespace api_notes { enum class RetainCountConventionKind { @@ -34,6 +40,694 @@ 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 isSwiftPrivate() const { + return SwiftPrivateSpecified ? llvm::Optional(SwiftPrivate) + : llvm::None; + } + + void setSwiftPrivate(llvm::Optional 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 SwiftBridge; + + /// The NS error domain for this type. + llvm::Optional NSErrorDomain; + +public: + CommonTypeInfo() : CommonEntityInfo() {} + + const llvm::Optional &getSwiftBridge() const { + return SwiftBridge; + } + + void setSwiftBridge(const llvm::Optional &SwiftType) { + SwiftBridge = SwiftType; + } + + void setSwiftBridge(const llvm::Optional &SwiftType) { + SwiftBridge = SwiftType + ? llvm::Optional(std::string(*SwiftType)) + : llvm::None; + } + + const llvm::Optional &getNSErrorDomain() const { + return NSErrorDomain; + } + + void setNSErrorDomain(const llvm::Optional &Domain) { + NSErrorDomain = Domain; + } + + void setNSErrorDomain(const llvm::Optional &Domain) { + NSErrorDomain = + Domain ? llvm::Optional(std::string(*Domain)) : llvm::None; + } + + friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &); + + CommonTypeInfo &operator|=(const CommonTypeInfo &RHS) { + // Merge inherited info. + static_cast(*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(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 getDefaultNullability() const { + return HasDefaultNullability + ? llvm::Optional( + static_cast(DefaultNullability)) + : llvm::None; + } + + /// Set the default nullability for properties and methods of this class. + void setDefaultNullability(NullabilityKind Kind) { + HasDefaultNullability = true; + DefaultNullability = static_cast(Kind); + } + + bool hasDesignatedInits() const { return HasDesignatedInits; } + void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; } + + llvm::Optional getSwiftImportAsNonGeneric() const { + return SwiftImportAsNonGenericSpecified + ? llvm::Optional(SwiftImportAsNonGeneric) + : llvm::None; + } + void setSwiftImportAsNonGeneric(llvm::Optional Value) { + SwiftImportAsNonGenericSpecified = Value.hasValue(); + SwiftImportAsNonGeneric = Value.hasValue() ? *Value : false; + } + + llvm::Optional getSwiftObjCMembers() const { + return SwiftObjCMembersSpecified ? llvm::Optional(SwiftObjCMembers) + : llvm::None; + } + void setSwiftObjCMembers(llvm::Optional 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(*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(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 getNullability() const { + return NullabilityAudited ? llvm::Optional( + static_cast(Nullable)) + : llvm::None; + } + + void setNullabilityAudited(NullabilityKind kind) { + NullabilityAudited = true; + Nullable = static_cast(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(*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(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 getSwiftImportAsAccessors() const { + return SwiftImportAsAccessorsSpecified + ? llvm::Optional(SwiftImportAsAccessors) + : llvm::None; + } + void setSwiftImportAsAccessors(llvm::Optional 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(*this) |= RHS; + + // Merge nullability. + if (!getNullability()) + if (auto Nullable = RHS.getDefaultNullability()) + setNullabilityAudited(*Nullable); + + return *this; + } + + ObjCPropertyInfo &operator|=(const ObjCPropertyInfo &RHS) { + static_cast(*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(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 isNoEscape() const { + if (!NoEscapeSpecified) + return llvm::None; + return NoEscape; + } + void setNoEscape(llvm::Optional Value) { + NoEscapeSpecified = Value.hasValue(); + NoEscape = Value.hasValue() ? *Value : false; + } + + llvm::Optional getRetainCountConvention() const { + if (!RawRetainCountConvention) + return llvm::None; + return static_cast(RawRetainCountConvention - 1); + } + void + setRetainCountConvention(llvm::Optional Value) { + RawRetainCountConvention = + Value.hasValue() ? static_cast(Value.getValue()) + 1 : 0; + assert(getRetainCountConvention() == Value && "bitfield too small"); + } + + ParamInfo &operator|=(const ParamInfo &RHS) { + static_cast(*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(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 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(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(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 getRetainCountConvention() const { + if (!RawRetainCountConvention) + return llvm::None; + return static_cast(RawRetainCountConvention - 1); + } + void + setRetainCountConvention(llvm::Optional Value) { + RawRetainCountConvention = + Value.hasValue() ? static_cast(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(nullability & NullabilityKindMask); + } + +public: + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); +}; + +inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) { + return static_cast(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(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 EnumExtensibility; + + TagInfo() : CommonTypeInfo(), HasFlagEnum(0), IsFlagEnum(0) {} + + llvm::Optional isFlagEnum() const { + if (HasFlagEnum) + return IsFlagEnum; + return llvm::None; + } + void setFlagEnum(llvm::Optional Value) { + HasFlagEnum = Value.hasValue(); + IsFlagEnum = Value.hasValue() ? *Value : false; + } + + TagInfo &operator|=(const TagInfo &RHS) { + static_cast(*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(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 SwiftWrapper; + + TypedefInfo() : CommonTypeInfo() {} + + TypedefInfo &operator|=(const TypedefInfo &RHS) { + static_cast(*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(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 --- /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(*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(*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(*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(*this).dump(OS); + if (SwiftImportAsAccessorsSpecified) + OS << (SwiftImportAsAccessors ? "[SwiftImportAsAccessors] " : ""); + OS << '\n'; +} + +void ParamInfo::dump(llvm::raw_ostream &OS) { + static_cast(*this).dump(OS); + if (NoEscapeSpecified) + OS << (NoEscape ? "[NoEscape] " : ""); + OS << "RawRetainCountConvention: " << RawRetainCountConvention << ' '; + OS << '\n'; +} + +void FunctionInfo::dump(llvm::raw_ostream &OS) { + static_cast(*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(*this).dump(OS); + OS << (DesignatedInit ? "[DesignatedInit] " : "") + << (RequiredInit ? "[RequiredInit] " : "") << '\n'; +} + +void TagInfo::dump(llvm::raw_ostream &OS) { + static_cast(*this).dump(OS); + if (HasFlagEnum) + OS << (IsFlagEnum ? "[FlagEnum] " : ""); + if (EnumExtensibility) + OS << "Enum Extensibility: " << static_cast(*EnumExtensibility) + << ' '; + OS << '\n'; +} + +void TypedefInfo::dump(llvm::raw_ostream &OS) { + static_cast(*this).dump(OS); + if (SwiftWrapper) + OS << "Swift Type: " << static_cast(*SwiftWrapper) << ' '; + OS << '\n'; +} +} // namespace api_notes +} // namespace clang diff --git a/clang/lib/APINotes/CMakeLists.txt b/clang/lib/APINotes/CMakeLists.txt --- 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)