diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-03-23 00:50:03 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-03-23 00:50:03 +0000 |
commit | 0a0d2b179085a52c10402feebeb6db8b4d96a140 (patch) | |
tree | e97aeca336472a81235e8bd034f648b034094e81 /include/clang/Sema/AttributeList.h | |
parent | 9a8ad9b28d54a3adc4cb8061d564f99f80144e30 (diff) |
Implement a new 'availability' attribute, that allows one to specify
which versions of an OS provide a certain facility. For example,
void foo()
__attribute__((availability(macosx,introduced=10.2,deprecated=10.4,obsoleted=10.6)));
says that the function "foo" was introduced in 10.2, deprecated in
10.4, and completely obsoleted in 10.6. This attribute ties in with
the deployment targets (e.g., -mmacosx-version-min=10.1 specifies that
we want to deploy back to Mac OS X 10.1). There are several concrete
behaviors that this attribute enables, as illustrated with the
function foo() above:
- If we choose a deployment target >= Mac OS X 10.4, uses of "foo"
will result in a deprecation warning, as if we had placed
attribute((deprecated)) on it (but with a better diagnostic)
- If we choose a deployment target >= Mac OS X 10.6, uses of "foo"
will result in an "unavailable" warning (in C)/error (in C++), as
if we had placed attribute((unavailable)) on it
- If we choose a deployment target prior to 10.2, foo() is
weak-imported (if it is a kind of entity that can be weak
imported), as if we had placed the weak_import attribute on it.
Naturally, there can be multiple availability attributes on a
declaration, for different platforms; only the current platform
matters when checking availability attributes.
The only platforms this attribute currently works for are "ios" and
"macosx", since we already have -mxxxx-version-min flags for them and we
have experience there with macro tricks translating down to the
deprecated/unavailable/weak_import attributes. The end goal is to open
this up to other platforms, and even extension to other "platforms"
that are really libraries (say, through a #pragma clang
define_system), but that hasn't yet been designed and we may want to
shake out more issues with this narrower problem first.
Addresses <rdar://problem/6690412>.
As a drive-by bug-fix, if an entity is both deprecated and
unavailable, we only emit the "unavailable" diagnostic.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128127 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Sema/AttributeList.h')
-rw-r--r-- | include/clang/Sema/AttributeList.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 382e50494e..3657b44b02 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -18,6 +18,7 @@ #include "llvm/Support/Allocator.h" #include "clang/Sema/Ownership.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" #include "clang/AST/Expr.h" #include <cassert> @@ -25,6 +26,23 @@ namespace clang { class IdentifierInfo; class Expr; +/// \brief Represents information about a change in availability for +/// an entity, which is part of the encoding of the 'availability' +/// attribute. +struct AvailabilityChange { + /// \brief The location of the keyword indicating the kind of change. + SourceLocation KeywordLoc; + + /// \brief The version number at which the change occurred. + VersionTuple Version; + + /// \brief The source range covering the version number. + SourceRange VersionRange; + + /// \brief Determine whether this availability change is valid. + bool isValid() const { return !Version.empty(); } +}; + /// AttributeList - Represents GCC's __attribute__ declaration. There are /// 4 forms of this construct...they are: /// @@ -48,6 +66,11 @@ private: AttributeList *Next; bool DeclspecAttribute, CXX0XAttribute; + // For the 'availability' attribute. + AvailabilityChange AvailabilityIntroduced; + AvailabilityChange AvailabilityDeprecated; + AvailabilityChange AvailabilityObsoleted; + /// True if already diagnosed as invalid. mutable bool Invalid; @@ -61,6 +84,15 @@ private: IdentifierInfo *ParmName, SourceLocation ParmLoc, Expr **args, unsigned numargs, bool declspec, bool cxx0x); + + AttributeList(llvm::BumpPtrAllocator &Alloc, + IdentifierInfo *AttrName, SourceLocation AttrLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + IdentifierInfo *ParmName, SourceLocation ParmLoc, + const AvailabilityChange &Introduced, + const AvailabilityChange &Deprecated, + const AvailabilityChange &Obsoleted, + bool declspec, bool cxx0x); public: class Factory { llvm::BumpPtrAllocator Alloc; @@ -78,6 +110,20 @@ public: return Mem; } + AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + IdentifierInfo *ParmName, SourceLocation ParmLoc, + const AvailabilityChange &Introduced, + const AvailabilityChange &Deprecated, + const AvailabilityChange &Obsoleted, + bool declspec = false, bool cxx0x = false) { + AttributeList *Mem = Alloc.Allocate<AttributeList>(); + new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc, + ParmName, ParmLoc, Introduced, Deprecated, + Obsoleted, declspec, cxx0x); + return Mem; + } + AttributeList* CreateIntegerAttribute(ASTContext &C, IdentifierInfo *Name, SourceLocation TokLoc, int Arg) { Expr* IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t)Arg), @@ -96,6 +142,7 @@ public: AT_always_inline, AT_analyzer_noreturn, AT_annotate, + AT_availability, // Clang-specific AT_base_check, AT_blocks, AT_carries_dependency, @@ -244,6 +291,21 @@ public: arg_iterator arg_end() const { return arg_iterator(Args, NumArgs); } + + const AvailabilityChange &getAvailabilityIntroduced() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return AvailabilityIntroduced; + } + + const AvailabilityChange &getAvailabilityDeprecated() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return AvailabilityDeprecated; + } + + const AvailabilityChange &getAvailabilityObsoleted() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return AvailabilityObsoleted; + } }; /// addAttributeLists - Add two AttributeLists together |