Path: blob/main/contrib/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp
35260 views
//===-- APINotesYAMLCompiler.cpp - API Notes YAML Format Reader -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// The types defined locally are designed to represent the YAML state, which9// adds an additional bit of state: e.g. a tri-state boolean attribute (yes, no,10// not applied) becomes a tri-state boolean + present. As a result, while these11// enumerations appear to be redefining constants from the attributes table12// data, they are distinct.13//1415#include "clang/APINotes/APINotesYAMLCompiler.h"16#include "clang/APINotes/APINotesWriter.h"17#include "clang/APINotes/Types.h"18#include "clang/Basic/LLVM.h"19#include "clang/Basic/Specifiers.h"20#include "llvm/ADT/StringSet.h"21#include "llvm/Support/SourceMgr.h"22#include "llvm/Support/VersionTuple.h"23#include "llvm/Support/YAMLTraits.h"24#include <optional>25#include <vector>2627using namespace clang;28using namespace api_notes;2930namespace {31enum class APIAvailability {32Available = 0,33None,34NonSwift,35};36} // namespace3738namespace llvm {39namespace yaml {40template <> struct ScalarEnumerationTraits<APIAvailability> {41static void enumeration(IO &IO, APIAvailability &AA) {42IO.enumCase(AA, "none", APIAvailability::None);43IO.enumCase(AA, "nonswift", APIAvailability::NonSwift);44IO.enumCase(AA, "available", APIAvailability::Available);45}46};47} // namespace yaml48} // namespace llvm4950namespace {51enum class MethodKind {52Class,53Instance,54};55} // namespace5657namespace llvm {58namespace yaml {59template <> struct ScalarEnumerationTraits<MethodKind> {60static void enumeration(IO &IO, MethodKind &MK) {61IO.enumCase(MK, "Class", MethodKind::Class);62IO.enumCase(MK, "Instance", MethodKind::Instance);63}64};65} // namespace yaml66} // namespace llvm6768namespace {69struct Param {70unsigned Position;71std::optional<bool> NoEscape = false;72std::optional<NullabilityKind> Nullability;73std::optional<RetainCountConventionKind> RetainCountConvention;74StringRef Type;75};7677typedef std::vector<Param> ParamsSeq;78} // namespace7980LLVM_YAML_IS_SEQUENCE_VECTOR(Param)81LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind)8283namespace llvm {84namespace yaml {85template <> struct ScalarEnumerationTraits<NullabilityKind> {86static void enumeration(IO &IO, NullabilityKind &NK) {87IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull);88IO.enumCase(NK, "Optional", NullabilityKind::Nullable);89IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified);90IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult);91// TODO: Mapping this to it's own value would allow for better cross92// checking. Also the default should be Unknown.93IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified);9495// Aliases for compatibility with existing APINotes.96IO.enumCase(NK, "N", NullabilityKind::NonNull);97IO.enumCase(NK, "O", NullabilityKind::Nullable);98IO.enumCase(NK, "U", NullabilityKind::Unspecified);99IO.enumCase(NK, "S", NullabilityKind::Unspecified);100}101};102103template <> struct ScalarEnumerationTraits<RetainCountConventionKind> {104static void enumeration(IO &IO, RetainCountConventionKind &RCCK) {105IO.enumCase(RCCK, "none", RetainCountConventionKind::None);106IO.enumCase(RCCK, "CFReturnsRetained",107RetainCountConventionKind::CFReturnsRetained);108IO.enumCase(RCCK, "CFReturnsNotRetained",109RetainCountConventionKind::CFReturnsNotRetained);110IO.enumCase(RCCK, "NSReturnsRetained",111RetainCountConventionKind::NSReturnsRetained);112IO.enumCase(RCCK, "NSReturnsNotRetained",113RetainCountConventionKind::NSReturnsNotRetained);114}115};116117template <> struct MappingTraits<Param> {118static void mapping(IO &IO, Param &P) {119IO.mapRequired("Position", P.Position);120IO.mapOptional("Nullability", P.Nullability, std::nullopt);121IO.mapOptional("RetainCountConvention", P.RetainCountConvention);122IO.mapOptional("NoEscape", P.NoEscape);123IO.mapOptional("Type", P.Type, StringRef(""));124}125};126} // namespace yaml127} // namespace llvm128129namespace {130typedef std::vector<NullabilityKind> NullabilitySeq;131132struct AvailabilityItem {133APIAvailability Mode = APIAvailability::Available;134StringRef Msg;135};136137/// Old attribute deprecated in favor of SwiftName.138enum class FactoryAsInitKind {139/// Infer based on name and type (the default).140Infer,141/// Treat as a class method.142AsClassMethod,143/// Treat as an initializer.144AsInitializer,145};146147struct Method {148StringRef Selector;149MethodKind Kind;150ParamsSeq Params;151NullabilitySeq Nullability;152std::optional<NullabilityKind> NullabilityOfRet;153std::optional<RetainCountConventionKind> RetainCountConvention;154AvailabilityItem Availability;155std::optional<bool> SwiftPrivate;156StringRef SwiftName;157FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer;158bool DesignatedInit = false;159bool Required = false;160StringRef ResultType;161};162163typedef std::vector<Method> MethodsSeq;164} // namespace165166LLVM_YAML_IS_SEQUENCE_VECTOR(Method)167168namespace llvm {169namespace yaml {170template <> struct ScalarEnumerationTraits<FactoryAsInitKind> {171static void enumeration(IO &IO, FactoryAsInitKind &FIK) {172IO.enumCase(FIK, "A", FactoryAsInitKind::Infer);173IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod);174IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer);175}176};177178template <> struct MappingTraits<Method> {179static void mapping(IO &IO, Method &M) {180IO.mapRequired("Selector", M.Selector);181IO.mapRequired("MethodKind", M.Kind);182IO.mapOptional("Parameters", M.Params);183IO.mapOptional("Nullability", M.Nullability);184IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, std::nullopt);185IO.mapOptional("RetainCountConvention", M.RetainCountConvention);186IO.mapOptional("Availability", M.Availability.Mode,187APIAvailability::Available);188IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));189IO.mapOptional("SwiftPrivate", M.SwiftPrivate);190IO.mapOptional("SwiftName", M.SwiftName, StringRef(""));191IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer);192IO.mapOptional("DesignatedInit", M.DesignatedInit, false);193IO.mapOptional("Required", M.Required, false);194IO.mapOptional("ResultType", M.ResultType, StringRef(""));195}196};197} // namespace yaml198} // namespace llvm199200namespace {201struct Property {202StringRef Name;203std::optional<MethodKind> Kind;204std::optional<NullabilityKind> Nullability;205AvailabilityItem Availability;206std::optional<bool> SwiftPrivate;207StringRef SwiftName;208std::optional<bool> SwiftImportAsAccessors;209StringRef Type;210};211212typedef std::vector<Property> PropertiesSeq;213} // namespace214215LLVM_YAML_IS_SEQUENCE_VECTOR(Property)216217namespace llvm {218namespace yaml {219template <> struct MappingTraits<Property> {220static void mapping(IO &IO, Property &P) {221IO.mapRequired("Name", P.Name);222IO.mapOptional("PropertyKind", P.Kind);223IO.mapOptional("Nullability", P.Nullability, std::nullopt);224IO.mapOptional("Availability", P.Availability.Mode,225APIAvailability::Available);226IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef(""));227IO.mapOptional("SwiftPrivate", P.SwiftPrivate);228IO.mapOptional("SwiftName", P.SwiftName, StringRef(""));229IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors);230IO.mapOptional("Type", P.Type, StringRef(""));231}232};233} // namespace yaml234} // namespace llvm235236namespace {237struct Class {238StringRef Name;239bool AuditedForNullability = false;240AvailabilityItem Availability;241std::optional<bool> SwiftPrivate;242StringRef SwiftName;243std::optional<StringRef> SwiftBridge;244std::optional<StringRef> NSErrorDomain;245std::optional<bool> SwiftImportAsNonGeneric;246std::optional<bool> SwiftObjCMembers;247MethodsSeq Methods;248PropertiesSeq Properties;249};250251typedef std::vector<Class> ClassesSeq;252} // namespace253254LLVM_YAML_IS_SEQUENCE_VECTOR(Class)255256namespace llvm {257namespace yaml {258template <> struct MappingTraits<Class> {259static void mapping(IO &IO, Class &C) {260IO.mapRequired("Name", C.Name);261IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false);262IO.mapOptional("Availability", C.Availability.Mode,263APIAvailability::Available);264IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef(""));265IO.mapOptional("SwiftPrivate", C.SwiftPrivate);266IO.mapOptional("SwiftName", C.SwiftName, StringRef(""));267IO.mapOptional("SwiftBridge", C.SwiftBridge);268IO.mapOptional("NSErrorDomain", C.NSErrorDomain);269IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric);270IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers);271IO.mapOptional("Methods", C.Methods);272IO.mapOptional("Properties", C.Properties);273}274};275} // namespace yaml276} // namespace llvm277278namespace {279struct Function {280StringRef Name;281ParamsSeq Params;282NullabilitySeq Nullability;283std::optional<NullabilityKind> NullabilityOfRet;284std::optional<api_notes::RetainCountConventionKind> RetainCountConvention;285AvailabilityItem Availability;286std::optional<bool> SwiftPrivate;287StringRef SwiftName;288StringRef Type;289StringRef ResultType;290};291292typedef std::vector<Function> FunctionsSeq;293} // namespace294295LLVM_YAML_IS_SEQUENCE_VECTOR(Function)296297namespace llvm {298namespace yaml {299template <> struct MappingTraits<Function> {300static void mapping(IO &IO, Function &F) {301IO.mapRequired("Name", F.Name);302IO.mapOptional("Parameters", F.Params);303IO.mapOptional("Nullability", F.Nullability);304IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt);305IO.mapOptional("RetainCountConvention", F.RetainCountConvention);306IO.mapOptional("Availability", F.Availability.Mode,307APIAvailability::Available);308IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));309IO.mapOptional("SwiftPrivate", F.SwiftPrivate);310IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));311IO.mapOptional("ResultType", F.ResultType, StringRef(""));312}313};314} // namespace yaml315} // namespace llvm316317namespace {318struct GlobalVariable {319StringRef Name;320std::optional<NullabilityKind> Nullability;321AvailabilityItem Availability;322std::optional<bool> SwiftPrivate;323StringRef SwiftName;324StringRef Type;325};326327typedef std::vector<GlobalVariable> GlobalVariablesSeq;328} // namespace329330LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable)331332namespace llvm {333namespace yaml {334template <> struct MappingTraits<GlobalVariable> {335static void mapping(IO &IO, GlobalVariable &GV) {336IO.mapRequired("Name", GV.Name);337IO.mapOptional("Nullability", GV.Nullability, std::nullopt);338IO.mapOptional("Availability", GV.Availability.Mode,339APIAvailability::Available);340IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef(""));341IO.mapOptional("SwiftPrivate", GV.SwiftPrivate);342IO.mapOptional("SwiftName", GV.SwiftName, StringRef(""));343IO.mapOptional("Type", GV.Type, StringRef(""));344}345};346} // namespace yaml347} // namespace llvm348349namespace {350struct EnumConstant {351StringRef Name;352AvailabilityItem Availability;353std::optional<bool> SwiftPrivate;354StringRef SwiftName;355};356357typedef std::vector<EnumConstant> EnumConstantsSeq;358} // namespace359360LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant)361362namespace llvm {363namespace yaml {364template <> struct MappingTraits<EnumConstant> {365static void mapping(IO &IO, EnumConstant &EC) {366IO.mapRequired("Name", EC.Name);367IO.mapOptional("Availability", EC.Availability.Mode,368APIAvailability::Available);369IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef(""));370IO.mapOptional("SwiftPrivate", EC.SwiftPrivate);371IO.mapOptional("SwiftName", EC.SwiftName, StringRef(""));372}373};374} // namespace yaml375} // namespace llvm376377namespace {378/// Syntactic sugar for EnumExtensibility and FlagEnum379enum class EnumConvenienceAliasKind {380/// EnumExtensibility: none, FlagEnum: false381None,382/// EnumExtensibility: open, FlagEnum: false383CFEnum,384/// EnumExtensibility: open, FlagEnum: true385CFOptions,386/// EnumExtensibility: closed, FlagEnum: false387CFClosedEnum388};389} // namespace390391namespace llvm {392namespace yaml {393template <> struct ScalarEnumerationTraits<EnumConvenienceAliasKind> {394static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) {395IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None);396IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum);397IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum);398IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions);399IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions);400IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);401IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);402}403};404} // namespace yaml405} // namespace llvm406407namespace {408struct Tag {409StringRef Name;410AvailabilityItem Availability;411StringRef SwiftName;412std::optional<bool> SwiftPrivate;413std::optional<StringRef> SwiftBridge;414std::optional<StringRef> NSErrorDomain;415std::optional<std::string> SwiftImportAs;416std::optional<std::string> SwiftRetainOp;417std::optional<std::string> SwiftReleaseOp;418std::optional<EnumExtensibilityKind> EnumExtensibility;419std::optional<bool> FlagEnum;420std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;421std::optional<bool> SwiftCopyable;422FunctionsSeq Methods;423};424425typedef std::vector<Tag> TagsSeq;426} // namespace427428LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)429430namespace llvm {431namespace yaml {432template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> {433static void enumeration(IO &IO, EnumExtensibilityKind &EEK) {434IO.enumCase(EEK, "none", EnumExtensibilityKind::None);435IO.enumCase(EEK, "open", EnumExtensibilityKind::Open);436IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed);437}438};439440template <> struct MappingTraits<Tag> {441static void mapping(IO &IO, Tag &T) {442IO.mapRequired("Name", T.Name);443IO.mapOptional("Availability", T.Availability.Mode,444APIAvailability::Available);445IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));446IO.mapOptional("SwiftPrivate", T.SwiftPrivate);447IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));448IO.mapOptional("SwiftBridge", T.SwiftBridge);449IO.mapOptional("NSErrorDomain", T.NSErrorDomain);450IO.mapOptional("SwiftImportAs", T.SwiftImportAs);451IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);452IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);453IO.mapOptional("EnumExtensibility", T.EnumExtensibility);454IO.mapOptional("FlagEnum", T.FlagEnum);455IO.mapOptional("EnumKind", T.EnumConvenienceKind);456IO.mapOptional("SwiftCopyable", T.SwiftCopyable);457IO.mapOptional("Methods", T.Methods);458}459};460} // namespace yaml461} // namespace llvm462463namespace {464struct Typedef {465StringRef Name;466AvailabilityItem Availability;467StringRef SwiftName;468std::optional<bool> SwiftPrivate;469std::optional<StringRef> SwiftBridge;470std::optional<StringRef> NSErrorDomain;471std::optional<SwiftNewTypeKind> SwiftType;472};473474typedef std::vector<Typedef> TypedefsSeq;475} // namespace476477LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)478479namespace llvm {480namespace yaml {481template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> {482static void enumeration(IO &IO, SwiftNewTypeKind &SWK) {483IO.enumCase(SWK, "none", SwiftNewTypeKind::None);484IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct);485IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum);486}487};488489template <> struct MappingTraits<Typedef> {490static void mapping(IO &IO, Typedef &T) {491IO.mapRequired("Name", T.Name);492IO.mapOptional("Availability", T.Availability.Mode,493APIAvailability::Available);494IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));495IO.mapOptional("SwiftPrivate", T.SwiftPrivate);496IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));497IO.mapOptional("SwiftBridge", T.SwiftBridge);498IO.mapOptional("NSErrorDomain", T.NSErrorDomain);499IO.mapOptional("SwiftWrapper", T.SwiftType);500}501};502} // namespace yaml503} // namespace llvm504505namespace {506struct Namespace;507typedef std::vector<Namespace> NamespacesSeq;508509struct TopLevelItems {510ClassesSeq Classes;511ClassesSeq Protocols;512FunctionsSeq Functions;513GlobalVariablesSeq Globals;514EnumConstantsSeq EnumConstants;515TagsSeq Tags;516TypedefsSeq Typedefs;517NamespacesSeq Namespaces;518};519} // namespace520521namespace llvm {522namespace yaml {523static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) {524IO.mapOptional("Classes", TLI.Classes);525IO.mapOptional("Protocols", TLI.Protocols);526IO.mapOptional("Functions", TLI.Functions);527IO.mapOptional("Globals", TLI.Globals);528IO.mapOptional("Enumerators", TLI.EnumConstants);529IO.mapOptional("Tags", TLI.Tags);530IO.mapOptional("Typedefs", TLI.Typedefs);531IO.mapOptional("Namespaces", TLI.Namespaces);532}533} // namespace yaml534} // namespace llvm535536namespace {537struct Namespace {538StringRef Name;539AvailabilityItem Availability;540StringRef SwiftName;541std::optional<bool> SwiftPrivate;542TopLevelItems Items;543};544} // namespace545546LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)547548namespace llvm {549namespace yaml {550template <> struct MappingTraits<Namespace> {551static void mapping(IO &IO, Namespace &T) {552IO.mapRequired("Name", T.Name);553IO.mapOptional("Availability", T.Availability.Mode,554APIAvailability::Available);555IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));556IO.mapOptional("SwiftPrivate", T.SwiftPrivate);557IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));558mapTopLevelItems(IO, T.Items);559}560};561} // namespace yaml562} // namespace llvm563564namespace {565struct Versioned {566VersionTuple Version;567TopLevelItems Items;568};569570typedef std::vector<Versioned> VersionedSeq;571} // namespace572573LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)574575namespace llvm {576namespace yaml {577template <> struct MappingTraits<Versioned> {578static void mapping(IO &IO, Versioned &V) {579IO.mapRequired("Version", V.Version);580mapTopLevelItems(IO, V.Items);581}582};583} // namespace yaml584} // namespace llvm585586namespace {587struct Module {588StringRef Name;589AvailabilityItem Availability;590TopLevelItems TopLevel;591VersionedSeq SwiftVersions;592593std::optional<bool> SwiftInferImportAsMember;594595#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)596LLVM_DUMP_METHOD void dump() /*const*/;597#endif598};599} // namespace600601namespace llvm {602namespace yaml {603template <> struct MappingTraits<Module> {604static void mapping(IO &IO, Module &M) {605IO.mapRequired("Name", M.Name);606IO.mapOptional("Availability", M.Availability.Mode,607APIAvailability::Available);608IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));609IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember);610mapTopLevelItems(IO, M.TopLevel);611IO.mapOptional("SwiftVersions", M.SwiftVersions);612}613};614} // namespace yaml615} // namespace llvm616617#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)618LLVM_DUMP_METHOD void Module::dump() {619llvm::yaml::Output OS(llvm::errs());620OS << *this;621}622#endif623624namespace {625bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag,626void *DiagContext) {627llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext);628IS >> M;629return static_cast<bool>(IS.error());630}631} // namespace632633bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,634llvm::raw_ostream &OS) {635Module M;636if (parseAPINotes(YI, M, nullptr, nullptr))637return true;638639llvm::yaml::Output YOS(OS);640YOS << M;641642return false;643}644645namespace {646using namespace api_notes;647648class YAMLConverter {649const Module &M;650APINotesWriter Writer;651llvm::raw_ostream &OS;652llvm::SourceMgr::DiagHandlerTy DiagHandler;653void *DiagHandlerCtxt;654bool ErrorOccured;655656/// Emit a diagnostic657bool emitError(llvm::Twine Message) {658DiagHandler(659llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),660DiagHandlerCtxt);661ErrorOccured = true;662return true;663}664665public:666YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,667llvm::raw_ostream &OS,668llvm::SourceMgr::DiagHandlerTy DiagHandler,669void *DiagHandlerCtxt)670: M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),671DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),672ErrorOccured(false) {}673674void convertAvailability(const AvailabilityItem &Availability,675CommonEntityInfo &CEI, llvm::StringRef APIName) {676// Populate the unavailability information.677CEI.Unavailable = (Availability.Mode == APIAvailability::None);678CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);679if (CEI.Unavailable || CEI.UnavailableInSwift) {680CEI.UnavailableMsg = std::string(Availability.Msg);681} else {682if (!Availability.Msg.empty())683emitError(llvm::Twine("availability message for available API '") +684APIName + "' will not be used");685}686}687688void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) {689for (const auto &P : Params) {690ParamInfo PI;691if (P.Nullability)692PI.setNullabilityAudited(*P.Nullability);693PI.setNoEscape(P.NoEscape);694PI.setType(std::string(P.Type));695PI.setRetainCountConvention(P.RetainCountConvention);696if (OutInfo.Params.size() <= P.Position)697OutInfo.Params.resize(P.Position + 1);698OutInfo.Params[P.Position] |= PI;699}700}701702void convertNullability(const NullabilitySeq &Nullability,703std::optional<NullabilityKind> ReturnNullability,704FunctionInfo &OutInfo, llvm::StringRef APIName) {705if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {706emitError(llvm::Twine("nullability info for '") + APIName +707"' does not fit");708return;709}710711bool audited = false;712unsigned int idx = 1;713for (const auto &N : Nullability)714OutInfo.addTypeInfo(idx++, N);715audited = Nullability.size() > 0 || ReturnNullability;716if (audited)717OutInfo.addTypeInfo(0, ReturnNullability ? *ReturnNullability718: NullabilityKind::NonNull);719if (!audited)720return;721OutInfo.NullabilityAudited = audited;722OutInfo.NumAdjustedNullable = idx;723}724725/// Convert the common parts of an entity from YAML.726template <typename T>727void convertCommonEntity(const T &Common, CommonEntityInfo &Info,728StringRef APIName) {729convertAvailability(Common.Availability, Info, APIName);730Info.setSwiftPrivate(Common.SwiftPrivate);731Info.SwiftName = std::string(Common.SwiftName);732}733734/// Convert the common parts of a type entity from YAML.735template <typename T>736void convertCommonType(const T &Common, CommonTypeInfo &Info,737StringRef APIName) {738convertCommonEntity(Common, Info, APIName);739if (Common.SwiftBridge)740Info.setSwiftBridge(std::string(*Common.SwiftBridge));741Info.setNSErrorDomain(Common.NSErrorDomain);742}743744// Translate from Method into ObjCMethodInfo and write it out.745void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName,746VersionTuple SwiftVersion) {747ObjCMethodInfo MI;748convertCommonEntity(M, MI, M.Selector);749750// Check if the selector ends with ':' to determine if it takes arguments.751bool takesArguments = M.Selector.ends_with(":");752753// Split the selector into pieces.754llvm::SmallVector<StringRef, 4> Args;755M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);756if (!takesArguments && Args.size() > 1) {757emitError("selector '" + M.Selector + "' is missing a ':' at the end");758return;759}760761// Construct ObjCSelectorRef.762api_notes::ObjCSelectorRef Selector;763Selector.NumArgs = !takesArguments ? 0 : Args.size();764Selector.Identifiers = Args;765766// Translate the initializer info.767MI.DesignatedInit = M.DesignatedInit;768MI.RequiredInit = M.Required;769if (M.FactoryAsInit != FactoryAsInitKind::Infer)770emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");771772MI.ResultType = std::string(M.ResultType);773774// Translate parameter information.775convertParams(M.Params, MI);776777// Translate nullability info.778convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector);779780MI.setRetainCountConvention(M.RetainCountConvention);781782// Write it.783Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI,784SwiftVersion);785}786787void convertContext(std::optional<ContextID> ParentContextID, const Class &C,788ContextKind Kind, VersionTuple SwiftVersion) {789// Write the class.790ContextInfo CI;791convertCommonType(C, CI, C.Name);792793if (C.AuditedForNullability)794CI.setDefaultNullability(NullabilityKind::NonNull);795if (C.SwiftImportAsNonGeneric)796CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric);797if (C.SwiftObjCMembers)798CI.setSwiftObjCMembers(*C.SwiftObjCMembers);799800ContextID CtxID =801Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);802803// Write all methods.804llvm::StringMap<std::pair<bool, bool>> KnownMethods;805for (const auto &method : C.Methods) {806// Check for duplicate method definitions.807bool IsInstanceMethod = method.Kind == MethodKind::Instance;808bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first809: KnownMethods[method.Selector].second;810if (Known) {811emitError(llvm::Twine("duplicate definition of method '") +812(IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " +813method.Selector + "]'");814continue;815}816Known = true;817818convertMethod(method, CtxID, C.Name, SwiftVersion);819}820821// Write all properties.822llvm::StringSet<> KnownInstanceProperties;823llvm::StringSet<> KnownClassProperties;824for (const auto &Property : C.Properties) {825// Check for duplicate property definitions.826if ((!Property.Kind || *Property.Kind == MethodKind::Instance) &&827!KnownInstanceProperties.insert(Property.Name).second) {828emitError(llvm::Twine("duplicate definition of instance property '") +829C.Name + "." + Property.Name + "'");830continue;831}832833if ((!Property.Kind || *Property.Kind == MethodKind::Class) &&834!KnownClassProperties.insert(Property.Name).second) {835emitError(llvm::Twine("duplicate definition of class property '") +836C.Name + "." + Property.Name + "'");837continue;838}839840// Translate from Property into ObjCPropertyInfo.841ObjCPropertyInfo PI;842convertAvailability(Property.Availability, PI, Property.Name);843PI.setSwiftPrivate(Property.SwiftPrivate);844PI.SwiftName = std::string(Property.SwiftName);845if (Property.Nullability)846PI.setNullabilityAudited(*Property.Nullability);847if (Property.SwiftImportAsAccessors)848PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors);849PI.setType(std::string(Property.Type));850851// Add both instance and class properties with this name.852if (Property.Kind) {853Writer.addObjCProperty(CtxID, Property.Name,854*Property.Kind == MethodKind::Instance, PI,855SwiftVersion);856} else {857Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion);858Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion);859}860}861}862863void convertNamespaceContext(std::optional<ContextID> ParentContextID,864const Namespace &TheNamespace,865VersionTuple SwiftVersion) {866// Write the namespace.867ContextInfo CI;868convertCommonEntity(TheNamespace, CI, TheNamespace.Name);869870ContextID CtxID =871Writer.addContext(ParentContextID, TheNamespace.Name,872ContextKind::Namespace, CI, SwiftVersion);873874convertTopLevelItems(Context(CtxID, ContextKind::Namespace),875TheNamespace.Items, SwiftVersion);876}877878void convertFunction(const Function &Function, FunctionInfo &FI) {879convertAvailability(Function.Availability, FI, Function.Name);880FI.setSwiftPrivate(Function.SwiftPrivate);881FI.SwiftName = std::string(Function.SwiftName);882convertParams(Function.Params, FI);883convertNullability(Function.Nullability, Function.NullabilityOfRet, FI,884Function.Name);885FI.ResultType = std::string(Function.ResultType);886FI.setRetainCountConvention(Function.RetainCountConvention);887}888889void convertTagContext(std::optional<Context> ParentContext, const Tag &T,890VersionTuple SwiftVersion) {891TagInfo TI;892std::optional<ContextID> ParentContextID =893ParentContext ? std::optional<ContextID>(ParentContext->id)894: std::nullopt;895convertCommonType(T, TI, T.Name);896897if ((T.SwiftRetainOp || T.SwiftReleaseOp) && !T.SwiftImportAs) {898emitError(llvm::Twine("should declare SwiftImportAs to use "899"SwiftRetainOp and SwiftReleaseOp (for ") +900T.Name + ")");901return;902}903if (T.SwiftReleaseOp.has_value() != T.SwiftRetainOp.has_value()) {904emitError(llvm::Twine("should declare both SwiftReleaseOp and "905"SwiftRetainOp (for ") +906T.Name + ")");907return;908}909910if (T.SwiftImportAs)911TI.SwiftImportAs = T.SwiftImportAs;912if (T.SwiftRetainOp)913TI.SwiftRetainOp = T.SwiftRetainOp;914if (T.SwiftReleaseOp)915TI.SwiftReleaseOp = T.SwiftReleaseOp;916917if (T.SwiftCopyable)918TI.setSwiftCopyable(T.SwiftCopyable);919920if (T.EnumConvenienceKind) {921if (T.EnumExtensibility) {922emitError(923llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") +924T.Name + ")");925return;926}927if (T.FlagEnum) {928emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") +929T.Name + ")");930return;931}932switch (*T.EnumConvenienceKind) {933case EnumConvenienceAliasKind::None:934TI.EnumExtensibility = EnumExtensibilityKind::None;935TI.setFlagEnum(false);936break;937case EnumConvenienceAliasKind::CFEnum:938TI.EnumExtensibility = EnumExtensibilityKind::Open;939TI.setFlagEnum(false);940break;941case EnumConvenienceAliasKind::CFOptions:942TI.EnumExtensibility = EnumExtensibilityKind::Open;943TI.setFlagEnum(true);944break;945case EnumConvenienceAliasKind::CFClosedEnum:946TI.EnumExtensibility = EnumExtensibilityKind::Closed;947TI.setFlagEnum(false);948break;949}950} else {951TI.EnumExtensibility = T.EnumExtensibility;952TI.setFlagEnum(T.FlagEnum);953}954955Writer.addTag(ParentContext, T.Name, TI, SwiftVersion);956957ContextInfo CI;958auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag,959CI, SwiftVersion);960961for (const auto &CXXMethod : T.Methods) {962CXXMethodInfo MI;963convertFunction(CXXMethod, MI);964Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);965}966}967968void convertTopLevelItems(std::optional<Context> Ctx,969const TopLevelItems &TLItems,970VersionTuple SwiftVersion) {971std::optional<ContextID> CtxID =972Ctx ? std::optional(Ctx->id) : std::nullopt;973974// Write all classes.975llvm::StringSet<> KnownClasses;976for (const auto &Class : TLItems.Classes) {977// Check for duplicate class definitions.978if (!KnownClasses.insert(Class.Name).second) {979emitError(llvm::Twine("multiple definitions of class '") + Class.Name +980"'");981continue;982}983984convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion);985}986987// Write all protocols.988llvm::StringSet<> KnownProtocols;989for (const auto &Protocol : TLItems.Protocols) {990// Check for duplicate protocol definitions.991if (!KnownProtocols.insert(Protocol.Name).second) {992emitError(llvm::Twine("multiple definitions of protocol '") +993Protocol.Name + "'");994continue;995}996997convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion);998}9991000// Write all namespaces.1001llvm::StringSet<> KnownNamespaces;1002for (const auto &Namespace : TLItems.Namespaces) {1003// Check for duplicate namespace definitions.1004if (!KnownNamespaces.insert(Namespace.Name).second) {1005emitError(llvm::Twine("multiple definitions of namespace '") +1006Namespace.Name + "'");1007continue;1008}10091010convertNamespaceContext(CtxID, Namespace, SwiftVersion);1011}10121013// Write all global variables.1014llvm::StringSet<> KnownGlobals;1015for (const auto &Global : TLItems.Globals) {1016// Check for duplicate global variables.1017if (!KnownGlobals.insert(Global.Name).second) {1018emitError(llvm::Twine("multiple definitions of global variable '") +1019Global.Name + "'");1020continue;1021}10221023GlobalVariableInfo GVI;1024convertAvailability(Global.Availability, GVI, Global.Name);1025GVI.setSwiftPrivate(Global.SwiftPrivate);1026GVI.SwiftName = std::string(Global.SwiftName);1027if (Global.Nullability)1028GVI.setNullabilityAudited(*Global.Nullability);1029GVI.setType(std::string(Global.Type));1030Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion);1031}10321033// Write all global functions.1034llvm::StringSet<> KnownFunctions;1035for (const auto &Function : TLItems.Functions) {1036// Check for duplicate global functions.1037if (!KnownFunctions.insert(Function.Name).second) {1038emitError(llvm::Twine("multiple definitions of global function '") +1039Function.Name + "'");1040continue;1041}10421043GlobalFunctionInfo GFI;1044convertFunction(Function, GFI);1045Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion);1046}10471048// Write all enumerators.1049llvm::StringSet<> KnownEnumConstants;1050for (const auto &EnumConstant : TLItems.EnumConstants) {1051// Check for duplicate enumerators1052if (!KnownEnumConstants.insert(EnumConstant.Name).second) {1053emitError(llvm::Twine("multiple definitions of enumerator '") +1054EnumConstant.Name + "'");1055continue;1056}10571058EnumConstantInfo ECI;1059convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name);1060ECI.setSwiftPrivate(EnumConstant.SwiftPrivate);1061ECI.SwiftName = std::string(EnumConstant.SwiftName);1062Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion);1063}10641065// Write all tags.1066llvm::StringSet<> KnownTags;1067for (const auto &Tag : TLItems.Tags) {1068// Check for duplicate tag definitions.1069if (!KnownTags.insert(Tag.Name).second) {1070emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name +1071"'");1072continue;1073}10741075convertTagContext(Ctx, Tag, SwiftVersion);1076}10771078// Write all typedefs.1079llvm::StringSet<> KnownTypedefs;1080for (const auto &Typedef : TLItems.Typedefs) {1081// Check for duplicate typedef definitions.1082if (!KnownTypedefs.insert(Typedef.Name).second) {1083emitError(llvm::Twine("multiple definitions of typedef '") +1084Typedef.Name + "'");1085continue;1086}10871088TypedefInfo TInfo;1089convertCommonType(Typedef, TInfo, Typedef.Name);1090TInfo.SwiftWrapper = Typedef.SwiftType;10911092Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion);1093}1094}10951096bool convertModule() {1097// Write the top-level items.1098convertTopLevelItems(/* context */ std::nullopt, M.TopLevel,1099VersionTuple());11001101// Convert the versioned information.1102for (const auto &Versioned : M.SwiftVersions)1103convertTopLevelItems(/* context */ std::nullopt, Versioned.Items,1104Versioned.Version);11051106if (!ErrorOccured)1107Writer.writeToStream(OS);11081109return ErrorOccured;1110}1111};1112} // namespace11131114static bool compile(const Module &M, const FileEntry *SourceFile,1115llvm::raw_ostream &OS,1116llvm::SourceMgr::DiagHandlerTy DiagHandler,1117void *DiagHandlerCtxt) {1118YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt);1119return C.convertModule();1120}11211122/// Simple diagnostic handler that prints diagnostics to standard error.1123static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) {1124Diag.print(nullptr, llvm::errs());1125}11261127bool api_notes::compileAPINotes(StringRef YAMLInput,1128const FileEntry *SourceFile,1129llvm::raw_ostream &OS,1130llvm::SourceMgr::DiagHandlerTy DiagHandler,1131void *DiagHandlerCtxt) {1132Module TheModule;11331134if (!DiagHandler)1135DiagHandler = &printDiagnostic;11361137if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt))1138return true;11391140return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt);1141}114211431144