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