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