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 
18 namespace clang {
19 namespace api_notes {
20 enum 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.
31 enum class EnumExtensibilityKind {
32   None,
33   Open,
34   Closed,
35 };
36 
37 /// The kind of a swift_wrapper/swift_newtype.
38 enum 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.
47 class CommonEntityInfo {
48 public:
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 
58 private:
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 
65 public:
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 ? *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 
111 inline 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 
120 inline bool operator!=(const CommonEntityInfo &LHS,
121                        const CommonEntityInfo &RHS) {
122   return !(LHS == RHS);
123 }
124 
125 /// Describes API notes for types.
126 class 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 
135 public:
136   CommonTypeInfo() {}
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 
182 inline 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 
188 inline 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.
193 class 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 
209 public:
210   ObjCContextInfo()
211       : HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0),
212         SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false),
213         SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {}
214 
215   /// Determine the default nullability for properties and methods of this
216   /// class.
217   ///
218   /// eturns the default nullability, if implied, or None if there is no
219   llvm::Optional<NullabilityKind> getDefaultNullability() const {
220     return HasDefaultNullability
221                ? llvm::Optional<NullabilityKind>(
222                      static_cast<NullabilityKind>(DefaultNullability))
223                : llvm::None;
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   llvm::Optional<bool> getSwiftImportAsNonGeneric() const {
236     return SwiftImportAsNonGenericSpecified
237                ? llvm::Optional<bool>(SwiftImportAsNonGeneric)
238                : llvm::None;
239   }
240   void setSwiftImportAsNonGeneric(llvm::Optional<bool> Value) {
241     SwiftImportAsNonGenericSpecified = Value.has_value();
242     SwiftImportAsNonGeneric = Value.value_or(false);
243   }
244 
245   llvm::Optional<bool> getSwiftObjCMembers() const {
246     return SwiftObjCMembersSpecified ? llvm::Optional<bool>(SwiftObjCMembers)
247                                      : llvm::None;
248   }
249   void setSwiftObjCMembers(llvm::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 
286 inline 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 
294 inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) {
295   return !(LHS == RHS);
296 }
297 
298 /// API notes for a variable/property.
299 class 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 
310 public:
311   VariableInfo() : NullabilityAudited(false), Nullable(0) {}
312 
313   llvm::Optional<NullabilityKind> getNullability() const {
314     return NullabilityAudited ? llvm::Optional<NullabilityKind>(
315                                     static_cast<NullabilityKind>(Nullable))
316                               : llvm::None;
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 
343 inline 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 
349 inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) {
350   return !(LHS == RHS);
351 }
352 
353 /// Describes API notes data for an Objective-C property.
354 class ObjCPropertyInfo : public VariableInfo {
355   unsigned SwiftImportAsAccessorsSpecified : 1;
356   unsigned SwiftImportAsAccessors : 1;
357 
358 public:
359   ObjCPropertyInfo()
360       : SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
361 
362   llvm::Optional<bool> getSwiftImportAsAccessors() const {
363     return SwiftImportAsAccessorsSpecified
364                ? llvm::Optional<bool>(SwiftImportAsAccessors)
365                : llvm::None;
366   }
367   void setSwiftImportAsAccessors(llvm::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 
398 inline bool operator==(const ObjCPropertyInfo &LHS,
399                        const ObjCPropertyInfo &RHS) {
400   return static_cast<const VariableInfo &>(LHS) == RHS &&
401          LHS.getSwiftImportAsAccessors() == RHS.getSwiftImportAsAccessors();
402 }
403 
404 inline bool operator!=(const ObjCPropertyInfo &LHS,
405                        const ObjCPropertyInfo &RHS) {
406   return !(LHS == RHS);
407 }
408 
409 /// Describes a function or method parameter.
410 class 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 
422 public:
423   ParamInfo()
424       : NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {}
425 
426   llvm::Optional<bool> isNoEscape() const {
427     if (!NoEscapeSpecified)
428       return llvm::None;
429     return NoEscape;
430   }
431   void setNoEscape(llvm::Optional<bool> Value) {
432     NoEscapeSpecified = Value.has_value();
433     NoEscape = Value.value_or(false);
434   }
435 
436   llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
437     if (!RawRetainCountConvention)
438       return llvm::None;
439     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
440   }
441   void
442   setRetainCountConvention(llvm::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 
466 inline 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 
473 inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
474   return !(LHS == RHS);
475 }
476 
477 /// API notes for a function or method.
478 class FunctionInfo : public CommonEntityInfo {
479 private:
480   static constexpr const unsigned NullabilityKindMask = 0x3;
481   static constexpr const unsigned NullabilityKindSize = 2;
482 
483   static constexpr const unsigned ReturnInfoIndex = 0;
484 
485 public:
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   llvm::Optional<RetainCountConventionKind> getRetainCountConvention() const {
555     if (!RawRetainCountConvention)
556       return llvm::None;
557     return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
558   }
559   void
560   setRetainCountConvention(llvm::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 
567 private:
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 
579 public:
580   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
581 };
582 
583 inline 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 
592 inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
593   return !(LHS == RHS);
594 }
595 
596 /// Describes API notes data for an Objective-C method.
597 class ObjCMethodInfo : public FunctionInfo {
598 public:
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 
623 inline 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 
629 inline bool operator!=(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
630   return !(LHS == RHS);
631 }
632 
633 /// Describes API notes data for a global variable.
634 class GlobalVariableInfo : public VariableInfo {
635 public:
636   GlobalVariableInfo() {}
637 };
638 
639 /// Describes API notes data for a global function.
640 class GlobalFunctionInfo : public FunctionInfo {
641 public:
642   GlobalFunctionInfo() {}
643 };
644 
645 /// Describes API notes data for an enumerator.
646 class EnumConstantInfo : public CommonEntityInfo {
647 public:
648   EnumConstantInfo() {}
649 };
650 
651 /// Describes API notes data for a tag.
652 class TagInfo : public CommonTypeInfo {
653   unsigned HasFlagEnum : 1;
654   unsigned IsFlagEnum : 1;
655 
656 public:
657   llvm::Optional<EnumExtensibilityKind> EnumExtensibility;
658 
659   TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
660 
661   llvm::Optional<bool> isFlagEnum() const {
662     if (HasFlagEnum)
663       return IsFlagEnum;
664     return llvm::None;
665   }
666   void setFlagEnum(llvm::Optional<bool> Value) {
667     HasFlagEnum = Value.has_value();
668     IsFlagEnum = Value.value_or(false);
669   }
670 
671   TagInfo &operator|=(const TagInfo &RHS) {
672     static_cast<CommonTypeInfo &>(*this) |= RHS;
673 
674     if (!HasFlagEnum)
675       setFlagEnum(RHS.isFlagEnum());
676 
677     if (!EnumExtensibility)
678       EnumExtensibility = RHS.EnumExtensibility;
679 
680     return *this;
681   }
682 
683   friend bool operator==(const TagInfo &, const TagInfo &);
684 
685   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
686 };
687 
688 inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
689   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
690          LHS.isFlagEnum() == RHS.isFlagEnum() &&
691          LHS.EnumExtensibility == RHS.EnumExtensibility;
692 }
693 
694 inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
695   return !(LHS == RHS);
696 }
697 
698 /// Describes API notes data for a typedef.
699 class TypedefInfo : public CommonTypeInfo {
700 public:
701   llvm::Optional<SwiftNewTypeKind> SwiftWrapper;
702 
703   TypedefInfo() {}
704 
705   TypedefInfo &operator|=(const TypedefInfo &RHS) {
706     static_cast<CommonTypeInfo &>(*this) |= RHS;
707     if (!SwiftWrapper)
708       SwiftWrapper = RHS.SwiftWrapper;
709     return *this;
710   }
711 
712   friend bool operator==(const TypedefInfo &, const TypedefInfo &);
713 
714   LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
715 };
716 
717 inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) {
718   return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
719          LHS.SwiftWrapper == RHS.SwiftWrapper;
720 }
721 
722 inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) {
723   return !(LHS == RHS);
724 }
725 } // namespace api_notes
726 } // namespace clang
727 
728 #endif
729