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