[cfe-commits] r128329 - in /cfe/trunk: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h include/clang/Sema/AttributeList.h lib/AST/DeclBase.cpp lib/Parse/ParseDecl.cpp lib/Parse/Parser.cpp lib/Sema/SemaDeclAttr.cpp test/Parser/attr-availability.c test/Sema/attr-availability-macosx.c
Douglas Gregor
dgregor at apple.com
Fri Mar 25 20:35:55 PDT 2011
Author: dgregor
Date: Fri Mar 25 22:35:55 2011
New Revision: 128329
URL: http://llvm.org/viewvc/llvm-project?rev=128329&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/Parser/attr-availability.c
cfe/trunk/test/Sema/attr-availability-macosx.c
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Mar 25 22:35:55 2011
@@ -46,6 +46,7 @@
string Name = name;
}
+class BoolArgument<string name> : Argument<name>;
class IdentifierArgument<string name> : Argument<name>;
class IntArgument<string name> : Argument<name>;
class StringArgument<string name> : Argument<name>;
@@ -140,7 +141,8 @@
def Availability : InheritableAttr {
let Spellings = ["availability"];
let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">,
- VersionArgument<"deprecated">, VersionArgument<"obsoleted">];
+ VersionArgument<"deprecated">, VersionArgument<"obsoleted">,
+ BoolArgument<"unavailable">];
let AdditionalMembers =
[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) {
return llvm::StringSwitch<llvm::StringRef>(Platform)
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Mar 25 22:35:55 2011
@@ -445,6 +445,8 @@
"'obsoleted'">;
def err_availability_redundant : Error<
"redundant %0 availability change; only the last specified change will " "be used">;
+def warn_availability_and_unavailable : Warning<
+ "'unavailable' availability overrides all other availability information">;
// Language specific pragmas
// - Generic warnings
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Mar 25 22:35:55 2011
@@ -121,6 +121,9 @@
/// \brief Identifier for "obsoleted".
IdentifierInfo *Ident_obsoleted;
+ /// \brief Identifier for "unavailable".
+ IdentifierInfo *Ident_unavailable;
+
/// C++0x contextual keywords.
mutable IdentifierInfo *Ident_final;
mutable IdentifierInfo *Ident_override;
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Fri Mar 25 22:35:55 2011
@@ -62,20 +62,24 @@
/// The number of expression arguments this attribute has.
/// The expressions themselves are stored after the object.
- unsigned NumArgs;
+ unsigned NumArgs : 16;
/// True if Microsoft style: declspec(foo).
- bool DeclspecAttribute;
+ unsigned DeclspecAttribute : 1;
/// True if C++0x-style: [[foo]].
- bool CXX0XAttribute;
+ unsigned CXX0XAttribute : 1;
/// True if already diagnosed as invalid.
- mutable bool Invalid;
+ mutable unsigned Invalid : 1;
/// True if this has the extra information associated with an
/// availability attribute.
- bool IsAvailability;
+ unsigned IsAvailability : 1;
+
+ /// \brief The location of the 'unavailable' keyword in an
+ /// availability attribute.
+ SourceLocation UnavailableLoc;
/// The next attribute in the current position.
AttributeList *NextInPosition;
@@ -127,11 +131,13 @@
const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
+ SourceLocation unavailable,
bool declspec, bool cxx0x)
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
- Invalid(false), IsAvailability(true), NextInPosition(0), NextInPool(0) {
+ Invalid(false), IsAvailability(true), UnavailableLoc(unavailable),
+ NextInPosition(0), NextInPool(0) {
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
@@ -315,6 +321,11 @@
assert(getKind() == AT_availability && "Not an availability attribute");
return getAvailabilitySlot(ObsoletedSlot);
}
+
+ SourceLocation getUnavailableLoc() const {
+ assert(getKind() == AT_availability && "Not an availability attribute");
+ return UnavailableLoc;
+ }
};
/// A factory, from which one makes pools, from which one creates
@@ -435,12 +446,14 @@
const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
+ SourceLocation unavailable,
bool declspec = false, bool cxx0x = false) {
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
return add(new (memory) AttributeList(attrName, attrLoc,
scopeName, scopeLoc,
parmName, parmLoc,
introduced, deprecated, obsoleted,
+ unavailable,
declspec, cxx0x));
}
@@ -557,10 +570,12 @@
const AvailabilityChange &introduced,
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted,
+ SourceLocation unavailable,
bool declspec = false, bool cxx0x = false) {
AttributeList *attr =
pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc,
- introduced, deprecated, obsoleted, declspec, cxx0x);
+ introduced, deprecated, obsoleted, unavailable,
+ declspec, cxx0x);
add(attr);
return attr;
}
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Mar 25 22:35:55 2011
@@ -268,6 +268,17 @@
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()) {
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Mar 25 22:35:55 2011
@@ -484,6 +484,7 @@
/// 'introduced' '=' version
/// 'deprecated' '=' version
/// 'removed' = version
+/// 'unavailable'
void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
SourceLocation AvailabilityLoc,
ParsedAttributes &attrs,
@@ -521,9 +522,11 @@
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 @@
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 @@
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) {
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri Mar 25 22:35:55 2011
@@ -426,6 +426,7 @@
Ident_introduced = 0;
Ident_deprecated = 0;
Ident_obsoleted = 0;
+ Ident_unavailable = 0;
}
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Mar 25 22:35:55 2011
@@ -1091,6 +1091,7 @@
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 @@
Platform,
Introduced.Version,
Deprecated.Version,
- Obsoleted.Version));
+ Obsoleted.Version,
+ IsUnavailable));
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Modified: cfe/trunk/test/Parser/attr-availability.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/attr-availability.c?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/test/Parser/attr-availability.c (original)
+++ cfe/trunk/test/Parser/attr-availability.c Fri Mar 25 22:35:55 2011
@@ -7,3 +7,9 @@
void f3() __attribute__((availability(ios,deprecated=10.4.7,introduced=10,obsoleted=10.6,introduced=10.2))); // expected-error{{redundant 'introduced' availability change; only the last specified change will be used}}
+void f4() __attribute__((availability(macosx,introduced=10.5), availability(ios,unavailable)));
+
+void f5() __attribute__((availability(macosx,introduced=10.5), availability(ios,unavailable, unavailable))); // expected-error{{redundant 'unavailable' availability change; only the last specified change will be used}}
+
+void f6() __attribute__((availability(macosx,unavailable,introduced=10.5))); // expected-warning{{warning: 'unavailable' availability overrides all other availability information}}
+
Modified: cfe/trunk/test/Sema/attr-availability-macosx.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-availability-macosx.c?rev=128329&r1=128328&r2=128329&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-availability-macosx.c (original)
+++ cfe/trunk/test/Sema/attr-availability-macosx.c Fri Mar 25 22:35:55 2011
@@ -5,6 +5,7 @@
void f2(int) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5)));
void f3(int) __attribute__((availability(macosx,introduced=10.6)));
void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3,obsoleted=10.5), availability(ios,introduced=2.0,deprecated=3.0))); // expected-note{{explicitly marked unavailable}}
+void f5(int) __attribute__((availability(ios,introduced=3.2), availability(macosx,unavailable))); // expected-note{{function has been explicitly marked unavailable here}}
void test() {
f0(0);
@@ -12,4 +13,5 @@
f2(0); // expected-warning{{'f2' is deprecated: first deprecated in Mac OS X 10.5}}
f3(0);
f4(0); // expected-error{{f4' is unavailable: obsoleted in Mac OS X 10.5}}
+ f5(0); // expected-error{{'f5' is unavailable: not available on Mac OS X}}
}
More information about the cfe-commits
mailing list