aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-03-26 03:35:55 +0000
committerDouglas Gregor <dgregor@apple.com>2011-03-26 03:35:55 +0000
commitb53e417ba487f4193ef3b0485b420e0fdae643a2 (patch)
tree14884ffa641989b6851088b555f1dd03b42331b4 /lib
parent2234873111009eb8655d63362cedc422eb9fc517 (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.cpp11
-rw-r--r--lib/Parse/ParseDecl.cpp41
-rw-r--r--lib/Parse/Parser.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp4
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) {