llvm-project/clang/lib/Sema/AttributeList.cpp

148 lines
4.6 KiB
C++
Raw Normal View History

//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AttributeList class implementation
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/AttributeList.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
IdentifierInfo *Ident) {
IdentifierLoc *Result = new (Ctx) IdentifierLoc;
Result->Loc = Loc;
Result->Ident = Ident;
return Result;
}
size_t AttributeList::allocated_size() const {
if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
else if (IsTypeTagForDatatype)
return AttributeFactory::TypeTagForDatatypeAllocSize;
else if (IsProperty)
return AttributeFactory::PropertyAllocSize;
return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
}
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;
}
}
// 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);
}
AttributeList *
AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
SourceLocation TokLoc, int Arg) {
ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
C.IntTy, TokLoc);
return create(Name, 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
}
#include "clang/Sema/AttrParsedAttrKinds.inc"
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
const IdentifierInfo *ScopeName,
Syntax SyntaxUsed) {
StringRef AttrName = Name->getName();
// Normalize the attribute name, __foo__ becomes foo.
if (AttrName.startswith("__") && AttrName.endswith("__") &&
AttrName.size() >= 4)
AttrName = AttrName.substr(2, AttrName.size() - 4);
SmallString<64> Buf;
if (ScopeName)
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);
}
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"
}