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 | 7ab142b55a6efedfeedfb54aae85878509cc82d1 (patch) | |
tree | d46fb848d43338e23796c1b4f1ed08879652d942 /clang/lib | |
parent | 785359525354436f91455f7d5bf5cbe36bdbd227 (diff) | |
download | bcm5719-llvm-7ab142b55a6efedfeedfb54aae85878509cc82d1.tar.gz bcm5719-llvm-7ab142b55a6efedfeedfb54aae85878509cc82d1.zip |
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.
llvm-svn: 128329
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 4 |
4 files changed, 54 insertions, 3 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 0e871ecc4c1..c081b0d4a93 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 976e60f0c93..d553687837e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 4cdf2deec34..5bf0abd6b78 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/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/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 81bf230f942..6d1a4c86f28 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/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) { |