1//===--- AttributeList.cpp --------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the AttributeList class implementation 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Sema/AttributeList.h" 15#include "clang/AST/ASTContext.h" 16#include "clang/AST/Expr.h" 17#include "clang/Basic/IdentifierTable.h" 18#include "llvm/ADT/SmallString.h" 19#include "llvm/ADT/StringSwitch.h" 20using namespace clang; 21 22IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 23 IdentifierInfo *Ident) { 24 IdentifierLoc *Result = new (Ctx) IdentifierLoc; 25 Result->Loc = Loc; 26 Result->Ident = Ident; 27 return Result; 28} 29 30size_t AttributeList::allocated_size() const { 31 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 32 else if (IsTypeTagForDatatype) 33 return AttributeFactory::TypeTagForDatatypeAllocSize; 34 else if (IsProperty) 35 return AttributeFactory::PropertyAllocSize; 36 return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); 37} 38 39AttributeFactory::AttributeFactory() { 40 // Go ahead and configure all the inline capacity. This is just a memset. 41 FreeLists.resize(InlineFreeListsCapacity); 42} 43AttributeFactory::~AttributeFactory() {} 44 45static size_t getFreeListIndexForSize(size_t size) { 46 assert(size >= sizeof(AttributeList)); 47 assert((size % sizeof(void*)) == 0); 48 return ((size - sizeof(AttributeList)) / sizeof(void*)); 49} 50 51void *AttributeFactory::allocate(size_t size) { 52 // Check for a previously reclaimed attribute. 53 size_t index = getFreeListIndexForSize(size); 54 if (index < FreeLists.size()) { 55 if (AttributeList *attr = FreeLists[index]) { 56 FreeLists[index] = attr->NextInPool; 57 return attr; 58 } 59 } 60 61 // Otherwise, allocate something new. 62 return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment); 63} 64 65void AttributeFactory::reclaimPool(AttributeList *cur) { 66 assert(cur && "reclaiming empty pool!"); 67 do { 68 // Read this here, because we're going to overwrite NextInPool 69 // when we toss 'cur' into the appropriate queue. 70 AttributeList *next = cur->NextInPool; 71 72 size_t size = cur->allocated_size(); 73 size_t freeListIndex = getFreeListIndexForSize(size); 74 75 // Expand FreeLists to the appropriate size, if required. 76 if (freeListIndex >= FreeLists.size()) 77 FreeLists.resize(freeListIndex+1); 78 79 // Add 'cur' to the appropriate free-list. 80 cur->NextInPool = FreeLists[freeListIndex]; 81 FreeLists[freeListIndex] = cur; 82 83 cur = next; 84 } while (cur); 85} 86 87void AttributePool::takePool(AttributeList *pool) { 88 assert(pool); 89 90 // Fast path: this pool is empty. 91 if (!Head) { 92 Head = pool; 93 return; 94 } 95 96 // Reverse the pool onto the current head. This optimizes for the 97 // pattern of pulling a lot of pools into a single pool. 98 do { 99 AttributeList *next = pool->NextInPool; 100 pool->NextInPool = Head; 101 Head = pool; 102 pool = next; 103 } while (pool); 104} 105 106AttributeList * 107AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, 108 SourceLocation TokLoc, int Arg) { 109 ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), 110 C.IntTy, TokLoc); 111 return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU); 112} 113 114#include "clang/Sema/AttrParsedAttrKinds.inc" 115 116AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, 117 const IdentifierInfo *ScopeName, 118 Syntax SyntaxUsed) { 119 StringRef AttrName = Name->getName(); 120 121 // Normalize the attribute name, __foo__ becomes foo. 122 if (AttrName.startswith("__") && AttrName.endswith("__") && 123 AttrName.size() >= 4) 124 AttrName = AttrName.substr(2, AttrName.size() - 4); 125 126 SmallString<64> Buf; 127 if (ScopeName) 128 Buf += ScopeName->getName(); 129 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is 130 // unscoped. 131 if (ScopeName || SyntaxUsed == AS_CXX11) 132 Buf += "::"; 133 Buf += AttrName; 134 135 return ::getAttrKind(Buf); 136} 137 138unsigned AttributeList::getAttributeSpellingListIndex() const { 139 // Both variables will be used in tablegen generated 140 // attribute spell list index matching code. 141 StringRef Name = AttrName->getName(); 142 StringRef Scope = ScopeName ? ScopeName->getName() : ""; 143 144#include "clang/Sema/AttrSpellingListIndex.inc" 145 146} 147 148struct ParsedAttrInfo { 149 unsigned NumArgs : 4; 150 unsigned OptArgs : 4; 151 unsigned HasCustomParsing : 1; 152}; 153 154namespace { 155 #include "clang/Sema/AttrParsedAttrImpl.inc" 156} 157 158static const ParsedAttrInfo &getInfo(const AttributeList &A) { 159 return AttrInfoMap[A.getKind()]; 160} 161 162unsigned AttributeList::getMinArgs() const { 163 return getInfo(*this).NumArgs; 164} 165 166unsigned AttributeList::getMaxArgs() const { 167 return getMinArgs() + getInfo(*this).OptArgs; 168} 169 170bool AttributeList::hasCustomParsing() const { 171 return getInfo(*this).HasCustomParsing; 172} 173