10b57cec5SDimitry Andric //===--- Availability.h - Classes for availability --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This files defines some classes that implement availability checking. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_AST_AVAILABILITY_H 140b57cec5SDimitry Andric #define LLVM_CLANG_AST_AVAILABILITY_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 17*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallString.h" 180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 190b57cec5SDimitry Andric #include "llvm/Support/VersionTuple.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace clang { 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric /// One specifier in an @available expression. 240b57cec5SDimitry Andric /// 250b57cec5SDimitry Andric /// \code 260b57cec5SDimitry Andric /// @available(macos 10.10, *) 270b57cec5SDimitry Andric /// \endcode 280b57cec5SDimitry Andric /// 290b57cec5SDimitry Andric /// Here, 'macos 10.10' and '*' both map to an instance of this type. 300b57cec5SDimitry Andric /// 310b57cec5SDimitry Andric class AvailabilitySpec { 320b57cec5SDimitry Andric /// Represents the version that this specifier requires. If the host OS 330b57cec5SDimitry Andric /// version is greater than or equal to Version, the @available will evaluate 340b57cec5SDimitry Andric /// to true. 350b57cec5SDimitry Andric VersionTuple Version; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric /// Name of the platform that Version corresponds to. 380b57cec5SDimitry Andric StringRef Platform; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric SourceLocation BeginLoc, EndLoc; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric public: AvailabilitySpec(VersionTuple Version,StringRef Platform,SourceLocation BeginLoc,SourceLocation EndLoc)430b57cec5SDimitry Andric AvailabilitySpec(VersionTuple Version, StringRef Platform, 440b57cec5SDimitry Andric SourceLocation BeginLoc, SourceLocation EndLoc) 450b57cec5SDimitry Andric : Version(Version), Platform(Platform), BeginLoc(BeginLoc), 460b57cec5SDimitry Andric EndLoc(EndLoc) {} 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric /// This constructor is used when representing the '*' case. AvailabilitySpec(SourceLocation StarLoc)490b57cec5SDimitry Andric AvailabilitySpec(SourceLocation StarLoc) 500b57cec5SDimitry Andric : BeginLoc(StarLoc), EndLoc(StarLoc) {} 510b57cec5SDimitry Andric getVersion()520b57cec5SDimitry Andric VersionTuple getVersion() const { return Version; } getPlatform()530b57cec5SDimitry Andric StringRef getPlatform() const { return Platform; } getBeginLoc()540b57cec5SDimitry Andric SourceLocation getBeginLoc() const { return BeginLoc; } getEndLoc()550b57cec5SDimitry Andric SourceLocation getEndLoc() const { return EndLoc; } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// Returns true when this represents the '*' case. isOtherPlatformSpec()580b57cec5SDimitry Andric bool isOtherPlatformSpec() const { return Version.empty(); } 590b57cec5SDimitry Andric }; 600b57cec5SDimitry Andric 61*0fca6ea1SDimitry Andric class Decl; 62*0fca6ea1SDimitry Andric 63*0fca6ea1SDimitry Andric /// Storage of availability attributes for a declaration. 64*0fca6ea1SDimitry Andric struct AvailabilityInfo { 65*0fca6ea1SDimitry Andric /// The domain is the platform for which this availability info applies to. 66*0fca6ea1SDimitry Andric llvm::SmallString<32> Domain; 67*0fca6ea1SDimitry Andric VersionTuple Introduced; 68*0fca6ea1SDimitry Andric VersionTuple Deprecated; 69*0fca6ea1SDimitry Andric VersionTuple Obsoleted; 70*0fca6ea1SDimitry Andric bool Unavailable = false; 71*0fca6ea1SDimitry Andric bool UnconditionallyDeprecated = false; 72*0fca6ea1SDimitry Andric bool UnconditionallyUnavailable = false; 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric AvailabilityInfo() = default; 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric /// Determine if this AvailabilityInfo represents the default availability. isDefaultAvailabilityInfo77*0fca6ea1SDimitry Andric bool isDefault() const { return *this == AvailabilityInfo(); } 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric /// Check if the symbol has been obsoleted. isObsoletedAvailabilityInfo80*0fca6ea1SDimitry Andric bool isObsoleted() const { return !Obsoleted.empty(); } 81*0fca6ea1SDimitry Andric 82*0fca6ea1SDimitry Andric /// Check if the symbol is unavailable unconditionally or 83*0fca6ea1SDimitry Andric /// on the active platform and os version. isUnavailableAvailabilityInfo84*0fca6ea1SDimitry Andric bool isUnavailable() const { 85*0fca6ea1SDimitry Andric return Unavailable || isUnconditionallyUnavailable(); 86*0fca6ea1SDimitry Andric } 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric /// Check if the symbol is unconditionally deprecated. 89*0fca6ea1SDimitry Andric /// 90*0fca6ea1SDimitry Andric /// i.e. \code __attribute__((deprecated)) \endcode isUnconditionallyDeprecatedAvailabilityInfo91*0fca6ea1SDimitry Andric bool isUnconditionallyDeprecated() const { return UnconditionallyDeprecated; } 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric /// Check if the symbol is unconditionally unavailable. 94*0fca6ea1SDimitry Andric /// 95*0fca6ea1SDimitry Andric /// i.e. \code __attribute__((unavailable)) \endcode isUnconditionallyUnavailableAvailabilityInfo96*0fca6ea1SDimitry Andric bool isUnconditionallyUnavailable() const { 97*0fca6ea1SDimitry Andric return UnconditionallyUnavailable; 98*0fca6ea1SDimitry Andric } 99*0fca6ea1SDimitry Andric AvailabilityInfoAvailabilityInfo100*0fca6ea1SDimitry Andric AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, 101*0fca6ea1SDimitry Andric VersionTuple O, bool U, bool UD, bool UU) 102*0fca6ea1SDimitry Andric : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), 103*0fca6ea1SDimitry Andric Unavailable(U), UnconditionallyDeprecated(UD), 104*0fca6ea1SDimitry Andric UnconditionallyUnavailable(UU) {} 105*0fca6ea1SDimitry Andric 106*0fca6ea1SDimitry Andric friend bool operator==(const AvailabilityInfo &Lhs, 107*0fca6ea1SDimitry Andric const AvailabilityInfo &Rhs); 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric public: 110*0fca6ea1SDimitry Andric static AvailabilityInfo createFromDecl(const Decl *Decl); 111*0fca6ea1SDimitry Andric }; 112*0fca6ea1SDimitry Andric 113*0fca6ea1SDimitry Andric inline bool operator==(const AvailabilityInfo &Lhs, 114*0fca6ea1SDimitry Andric const AvailabilityInfo &Rhs) { 115*0fca6ea1SDimitry Andric return std::tie(Lhs.Introduced, Lhs.Deprecated, Lhs.Obsoleted, 116*0fca6ea1SDimitry Andric Lhs.Unavailable, Lhs.UnconditionallyDeprecated, 117*0fca6ea1SDimitry Andric Lhs.UnconditionallyUnavailable) == 118*0fca6ea1SDimitry Andric std::tie(Rhs.Introduced, Rhs.Deprecated, Rhs.Obsoleted, 119*0fca6ea1SDimitry Andric Rhs.Unavailable, Rhs.UnconditionallyDeprecated, 120*0fca6ea1SDimitry Andric Rhs.UnconditionallyUnavailable); 121*0fca6ea1SDimitry Andric } 122*0fca6ea1SDimitry Andric 1230b57cec5SDimitry Andric } // end namespace clang 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric #endif 126