aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp41
1 files changed, 39 insertions, 2 deletions
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) {