2007-06-09 11:39:29 +08:00
|
|
|
//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-06-09 11:39:29 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines the AttributeList class implementation
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-08-21 02:27:03 +08:00
|
|
|
#include "clang/Sema/AttributeList.h"
|
2012-07-05 01:04:04 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2011-03-24 19:26:52 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-04-12 02:48:18 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2012-05-04 02:27:39 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2007-06-09 11:39:29 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2011-03-24 19:26:52 +08:00
|
|
|
size_t AttributeList::allocated_size() const {
|
|
|
|
if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
|
2012-08-17 08:08:38 +08:00
|
|
|
else if (IsTypeTagForDatatype)
|
|
|
|
return AttributeFactory::TypeTagForDatatypeAllocSize;
|
2011-03-24 19:26:52 +08:00
|
|
|
return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeFactory::AttributeFactory() {
|
|
|
|
// Go ahead and configure all the inline capacity. This is just a memset.
|
|
|
|
FreeLists.resize(InlineFreeListsCapacity);
|
|
|
|
}
|
|
|
|
AttributeFactory::~AttributeFactory() {}
|
|
|
|
|
|
|
|
static size_t getFreeListIndexForSize(size_t size) {
|
|
|
|
assert(size >= sizeof(AttributeList));
|
|
|
|
assert((size % sizeof(void*)) == 0);
|
|
|
|
return ((size - sizeof(AttributeList)) / sizeof(void*));
|
|
|
|
}
|
|
|
|
|
|
|
|
void *AttributeFactory::allocate(size_t size) {
|
|
|
|
// Check for a previously reclaimed attribute.
|
|
|
|
size_t index = getFreeListIndexForSize(size);
|
|
|
|
if (index < FreeLists.size()) {
|
|
|
|
if (AttributeList *attr = FreeLists[index]) {
|
|
|
|
FreeLists[index] = attr->NextInPool;
|
|
|
|
return attr;
|
|
|
|
}
|
2009-02-19 14:25:12 +08:00
|
|
|
}
|
2011-03-24 19:26:52 +08:00
|
|
|
|
|
|
|
// Otherwise, allocate something new.
|
|
|
|
return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttributeFactory::reclaimPool(AttributeList *cur) {
|
|
|
|
assert(cur && "reclaiming empty pool!");
|
|
|
|
do {
|
|
|
|
// Read this here, because we're going to overwrite NextInPool
|
|
|
|
// when we toss 'cur' into the appropriate queue.
|
|
|
|
AttributeList *next = cur->NextInPool;
|
|
|
|
|
|
|
|
size_t size = cur->allocated_size();
|
|
|
|
size_t freeListIndex = getFreeListIndexForSize(size);
|
|
|
|
|
|
|
|
// Expand FreeLists to the appropriate size, if required.
|
|
|
|
if (freeListIndex >= FreeLists.size())
|
|
|
|
FreeLists.resize(freeListIndex+1);
|
|
|
|
|
|
|
|
// Add 'cur' to the appropriate free-list.
|
|
|
|
cur->NextInPool = FreeLists[freeListIndex];
|
|
|
|
FreeLists[freeListIndex] = cur;
|
|
|
|
|
|
|
|
cur = next;
|
|
|
|
} while (cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttributePool::takePool(AttributeList *pool) {
|
|
|
|
assert(pool);
|
|
|
|
|
|
|
|
// Fast path: this pool is empty.
|
|
|
|
if (!Head) {
|
|
|
|
Head = pool;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reverse the pool onto the current head. This optimizes for the
|
|
|
|
// pattern of pulling a lot of pools into a single pool.
|
|
|
|
do {
|
|
|
|
AttributeList *next = pool->NextInPool;
|
|
|
|
pool->NextInPool = Head;
|
|
|
|
Head = pool;
|
|
|
|
pool = next;
|
|
|
|
} while (pool);
|
2007-06-09 11:39:29 +08:00
|
|
|
}
|
2008-02-21 07:14:47 +08:00
|
|
|
|
2011-03-24 19:26:52 +08:00
|
|
|
AttributeList *
|
|
|
|
AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
|
|
|
|
SourceLocation TokLoc, int Arg) {
|
|
|
|
Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
|
|
|
|
C.IntTy, TokLoc);
|
2012-06-19 00:13:52 +08:00
|
|
|
return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1,
|
|
|
|
AttributeList::AS_GNU);
|
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.
llvm-svn: 128127
2011-03-23 08:50:03 +08:00
|
|
|
}
|
|
|
|
|
2012-05-03 01:33:51 +08:00
|
|
|
#include "clang/Sema/AttrParsedAttrKinds.inc"
|
|
|
|
|
2012-05-04 02:27:39 +08:00
|
|
|
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
|
2012-06-19 00:13:52 +08:00
|
|
|
const IdentifierInfo *ScopeName,
|
|
|
|
Syntax SyntaxUsed) {
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef AttrName = Name->getName();
|
2008-02-21 07:14:47 +08:00
|
|
|
|
|
|
|
// Normalize the attribute name, __foo__ becomes foo.
|
2012-02-25 18:41:10 +08:00
|
|
|
if (AttrName.startswith("__") && AttrName.endswith("__") &&
|
|
|
|
AttrName.size() >= 4)
|
2009-10-18 02:12:29 +08:00
|
|
|
AttrName = AttrName.substr(2, AttrName.size() - 4);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-05-04 02:27:39 +08:00
|
|
|
SmallString<64> Buf;
|
|
|
|
if (ScopeName)
|
2012-06-19 00:13:52 +08:00
|
|
|
Buf += ScopeName->getName();
|
|
|
|
// Ensure that in the case of C++11 attributes, we look for '::foo' if it is
|
|
|
|
// unscoped.
|
|
|
|
if (ScopeName || SyntaxUsed == AS_CXX11)
|
|
|
|
Buf += "::";
|
|
|
|
Buf += AttrName;
|
|
|
|
|
|
|
|
return ::getAttrKind(Buf);
|
2008-02-21 07:14:47 +08:00
|
|
|
}
|
2013-01-25 00:46:58 +08:00
|
|
|
|
|
|
|
unsigned AttributeList::getAttributeSpellingListIndex() const {
|
|
|
|
// Both variables will be used in tablegen generated
|
|
|
|
// attribute spell list index matching code.
|
|
|
|
StringRef Name = AttrName->getName();
|
|
|
|
StringRef Scope = ScopeName ? ScopeName->getName() : "";
|
|
|
|
|
|
|
|
#include "clang/Sema/AttrSpellingListIndex.inc"
|
|
|
|
|
|
|
|
}
|
|
|
|
|