diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-03-26 03:35:55 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-03-26 03:35:55 +0000 |
commit | b53e417ba487f4193ef3b0485b420e0fdae643a2 (patch) | |
tree | 14884ffa641989b6851088b555f1dd03b42331b4 /lib | |
parent | 2234873111009eb8655d63362cedc422eb9fc517 (diff) |
Extend the new 'availability' attribute with support for an
'unavailable' argument, which specifies that the declaration to which
the attribute appertains is unavailable on that platform.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128329 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclBase.cpp | 11 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 41 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 4 |
4 files changed, 54 insertions, 3 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 0e871ecc4c..c081b0d4a9 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -268,6 +268,17 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, if (A->getPlatform()->getName() != TargetPlatform) return AR_Available; + // Make sure that this declaration has not been marked 'unavailable'. + if (A->getUnavailable()) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "not available on " << PrettyPlatformName; + } + + return AR_Unavailable; + } + // Make sure that this declaration has already been introduced. if (!A->getIntroduced().empty() && TargetMinVersion < A->getIntroduced()) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 976e60f0c9..d553687837 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -484,6 +484,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { /// 'introduced' '=' version /// 'deprecated' '=' version /// 'removed' = version +/// 'unavailable' void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation AvailabilityLoc, ParsedAttributes &attrs, @@ -521,9 +522,11 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, Ident_introduced = PP.getIdentifierInfo("introduced"); Ident_deprecated = PP.getIdentifierInfo("deprecated"); Ident_obsoleted = PP.getIdentifierInfo("obsoleted"); + Ident_unavailable = PP.getIdentifierInfo("unavailable"); } // Parse the set of introductions/deprecations/removals. + SourceLocation UnavailableLoc; do { if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_availability_expected_change); @@ -533,6 +536,20 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, IdentifierInfo *Keyword = Tok.getIdentifierInfo(); SourceLocation KeywordLoc = ConsumeToken(); + if (Keyword == Ident_unavailable) { + if (UnavailableLoc.isValid()) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword << SourceRange(UnavailableLoc); + } + UnavailableLoc = KeywordLoc; + + if (Tok.isNot(tok::comma)) + break; + + ConsumeToken(); + continue; + } + if (Tok.isNot(tok::equal)) { Diag(Tok, diag::err_expected_equal_after) << Keyword; @@ -589,13 +606,33 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, if (endLoc) *endLoc = RParenLoc; + // The 'unavailable' availability cannot be combined with any other + // availability changes. Make sure that hasn't happened. + if (UnavailableLoc.isValid()) { + bool Complained = false; + for (unsigned Index = Introduced; Index != Unknown; ++Index) { + if (Changes[Index].KeywordLoc.isValid()) { + if (!Complained) { + Diag(UnavailableLoc, diag::warn_availability_and_unavailable) + << SourceRange(Changes[Index].KeywordLoc, + Changes[Index].VersionRange.getEnd()); + Complained = true; + } + + // Clear out the availability. + Changes[Index] = AvailabilityChange(); + } + } + } + // Record this attribute - attrs.addNew(&Availability, AvailabilityLoc, + attrs.addNew(&Availability, AvailabilityLoc, 0, SourceLocation(), Platform, PlatformLoc, Changes[Introduced], Changes[Deprecated], - Changes[Obsoleted], false, false); + Changes[Obsoleted], + UnavailableLoc, false, false); } void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4cdf2deec3..5bf0abd6b7 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -426,6 +426,7 @@ void Parser::Initialize() { Ident_introduced = 0; Ident_deprecated = 0; Ident_obsoleted = 0; + Ident_unavailable = 0; } /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 81bf230f94..6d1a4c86f2 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1091,6 +1091,7 @@ static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); + bool IsUnavailable = Attr.getUnavailableLoc().isValid(); // Ensure that Introduced < Deprecated < Obsoleted (although not all // of these steps are needed). @@ -1122,7 +1123,8 @@ static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, Platform, Introduced.Version, Deprecated.Version, - Obsoleted.Version)); + Obsoleted.Version, + IsUnavailable)); } static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { |