1 | //===--- Availability.h - Classes for availability --------------*- 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 | // This files defines some classes that implement availability checking. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_AST_AVAILABILITY_H |
14 | #define LLVM_CLANG_AST_AVAILABILITY_H |
15 | |
16 | #include "clang/Basic/SourceLocation.h" |
17 | #include "llvm/ADT/SmallString.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/Support/VersionTuple.h" |
20 | |
21 | namespace clang { |
22 | |
23 | /// One specifier in an @available expression. |
24 | /// |
25 | /// \code |
26 | /// @available(macos 10.10, *) |
27 | /// \endcode |
28 | /// |
29 | /// Here, 'macos 10.10' and '*' both map to an instance of this type. |
30 | /// |
31 | class AvailabilitySpec { |
32 | /// Represents the version that this specifier requires. If the host OS |
33 | /// version is greater than or equal to Version, the @available will evaluate |
34 | /// to true. |
35 | VersionTuple Version; |
36 | |
37 | /// Name of the platform that Version corresponds to. |
38 | StringRef Platform; |
39 | |
40 | SourceLocation BeginLoc, EndLoc; |
41 | |
42 | public: |
43 | AvailabilitySpec(VersionTuple Version, StringRef Platform, |
44 | SourceLocation BeginLoc, SourceLocation EndLoc) |
45 | : Version(Version), Platform(Platform), BeginLoc(BeginLoc), |
46 | EndLoc(EndLoc) {} |
47 | |
48 | /// This constructor is used when representing the '*' case. |
49 | AvailabilitySpec(SourceLocation StarLoc) |
50 | : BeginLoc(StarLoc), EndLoc(StarLoc) {} |
51 | |
52 | VersionTuple getVersion() const { return Version; } |
53 | StringRef getPlatform() const { return Platform; } |
54 | SourceLocation getBeginLoc() const { return BeginLoc; } |
55 | SourceLocation getEndLoc() const { return EndLoc; } |
56 | |
57 | /// Returns true when this represents the '*' case. |
58 | bool isOtherPlatformSpec() const { return Version.empty(); } |
59 | }; |
60 | |
61 | class Decl; |
62 | |
63 | /// Storage of availability attributes for a declaration. |
64 | struct AvailabilityInfo { |
65 | /// The domain is the platform for which this availability info applies to. |
66 | llvm::SmallString<32> Domain; |
67 | VersionTuple Introduced; |
68 | VersionTuple Deprecated; |
69 | VersionTuple Obsoleted; |
70 | bool Unavailable = false; |
71 | bool UnconditionallyDeprecated = false; |
72 | bool UnconditionallyUnavailable = false; |
73 | |
74 | AvailabilityInfo() = default; |
75 | |
76 | /// Determine if this AvailabilityInfo represents the default availability. |
77 | bool isDefault() const { return *this == AvailabilityInfo(); } |
78 | |
79 | /// Check if the symbol has been obsoleted. |
80 | bool isObsoleted() const { return !Obsoleted.empty(); } |
81 | |
82 | /// Check if the symbol is unavailable unconditionally or |
83 | /// on the active platform and os version. |
84 | bool isUnavailable() const { |
85 | return Unavailable || isUnconditionallyUnavailable(); |
86 | } |
87 | |
88 | /// Check if the symbol is unconditionally deprecated. |
89 | /// |
90 | /// i.e. \code __attribute__((deprecated)) \endcode |
91 | bool isUnconditionallyDeprecated() const { return UnconditionallyDeprecated; } |
92 | |
93 | /// Check if the symbol is unconditionally unavailable. |
94 | /// |
95 | /// i.e. \code __attribute__((unavailable)) \endcode |
96 | bool isUnconditionallyUnavailable() const { |
97 | return UnconditionallyUnavailable; |
98 | } |
99 | |
100 | AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, |
101 | VersionTuple O, bool U, bool UD, bool UU) |
102 | : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), |
103 | Unavailable(U), UnconditionallyDeprecated(UD), |
104 | UnconditionallyUnavailable(UU) {} |
105 | |
106 | friend bool operator==(const AvailabilityInfo &Lhs, |
107 | const AvailabilityInfo &Rhs); |
108 | |
109 | public: |
110 | static AvailabilityInfo createFromDecl(const Decl *Decl); |
111 | }; |
112 | |
113 | inline bool operator==(const AvailabilityInfo &Lhs, |
114 | const AvailabilityInfo &Rhs) { |
115 | return std::tie(args: Lhs.Introduced, args: Lhs.Deprecated, args: Lhs.Obsoleted, |
116 | args: Lhs.Unavailable, args: Lhs.UnconditionallyDeprecated, |
117 | args: Lhs.UnconditionallyUnavailable) == |
118 | std::tie(args: Rhs.Introduced, args: Rhs.Deprecated, args: Rhs.Obsoleted, |
119 | args: Rhs.Unavailable, args: Rhs.UnconditionallyDeprecated, |
120 | args: Rhs.UnconditionallyUnavailable); |
121 | } |
122 | |
123 | } // end namespace clang |
124 | |
125 | #endif |
126 | |